diff --git a/.run/ruoyi-monitor-admin.run.xml b/.run/ruoyi-monitor-admin.run.xml index bcac3d594..3c2cc61b6 100644 --- a/.run/ruoyi-monitor-admin.run.xml +++ b/.run/ruoyi-monitor-admin.run.xml @@ -2,7 +2,7 @@ - diff --git a/.run/ruoyi-server.run.xml b/.run/ruoyi-server.run.xml index 57b0fb821..4cfac4f3f 100644 --- a/.run/ruoyi-server.run.xml +++ b/.run/ruoyi-server.run.xml @@ -1,8 +1,8 @@ - + - diff --git a/.run/ruoyi-snailjob-server.run.xml b/.run/ruoyi-snailjob-server.run.xml index f1d3447bd..bfa74427f 100644 --- a/.run/ruoyi-snailjob-server.run.xml +++ b/.run/ruoyi-snailjob-server.run.xml @@ -2,7 +2,7 @@ - diff --git a/README.md b/README.md index 3ef0ea03a..2d4456475 100644 --- a/README.md +++ b/README.md @@ -6,22 +6,25 @@ [![码云Gitee](https://gitee.com/dromara/RuoYi-Vue-Plus/badge/star.svg?theme=blue)](https://gitee.com/dromara/RuoYi-Vue-Plus) [![GitHub](https://img.shields.io/github/stars/dromara/RuoYi-Vue-Plus.svg?style=social&label=Stars)](https://github.com/dromara/RuoYi-Vue-Plus) +[![Star](https://gitcode.com/dromara/RuoYi-Vue-Plus/star/badge.svg)](https://gitcode.com/dromara/RuoYi-Vue-Plus) [![License](https://img.shields.io/badge/License-MIT-blue.svg)](https://gitee.com/dromara/RuoYi-Vue-Plus/blob/master/LICENSE) [![使用IntelliJ IDEA开发维护](https://img.shields.io/badge/IntelliJ%20IDEA-提供支持-blue.svg)](https://www.jetbrains.com/?from=RuoYi-Vue-Plus)
-[![RuoYi-Vue-Plus](https://img.shields.io/badge/RuoYi_Vue_Plus-5.2.3-success.svg)](https://gitee.com/dromara/RuoYi-Vue-Plus) -[![Spring Boot](https://img.shields.io/badge/Spring%20Boot-3.2-blue.svg)]() +[![RuoYi-Vue-Plus](https://img.shields.io/badge/RuoYi_Vue_Plus-5.3.0--BETA-success.svg)](https://gitee.com/dromara/RuoYi-Vue-Plus) +[![Spring Boot](https://img.shields.io/badge/Spring%20Boot-3.4-blue.svg)]() [![JDK-17](https://img.shields.io/badge/JDK-17-green.svg)]() [![JDK-21](https://img.shields.io/badge/JDK-21-green.svg)]() -> RuoYi-Vue-Plus 是重写 RuoYi-Vue 针对 `分布式集群与多租户` 场景全方位升级(不兼容原框架) +> Dromara RuoYi-Vue-Plus 是重写 RuoYi-Vue 针对 `分布式集群与多租户` 场景全方位升级(不兼容原框架) > 项目代码、文档 均开源免费可商用 遵循开源协议在项目中保留开源协议文件即可
活到老写到老 为兴趣而开源 为学习而开源 为让大家真正可以学到技术而开源 > 系统演示: [传送门](https://plus-doc.dromara.org/#/common/demo_system) -> 前端项目地址: [plus-ui](https://gitee.com/JavaLionLi/plus-ui) +> 官方前端项目地址: [plus-ui](https://gitee.com/JavaLionLi/plus-ui)
+> 成员前端项目地址: 基于vben [ruoyi-plus-vben](https://gitee.com/dapppp/ruoyi-plus-vben)
+> 成员前端项目地址: 基于vben5 [ruoyi-plus-vben5](https://gitee.com/dapppp/ruoyi-plus-vben5) > 文档地址: [plus-doc](https://plus-doc.dromara.org) @@ -31,6 +34,7 @@ MaxKey 业界领先单点登录产品 - https://gitee.com/dromara/MaxKey
CCFlow 驰聘低代码-流程-表单 - https://gitee.com/opencc/RuoYi-JFlow
数舵科技 软件定制开发APP小程序等 - http://www.shuduokeji.com/
引迈信息 软件开发平台 - https://www.jnpfsoft.com/index.html?from=plus-doc
+**启山商城系统 多租户商城源码可免费商用可二次开发 - https://www.73app.cn/**
[如何成为赞助商 加群联系作者详谈](https://plus-doc.dromara.org/#/common/add_group) # 本框架与RuoYi的功能差异 @@ -165,8 +169,8 @@ CCFlow 驰聘低代码-流程-表单 - https://gitee.com/opencc/RuoYi-JFlow
| ![输入图片说明](https://foruda.gitee.com/images/1680078779416197879/75e3ed02_1766278.png "屏幕截图") | ![输入图片说明](https://foruda.gitee.com/images/1680078802329118061/77e10915_1766278.png "屏幕截图") | | ![输入图片说明](https://foruda.gitee.com/images/1680078893627848351/34a1c342_1766278.png "屏幕截图") | ![输入图片说明](https://foruda.gitee.com/images/1680078928175016986/f126ec4a_1766278.png "屏幕截图") | | ![输入图片说明](https://foruda.gitee.com/images/1680078941718318363/b68a0f72_1766278.png "屏幕截图") | ![输入图片说明](https://foruda.gitee.com/images/1680078963175518631/3bb769a1_1766278.png "屏幕截图") | -| ![输入图片说明](https://foruda.gitee.com/images/1680078982294090567/b31c343d_1766278.png "屏幕截图") | ![输入图片说明](https://foruda.gitee.com/images/1680079000642440444/77ca82a9_1766278.png "屏幕截图") | -| ![输入图片说明](https://foruda.gitee.com/images/1680079020995074177/03b7d52e_1766278.png "屏幕截图") | ![输入图片说明](https://foruda.gitee.com/images/1680079039367822173/76811806_1766278.png "屏幕截图") | +| ![输入图片说明](https://foruda.gitee.com/images/1735829153637063344/3c21fd4c_1419627.png "屏幕截图") | ![输入图片说明](https://foruda.gitee.com/images/1735829181303499815/4522cefa_1419627.png "屏幕截图") | +| ![输入图片说明](https://foruda.gitee.com/images/1735829377205259767/76a705d7_1419627.png "屏幕截图") | ![输入图片说明](https://foruda.gitee.com/images/1722959592856812900/e2d0d342_1419627.png "屏幕截图") | | ![输入图片说明](https://foruda.gitee.com/images/1680079274333484664/4dfdc7c0_1766278.png "屏幕截图") | ![输入图片说明](https://foruda.gitee.com/images/1680079290467458224/d6715fcf_1766278.png "屏幕截图") | diff --git a/pom.xml b/pom.xml index 7b92aa7e7..087cc7367 100644 --- a/pom.xml +++ b/pom.xml @@ -10,33 +10,33 @@ RuoYi-Vue-Plus https://gitee.com/dromara/RuoYi-Vue-Plus - RuoYi-Vue-Plus多租户管理系统 + Dromara RuoYi-Vue-Plus多租户管理系统 - 5.2.3 - 3.2.11 + 5.3.0-BETA + 3.4.1 UTF-8 UTF-8 17 3.5.16 - 2.6.0 + 2.8.3 0.15.0 4.0.3 2.3 1.39.0 - 3.5.8 + 3.5.10 3.9.1 - 5.8.31 - 3.2.3 - 3.37.0 + 5.8.35 + 3.4.1 + 3.43.0 2.2.7 4.3.1 - 1.1.2 - 1.4.5 + 1.3.0-beta1.1 + 1.4.6 0.2.0 - 1.18.34 + 1.18.36 1.76 - 1.16.6 + 1.16.7 2.7.0 @@ -48,14 +48,14 @@ 1.2.83 - 8.7.2-20241022 + 8.7.2-20250101 - 7.0.1 + 1.6.0-m5 3.2.2 3.2.2 - 3.11.0 + 3.11.0 3.1.2 1.3.0 @@ -118,12 +118,16 @@ import + - org.flowable - flowable-bom - ${flowable.version} - pom - import + org.dromara.warm + warm-flow-mybatis-plus-sb3-starter + ${warm-flow.version} + + + org.dromara.warm + warm-flow-plugin-ui-sb-web + ${warm-flow.version} @@ -216,6 +220,12 @@ ${mybatis-plus.version} + + com.baomidou + mybatis-plus-jsqlparser + ${mybatis-plus.version} + + com.baomidou mybatis-plus-annotation @@ -369,7 +379,7 @@ org.apache.maven.plugins maven-compiler-plugin - ${maven-compiler-plugin.verison} + ${maven-compiler-plugin.version} ${java.version} ${java.version} diff --git a/ruoyi-admin/Dockerfile b/ruoyi-admin/Dockerfile index 737cbfc78..b489ab57c 100644 --- a/ruoyi-admin/Dockerfile +++ b/ruoyi-admin/Dockerfile @@ -1,6 +1,6 @@ # 贝尔实验室 Spring 官方推荐镜像 JDK下载地址 https://bell-sw.com/pages/downloads/ FROM bellsoft/liberica-openjdk-debian:17.0.11-cds -#FROM bellsoft/liberica-openjdk-debian:21.0.3-cds +#FROM bellsoft/liberica-openjdk-debian:21.0.5-cds #FROM findepi/graalvm:java17-native LABEL maintainer="Lion Li" @@ -16,6 +16,10 @@ ENV SERVER_PORT=8080 LANG=C.UTF-8 LC_ALL=C.UTF-8 JAVA_OPTS="" EXPOSE ${SERVER_PORT} ADD ./target/ruoyi-admin.jar ./app.jar +# 工作流字体文件 +ADD ./zhFonts/ /usr/share/fonts/zhFonts/ + +SHELL ["/bin/bash", "-c"] ENTRYPOINT java -Djava.security.egd=file:/dev/./urandom -Dserver.port=${SERVER_PORT} \ # 应用名称 如果想区分集群节点监控 改成不同的名称即可 diff --git a/ruoyi-admin/src/main/java/org/dromara/web/controller/AuthController.java b/ruoyi-admin/src/main/java/org/dromara/web/controller/AuthController.java index b561693d6..7fbc57f95 100644 --- a/ruoyi-admin/src/main/java/org/dromara/web/controller/AuthController.java +++ b/ruoyi-admin/src/main/java/org/dromara/web/controller/AuthController.java @@ -2,6 +2,7 @@ package org.dromara.web.controller; import cn.dev33.satoken.annotation.SaIgnore; import cn.dev33.satoken.exception.NotLoginException; +import cn.dev33.satoken.stp.StpUtil; import cn.hutool.core.codec.Base64; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; @@ -12,7 +13,7 @@ import me.zhyd.oauth.model.AuthResponse; import me.zhyd.oauth.model.AuthUser; import me.zhyd.oauth.request.AuthRequest; import me.zhyd.oauth.utils.AuthStateUtils; -import org.dromara.common.core.constant.UserConstants; +import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.core.domain.R; import org.dromara.common.core.domain.model.LoginBody; import org.dromara.common.core.domain.model.RegisterBody; @@ -92,7 +93,7 @@ public class AuthController { if (ObjectUtil.isNull(client) || !StringUtils.contains(client.getGrantType(), grantType)) { log.info("客户端id: {} 认证类型:{} 异常!.", clientId, grantType); return R.fail(MessageUtils.message("auth.grant.type.error")); - } else if (!UserConstants.NORMAL.equals(client.getStatus())) { + } else if (!SystemConstants.NORMAL.equals(client.getStatus())) { return R.fail(MessageUtils.message("auth.grant.type.blocked")); } // 校验租户 @@ -111,7 +112,7 @@ public class AuthController { } /** - * 第三方登录请求 + * 获取跳转URL * * @param source 登录来源 * @return 结果 @@ -133,13 +134,15 @@ public class AuthController { } /** - * 第三方登录回调业务处理 绑定授权 + * 前端回调绑定授权(需要token) * * @param loginBody 请求体 * @return 结果 */ @PostMapping("/social/callback") public R socialCallback(@RequestBody SocialLoginBody loginBody) { + // 校验token + StpUtil.checkLogin(); // 获取第三方登录信息 AuthResponse response = SocialUtils.loginAuth( loginBody.getSource(), loginBody.getSocialCode(), @@ -155,12 +158,14 @@ public class AuthController { /** - * 取消授权 + * 取消授权(需要token) * * @param socialId socialId */ @DeleteMapping(value = "/unlock/{socialId}") public R unlockSocial(@PathVariable Long socialId) { + // 校验token + StpUtil.checkLogin(); Boolean rows = socialUserService.deleteWithValidById(socialId); return rows ? R.ok() : R.fail("取消授权失败"); } @@ -226,7 +231,7 @@ public class AuthController { } // 根据域名进行筛选 List list = StreamUtils.filter(voList, vo -> - StringUtils.equals(vo.getDomain(), host)); + StringUtils.equalsIgnoreCase(vo.getDomain(), host)); result.setVoList(CollUtil.isNotEmpty(list) ? list : voList); return R.ok(result); } diff --git a/ruoyi-admin/src/main/java/org/dromara/web/service/SysLoginService.java b/ruoyi-admin/src/main/java/org/dromara/web/service/SysLoginService.java index c7ad9179c..41a802b44 100644 --- a/ruoyi-admin/src/main/java/org/dromara/web/service/SysLoginService.java +++ b/ruoyi-admin/src/main/java/org/dromara/web/service/SysLoginService.java @@ -12,11 +12,12 @@ import lombok.extern.slf4j.Slf4j; import me.zhyd.oauth.model.AuthUser; import org.dromara.common.core.constant.CacheConstants; import org.dromara.common.core.constant.Constants; +import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.core.constant.TenantConstants; +import org.dromara.common.core.domain.dto.PostDTO; import org.dromara.common.core.domain.dto.RoleDTO; import org.dromara.common.core.domain.model.LoginUser; import org.dromara.common.core.enums.LoginType; -import org.dromara.common.core.enums.TenantStatus; import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.exception.user.UserException; import org.dromara.common.core.utils.*; @@ -60,6 +61,7 @@ public class SysLoginService { private final ISysSocialService sysSocialService; private final ISysRoleService roleService; private final ISysDeptService deptService; + private final ISysPostService postService; private final SysUserMapper userMapper; @@ -148,21 +150,24 @@ public class SysLoginService { */ public LoginUser buildLoginUser(SysUserVo user) { LoginUser loginUser = new LoginUser(); + Long userId = user.getUserId(); loginUser.setTenantId(user.getTenantId()); - loginUser.setUserId(user.getUserId()); + loginUser.setUserId(userId); loginUser.setDeptId(user.getDeptId()); loginUser.setUsername(user.getUserName()); loginUser.setNickname(user.getNickName()); loginUser.setUserType(user.getUserType()); - loginUser.setMenuPermission(permissionService.getMenuPermission(user.getUserId())); - loginUser.setRolePermission(permissionService.getRolePermission(user.getUserId())); + loginUser.setMenuPermission(permissionService.getMenuPermission(userId)); + loginUser.setRolePermission(permissionService.getRolePermission(userId)); if (ObjectUtil.isNotNull(user.getDeptId())) { Opt deptOpt = Opt.of(user.getDeptId()).map(deptService::selectDeptById); loginUser.setDeptName(deptOpt.map(SysDeptVo::getDeptName).orElse(StringUtils.EMPTY)); loginUser.setDeptCategory(deptOpt.map(SysDeptVo::getDeptCategory).orElse(StringUtils.EMPTY)); } - List roles = roleService.selectRolesByUserId(user.getUserId()); + List roles = roleService.selectRolesByUserId(userId); + List posts = postService.selectPostsByUserId(userId); loginUser.setRoles(BeanUtil.copyToList(roles, RoleDTO.class)); + loginUser.setPosts(BeanUtil.copyToList(posts, PostDTO.class)); return loginUser; } @@ -223,17 +228,17 @@ public class SysLoginService { if (!TenantHelper.isEnable()) { return; } - if (TenantConstants.DEFAULT_TENANT_ID.equals(tenantId)) { - return; - } if (StringUtils.isBlank(tenantId)) { throw new TenantException("tenant.number.not.blank"); } + if (TenantConstants.DEFAULT_TENANT_ID.equals(tenantId)) { + return; + } SysTenantVo tenant = tenantService.queryByTenantId(tenantId); if (ObjectUtil.isNull(tenant)) { log.info("登录租户:{} 不存在.", tenantId); throw new TenantException("tenant.not.exists"); - } else if (TenantStatus.DISABLE.getCode().equals(tenant.getStatus())) { + } else if (SystemConstants.DISABLE.equals(tenant.getStatus())) { log.info("登录租户:{} 已被停用.", tenantId); throw new TenantException("tenant.blocked"); } else if (ObjectUtil.isNotNull(tenant.getExpireTime()) diff --git a/ruoyi-admin/src/main/java/org/dromara/web/service/SysRegisterService.java b/ruoyi-admin/src/main/java/org/dromara/web/service/SysRegisterService.java index ddab279bc..9ec08132e 100644 --- a/ruoyi-admin/src/main/java/org/dromara/web/service/SysRegisterService.java +++ b/ruoyi-admin/src/main/java/org/dromara/web/service/SysRegisterService.java @@ -84,11 +84,11 @@ public class SysRegisterService { String captcha = RedisUtils.getCacheObject(verifyKey); RedisUtils.deleteObject(verifyKey); if (captcha == null) { - recordLogininfor(tenantId, username, Constants.REGISTER, MessageUtils.message("user.jcaptcha.expire")); + recordLogininfor(tenantId, username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire")); throw new CaptchaExpireException(); } if (!code.equalsIgnoreCase(captcha)) { - recordLogininfor(tenantId, username, Constants.REGISTER, MessageUtils.message("user.jcaptcha.error")); + recordLogininfor(tenantId, username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error")); throw new CaptchaException(); } } diff --git a/ruoyi-admin/src/main/java/org/dromara/web/service/impl/EmailAuthStrategy.java b/ruoyi-admin/src/main/java/org/dromara/web/service/impl/EmailAuthStrategy.java index b5a24976e..1bed4f3e5 100644 --- a/ruoyi-admin/src/main/java/org/dromara/web/service/impl/EmailAuthStrategy.java +++ b/ruoyi-admin/src/main/java/org/dromara/web/service/impl/EmailAuthStrategy.java @@ -8,10 +8,10 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.dromara.common.core.constant.Constants; import org.dromara.common.core.constant.GlobalConstants; +import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.core.domain.model.EmailLoginBody; import org.dromara.common.core.domain.model.LoginUser; import org.dromara.common.core.enums.LoginType; -import org.dromara.common.core.enums.UserStatus; import org.dromara.common.core.exception.user.CaptchaExpireException; import org.dromara.common.core.exception.user.UserException; import org.dromara.common.core.utils.MessageUtils; @@ -92,7 +92,7 @@ public class EmailAuthStrategy implements IAuthStrategy { if (ObjectUtil.isNull(user)) { log.info("登录用户:{} 不存在.", email); throw new UserException("user.not.exists", email); - } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) { + } else if (SystemConstants.DISABLE.equals(user.getStatus())) { log.info("登录用户:{} 已被停用.", email); throw new UserException("user.blocked", email); } diff --git a/ruoyi-admin/src/main/java/org/dromara/web/service/impl/PasswordAuthStrategy.java b/ruoyi-admin/src/main/java/org/dromara/web/service/impl/PasswordAuthStrategy.java index f28024f35..e8e60e1c4 100644 --- a/ruoyi-admin/src/main/java/org/dromara/web/service/impl/PasswordAuthStrategy.java +++ b/ruoyi-admin/src/main/java/org/dromara/web/service/impl/PasswordAuthStrategy.java @@ -9,10 +9,10 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.dromara.common.core.constant.Constants; import org.dromara.common.core.constant.GlobalConstants; +import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.core.domain.model.LoginUser; import org.dromara.common.core.domain.model.PasswordLoginBody; import org.dromara.common.core.enums.LoginType; -import org.dromara.common.core.enums.UserStatus; import org.dromara.common.core.exception.user.CaptchaException; import org.dromara.common.core.exception.user.CaptchaExpireException; import org.dromara.common.core.exception.user.UserException; @@ -113,7 +113,7 @@ public class PasswordAuthStrategy implements IAuthStrategy { if (ObjectUtil.isNull(user)) { log.info("登录用户:{} 不存在.", username); throw new UserException("user.not.exists", username); - } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) { + } else if (SystemConstants.DISABLE.equals(user.getStatus())) { log.info("登录用户:{} 已被停用.", username); throw new UserException("user.blocked", username); } diff --git a/ruoyi-admin/src/main/java/org/dromara/web/service/impl/SmsAuthStrategy.java b/ruoyi-admin/src/main/java/org/dromara/web/service/impl/SmsAuthStrategy.java index 89f846244..2ffda353e 100644 --- a/ruoyi-admin/src/main/java/org/dromara/web/service/impl/SmsAuthStrategy.java +++ b/ruoyi-admin/src/main/java/org/dromara/web/service/impl/SmsAuthStrategy.java @@ -8,10 +8,10 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.dromara.common.core.constant.Constants; import org.dromara.common.core.constant.GlobalConstants; +import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.core.domain.model.LoginUser; import org.dromara.common.core.domain.model.SmsLoginBody; import org.dromara.common.core.enums.LoginType; -import org.dromara.common.core.enums.UserStatus; import org.dromara.common.core.exception.user.CaptchaExpireException; import org.dromara.common.core.exception.user.UserException; import org.dromara.common.core.utils.MessageUtils; @@ -92,7 +92,7 @@ public class SmsAuthStrategy implements IAuthStrategy { if (ObjectUtil.isNull(user)) { log.info("登录用户:{} 不存在.", phonenumber); throw new UserException("user.not.exists", phonenumber); - } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) { + } else if (SystemConstants.DISABLE.equals(user.getStatus())) { log.info("登录用户:{} 已被停用.", phonenumber); throw new UserException("user.blocked", phonenumber); } diff --git a/ruoyi-admin/src/main/java/org/dromara/web/service/impl/SocialAuthStrategy.java b/ruoyi-admin/src/main/java/org/dromara/web/service/impl/SocialAuthStrategy.java index 84630260f..419dbd6ba 100644 --- a/ruoyi-admin/src/main/java/org/dromara/web/service/impl/SocialAuthStrategy.java +++ b/ruoyi-admin/src/main/java/org/dromara/web/service/impl/SocialAuthStrategy.java @@ -11,9 +11,9 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import me.zhyd.oauth.model.AuthResponse; import me.zhyd.oauth.model.AuthUser; +import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.core.domain.model.LoginUser; import org.dromara.common.core.domain.model.SocialLoginBody; -import org.dromara.common.core.enums.UserStatus; import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.exception.user.UserException; import org.dromara.common.core.utils.StreamUtils; @@ -121,7 +121,7 @@ public class SocialAuthStrategy implements IAuthStrategy { if (ObjectUtil.isNull(user)) { log.info("登录用户:{} 不存在.", ""); throw new UserException("user.not.exists", ""); - } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) { + } else if (SystemConstants.DISABLE.equals(user.getStatus())) { log.info("登录用户:{} 已被停用.", ""); throw new UserException("user.blocked", ""); } diff --git a/ruoyi-admin/src/main/java/org/dromara/web/service/impl/XcxAuthStrategy.java b/ruoyi-admin/src/main/java/org/dromara/web/service/impl/XcxAuthStrategy.java index aa8be73a7..fa9b61819 100644 --- a/ruoyi-admin/src/main/java/org/dromara/web/service/impl/XcxAuthStrategy.java +++ b/ruoyi-admin/src/main/java/org/dromara/web/service/impl/XcxAuthStrategy.java @@ -5,13 +5,20 @@ import cn.dev33.satoken.stp.StpUtil; import cn.hutool.core.util.ObjectUtil; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import me.zhyd.oauth.config.AuthConfig; +import me.zhyd.oauth.model.AuthCallback; +import me.zhyd.oauth.model.AuthResponse; +import me.zhyd.oauth.model.AuthToken; +import me.zhyd.oauth.model.AuthUser; +import me.zhyd.oauth.request.AuthRequest; +import me.zhyd.oauth.request.AuthWechatMiniProgramRequest; +import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.core.domain.model.XcxLoginBody; import org.dromara.common.core.domain.model.XcxLoginUser; -import org.dromara.common.core.enums.UserStatus; +import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.utils.ValidatorUtils; import org.dromara.common.json.utils.JsonUtils; import org.dromara.common.satoken.utils.LoginHelper; -import org.dromara.system.domain.SysClient; import org.dromara.system.domain.vo.SysClientVo; import org.dromara.system.domain.vo.SysUserVo; import org.dromara.web.domain.vo.LoginVo; @@ -40,12 +47,24 @@ public class XcxAuthStrategy implements IAuthStrategy { // 多个小程序识别使用 String appid = loginBody.getAppid(); - // todo 以下自行实现 // 校验 appid + appsrcret + xcxCode 调用登录凭证校验接口 获取 session_key 与 openid - String openid = ""; + AuthRequest authRequest = new AuthWechatMiniProgramRequest(AuthConfig.builder() + .clientId(appid).clientSecret("自行填写密钥 可根据不同appid填入不同密钥") + .ignoreCheckRedirectUri(true).ignoreCheckState(true).build()); + AuthCallback authCallback = new AuthCallback(); + authCallback.setCode(xcxCode); + AuthResponse resp = authRequest.login(authCallback); + String openid, unionId; + if (resp.ok()) { + AuthToken token = resp.getData().getToken(); + openid = token.getOpenId(); + // 微信小程序只有关联到微信开放平台下之后才能获取到 unionId,因此unionId不一定能返回。 + unionId = token.getUnionId(); + } else { + throw new ServiceException(resp.getMsg()); + } // 框架登录不限制从什么表查询 只要最终构建出 LoginUser 即可 SysUserVo user = loadUserByOpenid(openid); - // 此处可根据登录用户的数据不同 自行创建 loginUser 属性不够用继承扩展就行了 XcxLoginUser loginUser = new XcxLoginUser(); loginUser.setTenantId(user.getTenantId()); @@ -82,7 +101,7 @@ public class XcxAuthStrategy implements IAuthStrategy { if (ObjectUtil.isNull(user)) { log.info("登录用户:{} 不存在.", openid); // todo 用户不存在 业务逻辑自行实现 - } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) { + } else if (SystemConstants.DISABLE.equals(user.getStatus())) { log.info("登录用户:{} 已被停用.", openid); // todo 用户已被停用 业务逻辑自行实现 } diff --git a/ruoyi-admin/src/main/resources/application-dev.yml b/ruoyi-admin/src/main/resources/application-dev.yml index 4410ab59f..63b76e951 100644 --- a/ruoyi-admin/src/main/resources/application-dev.yml +++ b/ruoyi-admin/src/main/resources/application-dev.yml @@ -2,7 +2,7 @@ spring.boot.admin.client: # 增加客户端开关 enabled: true - url: http://localhost:9090/admin + url: http://localhost:9090 instance: service-host-type: IP metadata: @@ -16,17 +16,19 @@ snail-job: enabled: true # 需要在 SnailJob 后台组管理创建对应名称的组,然后创建任务的时候选择对应的组,才能正确分派任务 group: "ruoyi_group" - # SnailJob 接入验证令牌 详见 script/sql/snail_job.sql `sj_group_config` 表 + # SnailJob 接入验证令牌 详见 script/sql/ry_job.sql `sj_group_config` 表 token: "SJ_cKqBTPzCsWA3VyuCfFoccmuIEGXjr5KT" server: host: 127.0.0.1 port: 17888 - # 详见 script/sql/snail_job.sql `sj_namespace` 表 + # 命名空间UUID 详见 script/sql/ry_job.sql `sj_namespace`表`unique_id`字段 namespace: ${spring.profiles.active} - # 随主应用端口飘逸 + # 随主应用端口漂移 port: 2${server.port} # 客户端ip指定 host: + # RPC类型: netty, grpc + rpc-type: grpc --- # 数据源配置 spring: @@ -50,14 +52,14 @@ spring: url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true username: root password: root - # 从库数据源 - slave: - lazy: true - type: ${spring.datasource.type} - driverClassName: com.mysql.cj.jdbc.Driver - url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true - username: - password: +# # 从库数据源 +# slave: +# lazy: true +# type: ${spring.datasource.type} +# driverClassName: com.mysql.cj.jdbc.Driver +# url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true +# username: +# password: # oracle: # type: ${spring.datasource.type} # driverClassName: oracle.jdbc.OracleDriver @@ -200,7 +202,7 @@ justauth: redirect-uri: ${justauth.address}/social-callback?source=maxkey topiam: # topiam 服务器地址 - server-url: http://127.0.0.1:1989/api/v1/authorize/y0q************spq***********8ol + server-url: http://127.0.0.1:1898/api/v1/authorize/y0q************spq***********8ol client-id: 449c4*********937************759 client-secret: ac7***********1e0************28d redirect-uri: ${justauth.address}/social-callback?source=topiam diff --git a/ruoyi-admin/src/main/resources/application-prod.yml b/ruoyi-admin/src/main/resources/application-prod.yml index d26111828..3e41f84c0 100644 --- a/ruoyi-admin/src/main/resources/application-prod.yml +++ b/ruoyi-admin/src/main/resources/application-prod.yml @@ -5,7 +5,7 @@ spring.servlet.multipart.location: /ruoyi/server/temp spring.boot.admin.client: # 增加客户端开关 enabled: true - url: http://localhost:9090/admin + url: http://localhost:9090 instance: service-host-type: IP metadata: @@ -19,17 +19,19 @@ snail-job: enabled: true # 需要在 SnailJob 后台组管理创建对应名称的组,然后创建任务的时候选择对应的组,才能正确分派任务 group: "ruoyi_group" - # SnailJob 接入验证令牌 详见 script/sql/snail_job.sql `sj_group_config` 表 + # SnailJob 接入验证令牌 详见 script/sql/ry_job.sql `sj_group_config`表 token: "SJ_cKqBTPzCsWA3VyuCfFoccmuIEGXjr5KT" server: host: 127.0.0.1 port: 17888 - # 详见 script/sql/snail_job.sql `sj_namespace` 表 + # 命名空间UUID 详见 script/sql/ry_job.sql `sj_namespace`表`unique_id`字段 namespace: ${spring.profiles.active} - # 随主应用端口飘逸 + # 随主应用端口漂移 port: 2${server.port} # 客户端ip指定 host: + # RPC类型: netty, grpc + rpc-type: grpc --- # 数据源配置 spring: @@ -53,14 +55,14 @@ spring: url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true username: root password: root - # 从库数据源 - slave: - lazy: true - type: ${spring.datasource.type} - driverClassName: com.mysql.cj.jdbc.Driver - url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true - username: - password: +# # 从库数据源 +# slave: +# lazy: true +# type: ${spring.datasource.type} +# driverClassName: com.mysql.cj.jdbc.Driver +# url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true +# username: +# password: # oracle: # type: ${spring.datasource.type} # driverClassName: oracle.jdbc.OracleDriver diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml index 82d0f1e50..dbe16888d 100644 --- a/ruoyi-admin/src/main/resources/application.yml +++ b/ruoyi-admin/src/main/resources/application.yml @@ -47,6 +47,7 @@ logging: org.dromara: @logging.level@ org.springframework: warn org.mybatis.spring.mapper: error + org.apache.fury: warn config: classpath:logback-plus.xml # 用户配置 @@ -110,17 +111,15 @@ sa-token: security: # 排除路径 excludes: - # 静态资源 - /*.html - /**/*.html - /**/*.css - /**/*.js - # 公共路径 - /favicon.ico - /error - # swagger 文档配置 - /*/api-docs - /*/api-docs/** + - /warm-flow-ui/token-name # 多租户配置 tenant: @@ -141,6 +140,8 @@ tenant: # MyBatisPlus配置 # https://baomidou.com/config/ mybatis-plus: + # 自定义配置 是否全局开启逻辑删除 关闭后 所有逻辑删除功能将失效 + enableLogicDelete: true # 多包名使用 例如 org.dromara.**.mapper,org.xxx.**.mapper mapperPackage: org.dromara.**.mapper # 对应的 XML 文件位置 @@ -217,6 +218,8 @@ springdoc: packages-to-scan: org.dromara.system - group: 4.代码生成模块 packages-to-scan: org.dromara.generator + - group: 5.工作流模块 + packages-to-scan: org.dromara.workflow # 防止XSS攻击 xss: @@ -225,8 +228,7 @@ xss: # 排除链接(多个用逗号分隔) excludeUrls: - /system/notice - - /workflow/model/save - - /workflow/model/editModelXml + - /warm-flow/save-xml # 全局线程池相关配置 # 如使用JDK21请直接使用虚拟线程 不要开启此配置 @@ -271,24 +273,11 @@ websocket: # 设置访问源地址 allowedOrigins: '*' ---- #flowable配置 -flowable: - # 开关 用于启动/停用工作流 +--- # warm-flow工作流配置 +warm-flow: + # 是否开启工作流,默认true enabled: true - process.enabled: ${flowable.enabled} - eventregistry.enabled: ${flowable.enabled} - async-executor-activate: false #关闭定时任务JOB - # 将databaseSchemaUpdate设置为true。当Flowable发现库与数据库表结构不一致时,会自动将数据库表结构升级至新版本。 - database-schema-update: true - activity-font-name: 宋体 - label-font-name: 宋体 - annotation-font-name: 宋体 - # 关闭各个模块生成表,目前只使用工作流基础表 - idm: - enabled: false - cmmn: - enabled: false - dmn: - enabled: false - app: - enabled: false + # 是否开启设计器ui + ui: true + # 默认Authorization,如果有多个token,用逗号分隔 + token-name: ${sa-token.token-name},clientid diff --git a/ruoyi-admin/src/main/resources/logback-plus.xml b/ruoyi-admin/src/main/resources/logback-plus.xml index 40fa33b7c..b74289ecd 100644 --- a/ruoyi-admin/src/main/resources/logback-plus.xml +++ b/ruoyi-admin/src/main/resources/logback-plus.xml @@ -2,7 +2,7 @@ + value="%cyan(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) %highlight(%-5level) %boldMagenta(%logger{36}%n) - %msg%n"/> diff --git a/ruoyi-admin/zhFonts/.uuid b/ruoyi-admin/zhFonts/.uuid new file mode 100644 index 000000000..cee5cdd7c --- /dev/null +++ b/ruoyi-admin/zhFonts/.uuid @@ -0,0 +1 @@ +3f2ee348-0303-40ca-bf03-03f48d2d2141 \ No newline at end of file diff --git a/ruoyi-admin/zhFonts/SIMSUN.TTC b/ruoyi-admin/zhFonts/SIMSUN.TTC new file mode 100644 index 000000000..6ca8de3da Binary files /dev/null and b/ruoyi-admin/zhFonts/SIMSUN.TTC differ diff --git a/ruoyi-admin/zhFonts/fonts.dir b/ruoyi-admin/zhFonts/fonts.dir new file mode 100644 index 000000000..fed95442c --- /dev/null +++ b/ruoyi-admin/zhFonts/fonts.dir @@ -0,0 +1,4 @@ +3 +SIMSUN.TTC -misc-simsun-medium-r-normal--0-0-0-0-p-0-iso10646-1 +SIMSUN.TTC -misc-simsun-medium-r-normal--0-0-0-0-p-0-iso8859-1 +SIMSUN.TTC -misc-simsun-medium-r-normal--0-0-0-0-p-0-koi8-r diff --git a/ruoyi-admin/zhFonts/fonts.scale b/ruoyi-admin/zhFonts/fonts.scale new file mode 100644 index 000000000..fed95442c --- /dev/null +++ b/ruoyi-admin/zhFonts/fonts.scale @@ -0,0 +1,4 @@ +3 +SIMSUN.TTC -misc-simsun-medium-r-normal--0-0-0-0-p-0-iso10646-1 +SIMSUN.TTC -misc-simsun-medium-r-normal--0-0-0-0-p-0-iso8859-1 +SIMSUN.TTC -misc-simsun-medium-r-normal--0-0-0-0-p-0-koi8-r diff --git a/ruoyi-common/ruoyi-common-bom/pom.xml b/ruoyi-common/ruoyi-common-bom/pom.xml index dbc5f1c2b..19f2d0372 100644 --- a/ruoyi-common/ruoyi-common-bom/pom.xml +++ b/ruoyi-common/ruoyi-common-bom/pom.xml @@ -14,7 +14,7 @@ - 5.2.3 + 5.3.0-BETA diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/config/ThreadPoolConfig.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/config/ThreadPoolConfig.java index b4d452817..2630485a4 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/config/ThreadPoolConfig.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/config/ThreadPoolConfig.java @@ -4,11 +4,13 @@ import jakarta.annotation.PreDestroy; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.concurrent.BasicThreadFactory; import org.dromara.common.core.config.properties.ThreadPoolProperties; +import org.dromara.common.core.utils.SpringUtils; import org.dromara.common.core.utils.Threads; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; +import org.springframework.core.task.VirtualThreadTaskExecutor; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import java.util.concurrent.ScheduledExecutorService; @@ -49,8 +51,15 @@ public class ThreadPoolConfig { */ @Bean(name = "scheduledExecutorService") protected ScheduledExecutorService scheduledExecutorService() { + // daemon 必须为 true + BasicThreadFactory.Builder builder = new BasicThreadFactory.Builder().daemon(true); + if (SpringUtils.isVirtual()) { + builder.namingPattern("virtual-schedule-pool-%d").wrappedFactory(new VirtualThreadTaskExecutor().getVirtualThreadFactory()); + } else { + builder.namingPattern("schedule-pool-%d"); + } ScheduledThreadPoolExecutor scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(core, - new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build(), + builder.build(), new ThreadPoolExecutor.CallerRunsPolicy()) { @Override protected void afterExecute(Runnable r, Throwable t) { diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/CacheNames.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/CacheNames.java index 28ba17739..bf8efc550 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/CacheNames.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/CacheNames.java @@ -60,6 +60,16 @@ public interface CacheNames { */ String SYS_OSS = "sys_oss#30d"; + /** + * 角色自定义权限 + */ + String SYS_ROLE_CUSTOM = "sys_role_custom#30d"; + + /** + * 部门及以下权限 + */ + String SYS_DEPT_AND_CHILD = "sys_dept_and_child#30d"; + /** * OSS配置 */ diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/Constants.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/Constants.java index cdbda89f6..273c7344a 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/Constants.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/Constants.java @@ -68,12 +68,7 @@ public interface Constants { Integer CAPTCHA_EXPIRATION = 2; /** - * 令牌 - */ - String TOKEN = "token"; - - /** - * 顶级部门id + * 顶级父级id */ Long TOP_PARENT_ID = 0L; diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/SystemConstants.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/SystemConstants.java new file mode 100644 index 000000000..55240bbf8 --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/SystemConstants.java @@ -0,0 +1,75 @@ +package org.dromara.common.core.constant; + +/** + * 系统常量信息 + * + * @author Lion Li + */ +public interface SystemConstants { + + /** + * 正常状态 + */ + String NORMAL = "0"; + + /** + * 异常状态 + */ + String DISABLE = "1"; + + /** + * 是否为系统默认(是) + */ + String YES = "Y"; + + /** + * 是否为系统默认(否) + */ + String NO = "N"; + + /** + * 是否菜单外链(是) + */ + String YES_FRAME = "0"; + + /** + * 是否菜单外链(否) + */ + String NO_FRAME = "1"; + + /** + * 菜单类型(目录) + */ + String TYPE_DIR = "M"; + + /** + * 菜单类型(菜单) + */ + String TYPE_MENU = "C"; + + /** + * 菜单类型(按钮) + */ + String TYPE_BUTTON = "F"; + + /** + * Layout组件标识 + */ + String LAYOUT = "Layout"; + + /** + * ParentView组件标识 + */ + String PARENT_VIEW = "ParentView"; + + /** + * InnerLink组件标识 + */ + String INNER_LINK = "InnerLink"; + + /** + * 超级管理员ID + */ + Long SUPER_ADMIN_ID = 1L; + +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/TenantConstants.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/TenantConstants.java index 86b63c97a..33ce0cf6c 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/TenantConstants.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/TenantConstants.java @@ -7,16 +7,6 @@ package org.dromara.common.core.constant; */ public interface TenantConstants { - /** - * 租户正常状态 - */ - String NORMAL = "0"; - - /** - * 租户封禁状态 - */ - String DISABLE = "1"; - /** * 超级管理员ID */ diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/UserConstants.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/UserConstants.java deleted file mode 100644 index 76f6dd4ad..000000000 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/UserConstants.java +++ /dev/null @@ -1,152 +0,0 @@ -package org.dromara.common.core.constant; - -/** - * 用户常量信息 - * - * @author ruoyi - */ -public interface UserConstants { - - /** - * 平台内系统用户的唯一标志 - */ - String SYS_USER = "SYS_USER"; - - /** - * 正常状态 - */ - String NORMAL = "0"; - - /** - * 异常状态 - */ - String EXCEPTION = "1"; - - /** - * 用户正常状态 - */ - String USER_NORMAL = "0"; - - /** - * 用户封禁状态 - */ - String USER_DISABLE = "1"; - - /** - * 角色正常状态 - */ - String ROLE_NORMAL = "0"; - - /** - * 角色封禁状态 - */ - String ROLE_DISABLE = "1"; - - /** - * 部门正常状态 - */ - String DEPT_NORMAL = "0"; - - /** - * 部门停用状态 - */ - String DEPT_DISABLE = "1"; - - /** - * 岗位正常状态 - */ - String POST_NORMAL = "0"; - - /** - * 岗位停用状态 - */ - String POST_DISABLE = "1"; - - /** - * 字典正常状态 - */ - String DICT_NORMAL = "0"; - - /** - * 通用存在标志 - */ - String DEL_FLAG_NORMAL = "0"; - - /** - * 通用删除标志 - */ - String DEL_FLAG_REMOVED = "2"; - - /** - * 是否为系统默认(是) - */ - String YES = "Y"; - - /** - * 是否菜单外链(是) - */ - String YES_FRAME = "0"; - - /** - * 是否菜单外链(否) - */ - String NO_FRAME = "1"; - - /** - * 菜单正常状态 - */ - String MENU_NORMAL = "0"; - - /** - * 菜单停用状态 - */ - String MENU_DISABLE = "1"; - - /** - * 菜单类型(目录) - */ - String TYPE_DIR = "M"; - - /** - * 菜单类型(菜单) - */ - String TYPE_MENU = "C"; - - /** - * 菜单类型(按钮) - */ - String TYPE_BUTTON = "F"; - - /** - * Layout组件标识 - */ - String LAYOUT = "Layout"; - - /** - * ParentView组件标识 - */ - String PARENT_VIEW = "ParentView"; - - /** - * InnerLink组件标识 - */ - String INNER_LINK = "InnerLink"; - - /** - * 用户名长度限制 - */ - int USERNAME_MIN_LENGTH = 2; - int USERNAME_MAX_LENGTH = 20; - - /** - * 密码长度限制 - */ - int PASSWORD_MIN_LENGTH = 5; - int PASSWORD_MAX_LENGTH = 20; - - /** - * 超级管理员ID - */ - Long SUPER_ADMIN_ID = 1L; - -} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/CompleteTaskDTO.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/CompleteTaskDTO.java new file mode 100644 index 000000000..2e63f8aca --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/CompleteTaskDTO.java @@ -0,0 +1,71 @@ +package org.dromara.common.core.domain.dto; + +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * 办理任务请求对象 + * + * @author may + */ +@Data +public class CompleteTaskDTO implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 任务id + */ + private Long taskId; + + /** + * 附件id + */ + private String fileId; + + /** + * 抄送人员 + */ + private List flowCopyList; + + /** + * 消息类型 + */ + private List messageType; + + /** + * 办理意见 + */ + private String message; + + /** + * 消息通知 + */ + private String notice; + + /** + * 流程变量 + */ + private Map variables; + + /** + * 扩展变量(此处为逗号分隔的ossId) + */ + private String ext; + + public Map getVariables() { + if (variables == null) { + return new HashMap<>(16); + } + variables.entrySet().removeIf(entry -> Objects.isNull(entry.getValue())); + return variables; + } + +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/DeptDTO.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/DeptDTO.java new file mode 100644 index 000000000..65c012faf --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/DeptDTO.java @@ -0,0 +1,37 @@ +package org.dromara.common.core.domain.dto; + +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serial; +import java.io.Serializable; + +/** + * 部门 + * + * @author AprilWind + */ + +@Data +@NoArgsConstructor +public class DeptDTO implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 部门ID + */ + private Long deptId; + + /** + * 父部门ID + */ + private Long parentId; + + /** + * 部门名称 + */ + private String deptName; + +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/FlowCopyDTO.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/FlowCopyDTO.java new file mode 100644 index 000000000..2f20b21f7 --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/FlowCopyDTO.java @@ -0,0 +1,30 @@ +package org.dromara.common.core.domain.dto; + +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; + + +/** + * 抄送 + * + * @author may + */ +@Data +public class FlowCopyDTO implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 用户id + */ + private Long userId; + + /** + * 用户名称 + */ + private String userName; + +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/PostDTO.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/PostDTO.java new file mode 100644 index 000000000..7536ee33d --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/PostDTO.java @@ -0,0 +1,46 @@ +package org.dromara.common.core.domain.dto; + +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serial; +import java.io.Serializable; + +/** + * 岗位 + * + * @author AprilWind + */ +@Data +@NoArgsConstructor +public class PostDTO implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 岗位ID + */ + private Long postId; + + /** + * 部门id + */ + private Long deptId; + + /** + * 岗位编码 + */ + private String postCode; + + /** + * 岗位名称 + */ + private String postName; + + /** + * 岗位类别编码 + */ + private String postCategory; + +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/StartProcessDTO.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/StartProcessDTO.java new file mode 100644 index 000000000..3934ada55 --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/StartProcessDTO.java @@ -0,0 +1,45 @@ +package org.dromara.common.core.domain.dto; + + +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +/** + * 启动流程对象 + * + * @author may + */ +@Data +public class StartProcessDTO implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 业务唯一值id + */ + private String businessId; + + /** + * 流程定义编码 + */ + private String flowCode; + + /** + * 流程变量,前端会提交一个元素{'entity': {业务详情数据对象}} + */ + private Map variables; + + public Map getVariables() { + if (variables == null) { + return new HashMap<>(16); + } + variables.entrySet().removeIf(entry -> Objects.isNull(entry.getValue())); + return variables; + } +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/TaskAssigneeDTO.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/TaskAssigneeDTO.java new file mode 100644 index 000000000..85893e1dc --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/TaskAssigneeDTO.java @@ -0,0 +1,101 @@ +package org.dromara.common.core.domain.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serial; +import java.io.Serializable; +import java.util.Date; +import java.util.List; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * 任务受让人 + * + * @author AprilWind + */ +@Data +@NoArgsConstructor +public class TaskAssigneeDTO implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 总大小 + */ + private Long total = 0L; + + /** + * + */ + private List list; + + public TaskAssigneeDTO(Long total, List list) { + this.total = total; + this.list = list; + } + + /** + * 将源列表转换为 TaskHandler 列表 + * + * @param 通用类型 + * @param sourceList 待转换的源列表 + * @param storageId 提取 storageId 的函数 + * @param handlerCode 提取 handlerCode 的函数 + * @param handlerName 提取 handlerName 的函数 + * @param groupName 提取 groupName 的函数 + * @param createTimeMapper 提取 createTime 的函数 + * @return 转换后的 TaskHandler 列表 + */ + public static List convertToHandlerList( + List sourceList, + Function storageId, + Function handlerCode, + Function handlerName, + Function groupName, + Function createTimeMapper) { + return sourceList.stream() + .map(item -> new TaskHandler( + String.valueOf(storageId.apply(item)), + handlerCode.apply(item), + handlerName.apply(item), + groupName != null ? String.valueOf(groupName.apply(item)) : null, + createTimeMapper.apply(item) + )).collect(Collectors.toList()); + } + + @Data + @NoArgsConstructor + @AllArgsConstructor + public static class TaskHandler { + + /** + * 主键 + */ + private String storageId; + + /** + * 权限编码 + */ + private String handlerCode; + + /** + * 权限名称 + */ + private String handlerName; + + /** + * 权限分组 + */ + private String groupName; + + /** + * 创建时间 + */ + private Date createTime; + } + +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/event/ProcessDeleteEvent.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/event/ProcessDeleteEvent.java new file mode 100644 index 000000000..d570c314e --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/event/ProcessDeleteEvent.java @@ -0,0 +1,34 @@ +package org.dromara.common.core.domain.event; + +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; + +/** + * 删除流程监听 + * + * @author AprilWind + */ +@Data +public class ProcessDeleteEvent implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 流程定义编码 + */ + private String flowCode; + + /** + * 业务id + */ + private String businessId; + +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/event/ProcessEvent.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/event/ProcessEvent.java index 61c7efc39..21bfbefa4 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/event/ProcessEvent.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/event/ProcessEvent.java @@ -10,7 +10,6 @@ import java.io.Serializable; * * @author may */ - @Data public class ProcessEvent implements Serializable { @@ -18,14 +17,19 @@ public class ProcessEvent implements Serializable { private static final long serialVersionUID = 1L; /** - * 流程定义key + * 租户ID */ - private String key; + private String tenantId; + + /** + * 流程定义编码 + */ + private String flowCode; /** * 业务id */ - private String businessKey; + private String businessId; /** * 状态 @@ -37,5 +41,4 @@ public class ProcessEvent implements Serializable { */ private boolean submit; - } diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/event/ProcessTaskEvent.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/event/ProcessTaskEvent.java index 019ca823b..33bc6e5a6 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/event/ProcessTaskEvent.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/event/ProcessTaskEvent.java @@ -10,7 +10,6 @@ import java.io.Serializable; * * @author may */ - @Data public class ProcessTaskEvent implements Serializable { @@ -18,23 +17,28 @@ public class ProcessTaskEvent implements Serializable { private static final long serialVersionUID = 1L; /** - * 流程定义key + * 租户ID */ - private String key; + private String tenantId; /** - * 审批节点key + * 流程定义编码 */ - private String taskDefinitionKey; + private String flowCode; + + /** + * 审批节点编码 + */ + private String nodeCode; /** * 任务id */ - private String taskId; + private Long taskId; /** * 业务id */ - private String businessKey; + private String businessId; } diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/model/LoginUser.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/model/LoginUser.java index c723e7668..338d4d70a 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/model/LoginUser.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/model/LoginUser.java @@ -1,8 +1,9 @@ package org.dromara.common.core.domain.model; -import org.dromara.common.core.domain.dto.RoleDTO; import lombok.Data; import lombok.NoArgsConstructor; +import org.dromara.common.core.domain.dto.PostDTO; +import org.dromara.common.core.domain.dto.RoleDTO; import java.io.Serial; import java.io.Serializable; @@ -111,6 +112,11 @@ public class LoginUser implements Serializable { */ private List roles; + /** + * 岗位对象 + */ + private List posts; + /** * 数据权限 当前角色ID */ diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/model/PasswordLoginBody.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/model/PasswordLoginBody.java index 22de8f2c4..87d0e8e73 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/model/PasswordLoginBody.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/model/PasswordLoginBody.java @@ -5,8 +5,6 @@ import lombok.Data; import lombok.EqualsAndHashCode; import org.hibernate.validator.constraints.Length; -import static org.dromara.common.core.constant.UserConstants.*; - /** * 密码登录对象 * @@ -20,14 +18,14 @@ public class PasswordLoginBody extends LoginBody { * 用户名 */ @NotBlank(message = "{user.username.not.blank}") - @Length(min = USERNAME_MIN_LENGTH, max = USERNAME_MAX_LENGTH, message = "{user.username.length.valid}") + @Length(min = 2, max = 20, message = "{user.username.length.valid}") private String username; /** * 用户密码 */ @NotBlank(message = "{user.password.not.blank}") - @Length(min = PASSWORD_MIN_LENGTH, max = PASSWORD_MAX_LENGTH, message = "{user.password.length.valid}") + @Length(min = 5, max = 20, message = "{user.password.length.valid}") private String password; } diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/model/RegisterBody.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/model/RegisterBody.java index 440422bb6..6ea8a764a 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/model/RegisterBody.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/model/RegisterBody.java @@ -5,8 +5,6 @@ import lombok.Data; import lombok.EqualsAndHashCode; import org.hibernate.validator.constraints.Length; -import static org.dromara.common.core.constant.UserConstants.*; - /** * 用户注册对象 * @@ -20,14 +18,14 @@ public class RegisterBody extends LoginBody { * 用户名 */ @NotBlank(message = "{user.username.not.blank}") - @Length(min = USERNAME_MIN_LENGTH, max = USERNAME_MAX_LENGTH, message = "{user.username.length.valid}") + @Length(min = 2, max = 20, message = "{user.username.length.valid}") private String username; /** * 用户密码 */ @NotBlank(message = "{user.password.not.blank}") - @Length(min = PASSWORD_MIN_LENGTH, max = PASSWORD_MAX_LENGTH, message = "{user.password.length.valid}") + @Length(min = 5, max = 20, message = "{user.password.length.valid}") private String password; private String userType; diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/model/TaskAssigneeBody.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/model/TaskAssigneeBody.java new file mode 100644 index 000000000..0cbed2f18 --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/model/TaskAssigneeBody.java @@ -0,0 +1,56 @@ +package org.dromara.common.core.domain.model; + +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serial; +import java.io.Serializable; + +/** + * 任务受让人 + * + * @author AprilWind + */ +@Data +@NoArgsConstructor +public class TaskAssigneeBody implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 权限编码 + */ + private String handlerCode; + + /** + * 权限名称 + */ + private String handlerName; + + /** + * 权限分组 + */ + private String groupId; + + /** + * 开始时间 + */ + private String beginTime; + + /** + * 结束时间 + */ + private String endTime; + + /** + * 当前页 + */ + private Integer pageNum = 1; + + /** + * 每页显示条数 + */ + private Integer pageSize = 10; + +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/enums/BusinessStatusEnum.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/enums/BusinessStatusEnum.java index 0af943a78..c1660ee93 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/enums/BusinessStatusEnum.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/enums/BusinessStatusEnum.java @@ -7,6 +7,10 @@ import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.utils.StringUtils; import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; /** * 业务状态枚举 @@ -16,30 +20,37 @@ import java.util.Arrays; @Getter @AllArgsConstructor public enum BusinessStatusEnum { + /** * 已撤销 */ CANCEL("cancel", "已撤销"), + /** * 草稿 */ DRAFT("draft", "草稿"), + /** * 待审核 */ WAITING("waiting", "待审核"), + /** * 已完成 */ FINISH("finish", "已完成"), + /** * 已作废 */ INVALID("invalid", "已作废"), + /** * 已退回 */ BACK("back", "已退回"), + /** * 已终止 */ @@ -55,20 +66,72 @@ public enum BusinessStatusEnum { */ private final String desc; + private static final Map STATUS_MAP = Arrays.stream(BusinessStatusEnum.values()) + .collect(Collectors.toConcurrentMap(BusinessStatusEnum::getStatus, Function.identity())); + /** - * 获取业务状态 + * 根据状态获取对应的 BusinessStatusEnum 枚举 * - * @param status 状态 + * @param status 业务状态码 + * @return 对应的 BusinessStatusEnum 枚举,如果找不到则返回 null + */ + public static BusinessStatusEnum getByStatus(String status) { + // 使用 STATUS_MAP 获取对应的枚举,若找不到则返回 null + return STATUS_MAP.get(status); + } + + /** + * 根据状态获取对应的业务状态描述信息 + * + * @param status 业务状态码 + * @return 返回业务状态描述,若状态码为空或未找到对应的枚举,返回空字符串 */ public static String findByStatus(String status) { if (StringUtils.isBlank(status)) { return StrUtil.EMPTY; } - return Arrays.stream(BusinessStatusEnum.values()) - .filter(statusEnum -> statusEnum.getStatus().equals(status)) - .findFirst() - .map(BusinessStatusEnum::getDesc) - .orElse(StrUtil.EMPTY); + BusinessStatusEnum statusEnum = STATUS_MAP.get(status); + return (statusEnum != null) ? statusEnum.getDesc() : StrUtil.EMPTY; + } + + /** + * 判断是否为指定的状态之一:草稿、已撤销或已退回 + * + * @param status 要检查的状态 + * @return 如果状态为草稿、已撤销或已退回之一,则返回 true;否则返回 false + */ + public static boolean isDraftOrCancelOrBack(String status) { + return DRAFT.status.equals(status) || CANCEL.status.equals(status) || BACK.status.equals(status); + } + + /** + * 判断是否为撤销,退回,作废,终止 + * + * @param status status + * @return 结果 + */ + public static boolean initialState(String status) { + return CANCEL.status.equals(status) || BACK.status.equals(status) || INVALID.status.equals(status) || TERMINATION.status.equals(status); + } + + /** + * 获取运行中的实例状态列表 + * + * @return 包含运行中实例状态的不可变列表 + * (包含 DRAFT、WAITING、BACK 和 CANCEL 状态) + */ + public static List runningStatus() { + return Arrays.asList(DRAFT.status, WAITING.status, BACK.status, CANCEL.status); + } + + /** + * 获取结束实例的状态列表 + * + * @return 包含结束实例状态的不可变列表 + * (包含 FINISH、INVALID 和 TERMINATION 状态) + */ + public static List finishStatus() { + return Arrays.asList(FINISH.status, INVALID.status, TERMINATION.status); } /** @@ -148,5 +211,5 @@ public enum BusinessStatusEnum { throw new ServiceException("流程状态为空!"); } } -} +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/enums/FormatsType.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/enums/FormatsType.java new file mode 100644 index 000000000..8d4b6d911 --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/enums/FormatsType.java @@ -0,0 +1,146 @@ +package org.dromara.common.core.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.dromara.common.core.utils.StringUtils; + +/* + * 日期格式 + * "yyyy":4位数的年份,例如:2023年表示为"2023"。 + * "yy":2位数的年份,例如:2023年表示为"23"。 + * "MM":2位数的月份,取值范围为01到12,例如:7月表示为"07"。 + * "M":不带前导零的月份,取值范围为1到12,例如:7月表示为"7"。 + * "dd":2位数的日期,取值范围为01到31,例如:22日表示为"22"。 + * "d":不带前导零的日期,取值范围为1到31,例如:22日表示为"22"。 + * "EEEE":星期的全名,例如:星期三表示为"Wednesday"。 + * "E":星期的缩写,例如:星期三表示为"Wed"。 + * "DDD" 或 "D":一年中的第几天,取值范围为001到366,例如:第200天表示为"200"。 + * 时间格式 + * "HH":24小时制的小时数,取值范围为00到23,例如:下午5点表示为"17"。 + * "hh":12小时制的小时数,取值范围为01到12,例如:下午5点表示为"05"。 + * "mm":分钟数,取值范围为00到59,例如:30分钟表示为"30"。 + * "ss":秒数,取值范围为00到59,例如:45秒表示为"45"。 + * "SSS":毫秒数,取值范围为000到999,例如:123毫秒表示为"123"。 + */ + +/** + * 日期格式与时间格式枚举 + */ +@Getter +@AllArgsConstructor +public enum FormatsType { + + /** + * 例如:2023年表示为"23" + */ + YY("yy"), + + /** + * 例如:2023年表示为"2023" + */ + YYYY("yyyy"), + + /** + * 例例如,2023年7月可以表示为 "2023-07" + */ + YYYY_MM("yyyy-MM"), + + /** + * 例如,日期 "2023年7月22日" 可以表示为 "2023-07-22" + */ + YYYY_MM_DD("yyyy-MM-dd"), + + /** + * 例如,当前时间如果是 "2023年7月22日下午3点30分",则可以表示为 "2023-07-22 15:30" + */ + YYYY_MM_DD_HH_MM("yyyy-MM-dd HH:mm"), + + /** + * 例如,当前时间如果是 "2023年7月22日下午3点30分45秒",则可以表示为 "2023-07-22 15:30:45" + */ + YYYY_MM_DD_HH_MM_SS("yyyy-MM-dd HH:mm:ss"), + + /** + * 例如:下午3点30分45秒,表示为 "15:30:45" + */ + HH_MM_SS("HH:mm:ss"), + + /** + * 例例如,2023年7月可以表示为 "2023/07" + */ + YYYY_MM_SLASH("yyyy/MM"), + + /** + * 例如,日期 "2023年7月22日" 可以表示为 "2023/07/22" + */ + YYYY_MM_DD_SLASH("yyyy/MM/dd"), + + /** + * 例如,当前时间如果是 "2023年7月22日下午3点30分45秒",则可以表示为 "2023/07/22 15:30:45" + */ + YYYY_MM_DD_HH_MM_SLASH("yyyy/MM/dd HH:mm"), + + /** + * 例如,当前时间如果是 "2023年7月22日下午3点30分45秒",则可以表示为 "2023/07/22 15:30:45" + */ + YYYY_MM_DD_HH_MM_SS_SLASH("yyyy/MM/dd HH:mm:ss"), + + /** + * 例例如,2023年7月可以表示为 "2023.07" + */ + YYYY_MM_DOT("yyyy.MM"), + + /** + * 例如,日期 "2023年7月22日" 可以表示为 "2023.07.22" + */ + YYYY_MM_DD_DOT("yyyy.MM.dd"), + + /** + * 例如,当前时间如果是 "2023年7月22日下午3点30分",则可以表示为 "2023.07.22 15:30" + */ + YYYY_MM_DD_HH_MM_DOT("yyyy.MM.dd HH:mm"), + + /** + * 例如,当前时间如果是 "2023年7月22日下午3点30分45秒",则可以表示为 "2023.07.22 15:30:45" + */ + YYYY_MM_DD_HH_MM_SS_DOT("yyyy.MM.dd HH:mm:ss"), + + /** + * 例如,2023年7月可以表示为 "202307" + */ + YYYYMM("yyyyMM"), + + /** + * 例如,2023年7月22日可以表示为 "20230722" + */ + YYYYMMDD("yyyyMMdd"), + + /** + * 例如,2023年7月22日下午3点可以表示为 "2023072215" + */ + YYYYMMDDHH("yyyyMMddHH"), + + /** + * 例如,2023年7月22日下午3点30分可以表示为 "202307221530" + */ + YYYYMMDDHHMM("yyyyMMddHHmm"), + + /** + * 例如,2023年7月22日下午3点30分45秒可以表示为 "20230722153045" + */ + YYYYMMDDHHMMSS("yyyyMMddHHmmss"); + + /** + * 时间格式 + */ + private final String timeFormat; + + public static FormatsType getFormatsType(String str) { + for (FormatsType value : values()) { + if (StringUtils.contains(str, value.getTimeFormat())) { + return value; + } + } + throw new RuntimeException("'FormatsType' not found By " + str); + } +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/enums/TenantStatus.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/enums/TenantStatus.java deleted file mode 100644 index 400a3996a..000000000 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/enums/TenantStatus.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.dromara.common.core.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * 用户状态 - * - * @author LionLi - */ -@Getter -@AllArgsConstructor -public enum TenantStatus { - /** - * 正常 - */ - OK("0", "正常"), - /** - * 停用 - */ - DISABLE("1", "停用"), - /** - * 删除 - */ - DELETED("2", "删除"); - - private final String code; - private final String info; - -} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/DeptService.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/DeptService.java index db9463e79..f93d1778a 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/DeptService.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/DeptService.java @@ -1,5 +1,9 @@ package org.dromara.common.core.service; +import org.dromara.common.core.domain.dto.DeptDTO; + +import java.util.List; + /** * 通用 部门服务 * @@ -15,4 +19,19 @@ public interface DeptService { */ String selectDeptNameByIds(String deptIds); + /** + * 根据部门ID查询部门负责人 + * + * @param deptId 部门ID,用于指定需要查询的部门 + * @return 返回该部门的负责人ID + */ + Long selectDeptLeaderById(Long deptId); + + /** + * 查询部门 + * + * @return 部门列表 + */ + List selectDeptsByList(); + } diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/PostService.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/PostService.java new file mode 100644 index 000000000..41d4e8308 --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/PostService.java @@ -0,0 +1,10 @@ +package org.dromara.common.core.service; + +/** + * 通用 岗位服务 + * + * @author AprilWind + */ +public interface PostService { + +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/RoleService.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/RoleService.java new file mode 100644 index 000000000..ba62c82ae --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/RoleService.java @@ -0,0 +1,10 @@ +package org.dromara.common.core.service; + +/** + * 通用 角色服务 + * + * @author AprilWind + */ +public interface RoleService { + +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/TaskAssigneeService.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/TaskAssigneeService.java new file mode 100644 index 000000000..9af669111 --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/TaskAssigneeService.java @@ -0,0 +1,45 @@ +package org.dromara.common.core.service; + +import org.dromara.common.core.domain.dto.TaskAssigneeDTO; +import org.dromara.common.core.domain.model.TaskAssigneeBody; + +/** + * 工作流设计器获取任务执行人 + * + * @author Lion Li + */ +public interface TaskAssigneeService { + + /** + * 查询角色并返回任务指派的列表,支持分页 + * + * @param taskQuery 查询条件 + * @return 办理人 + */ + TaskAssigneeDTO selectRolesByTaskAssigneeList(TaskAssigneeBody taskQuery); + + /** + * 查询岗位并返回任务指派的列表,支持分页 + * + * @param taskQuery 查询条件 + * @return 办理人 + */ + TaskAssigneeDTO selectPostsByTaskAssigneeList(TaskAssigneeBody taskQuery); + + /** + * 查询部门并返回任务指派的列表,支持分页 + * + * @param taskQuery 查询条件 + * @return 办理人 + */ + TaskAssigneeDTO selectDeptsByTaskAssigneeList(TaskAssigneeBody taskQuery); + + /** + * 查询用户并返回任务指派的列表,支持分页 + * + * @param taskQuery 查询条件 + * @return 办理人 + */ + TaskAssigneeDTO selectUsersByTaskAssigneeList(TaskAssigneeBody taskQuery); + +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/UserService.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/UserService.java index 43aef28cb..67cd54fba 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/UserService.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/UserService.java @@ -82,4 +82,13 @@ public interface UserService { * @return 用户 */ List selectUsersByDeptIds(List deptIds); + + /** + * 通过岗位ID查询用户 + * + * @param postIds 岗位ids + * @return 用户 + */ + List selectUsersByPostIds(List postIds); + } diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/WorkflowService.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/WorkflowService.java index 4e556c9cb..565362e56 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/WorkflowService.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/WorkflowService.java @@ -1,5 +1,8 @@ package org.dromara.common.core.service; +import org.dromara.common.core.domain.dto.CompleteTaskDTO; +import org.dromara.common.core.domain.dto.StartProcessDTO; + import java.util.List; import java.util.Map; @@ -13,64 +16,63 @@ public interface WorkflowService { /** * 运行中的实例 删除程实例,删除历史记录,删除业务与流程关联信息 * - * @param businessKeys 业务id + * @param businessIds 业务id * @return 结果 */ - boolean deleteRunAndHisInstance(List businessKeys); + boolean deleteInstance(List businessIds); /** * 获取当前流程状态 * * @param taskId 任务id + * @return 状态 */ - String getBusinessStatusByTaskId(String taskId); + String getBusinessStatusByTaskId(Long taskId); /** * 获取当前流程状态 * - * @param businessKey 业务id + * @param businessId 业务id + * @return 状态 */ - String getBusinessStatus(String businessKey); + String getBusinessStatus(String businessId); /** - * 设置流程变量(全局变量) + * 设置流程变量 * - * @param taskId 任务id - * @param variableName 变量名称 - * @param value 变量值 + * @param instanceId 流程实例id + * @param variable 流程变量 */ - void setVariable(String taskId, String variableName, Object value); - - /** - * 设置流程变量(全局变量) - * - * @param taskId 任务id - * @param variables 流程变量 - */ - void setVariables(String taskId, Map variables); - - /** - * 设置流程变量(本地变量,非全局变量) - * - * @param taskId 任务id - * @param variableName 变量名称 - * @param value 变量值 - */ - void setVariableLocal(String taskId, String variableName, Object value); - - /** - * 设置流程变量(本地变量,非全局变量) - * - * @param taskId 任务id - * @param variables 流程变量 - */ - void setVariablesLocal(String taskId, Map variables); + void setVariable(Long instanceId, Map variable); /** * 按照业务id查询流程实例id * - * @param businessKey 业务id + * @param businessId 业务id * @return 结果 */ - String getInstanceIdByBusinessKey(String businessKey); + Long getInstanceIdByBusinessId(String businessId); + + /** + * 新增租户流程定义 + * + * @param tenantId 租户id + */ + void syncDef(String tenantId); + + /** + * 启动流程 + * + * @param startProcess 参数 + * @return 结果 + */ + Map startWorkFlow(StartProcessDTO startProcess); + + /** + * 办理任务 + * + * @param completeTask 参数 + * @return 结果 + */ + boolean completeTask(CompleteTaskDTO completeTask); } diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/DateUtils.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/DateUtils.java index 72178a7b6..41d0f6c25 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/DateUtils.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/DateUtils.java @@ -1,106 +1,157 @@ package org.dromara.common.core.utils; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; import org.apache.commons.lang3.time.DateFormatUtils; +import org.dromara.common.core.enums.FormatsType; +import org.dromara.common.core.exception.ServiceException; import java.lang.management.ManagementFactory; import java.text.ParseException; import java.text.SimpleDateFormat; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.ZoneId; -import java.time.ZonedDateTime; +import java.time.*; import java.util.Date; +import java.util.concurrent.TimeUnit; /** * 时间工具类 * * @author ruoyi */ -@NoArgsConstructor(access = AccessLevel.PRIVATE) public class DateUtils extends org.apache.commons.lang3.time.DateUtils { - - public static final String YYYY = "yyyy"; - - public static final String YYYY_MM = "yyyy-MM"; - - public static final String YYYY_MM_DD = "yyyy-MM-dd"; - - public static final String YYYYMMDDHHMMSS = "yyyyMMddHHmmss"; - - public static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss"; - private static final String[] PARSE_PATTERNS = { "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM", "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM", "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"}; + @Deprecated + private DateUtils() { + } + /** - * 获取当前Date型日期 + * 获取当前日期和时间 * - * @return Date() 当前日期 + * @return 当前日期和时间的 Date 对象表示 */ public static Date getNowDate() { return new Date(); } /** - * 获取当前日期, 默认格式为yyyy-MM-dd + * 获取当前日期的字符串表示,格式为YYYY-MM-DD * - * @return String + * @return 当前日期的字符串表示 */ public static String getDate() { - return dateTimeNow(YYYY_MM_DD); + return dateTimeNow(FormatsType.YYYY_MM_DD); } + /** + * 获取当前日期的字符串表示,格式为yyyyMMdd + * + * @return 当前日期的字符串表示 + */ + public static String getCurrentDate() { + return DateFormatUtils.format(new Date(), FormatsType.YYYYMMDD.getTimeFormat()); + } + + /** + * 获取当前日期的路径格式字符串,格式为"yyyy/MM/dd" + * + * @return 当前日期的路径格式字符串 + */ + public static String datePath() { + Date now = new Date(); + return DateFormatUtils.format(now, FormatsType.YYYY_MM_DD_SLASH.getTimeFormat()); + } + + /** + * 获取当前时间的字符串表示,格式为YYYY-MM-DD HH:MM:SS + * + * @return 当前时间的字符串表示 + */ public static String getTime() { - return dateTimeNow(YYYY_MM_DD_HH_MM_SS); + return dateTimeNow(FormatsType.YYYY_MM_DD_HH_MM_SS); } + /** + * 获取当前时间的字符串表示,格式为 "HH:MM:SS" + * + * @return 当前时间的字符串表示,格式为 "HH:MM:SS" + */ + public static String getTimeWithHourMinuteSecond() { + return dateTimeNow(FormatsType.HH_MM_SS); + } + + /** + * 获取当前日期和时间的字符串表示,格式为YYYYMMDDHHMMSS + * + * @return 当前日期和时间的字符串表示 + */ public static String dateTimeNow() { - return dateTimeNow(YYYYMMDDHHMMSS); + return dateTimeNow(FormatsType.YYYYMMDDHHMMSS); } - public static String dateTimeNow(final String format) { + /** + * 获取当前日期和时间的指定格式的字符串表示 + * + * @param format 日期时间格式,例如"YYYY-MM-DD HH:MM:SS" + * @return 当前日期和时间的字符串表示 + */ + public static String dateTimeNow(final FormatsType format) { return parseDateToStr(format, new Date()); } - public static String dateTime(final Date date) { - return parseDateToStr(YYYY_MM_DD, date); + /** + * 将指定日期格式化为 YYYY-MM-DD 格式的字符串 + * + * @param date 要格式化的日期对象 + * @return 格式化后的日期字符串 + */ + public static String formatDate(final Date date) { + return parseDateToStr(FormatsType.YYYY_MM_DD, date); } - public static String parseDateToStr(final String format, final Date date) { - return new SimpleDateFormat(format).format(date); + /** + * 将指定日期格式化为 YYYY-MM-DD HH:MM:SS 格式的字符串 + * + * @param date 要格式化的日期对象 + * @return 格式化后的日期时间字符串 + */ + public static String formatDateTime(final Date date) { + return parseDateToStr(FormatsType.YYYY_MM_DD_HH_MM_SS, date); } - public static Date dateTime(final String format, final String ts) { + /** + * 将指定日期按照指定格式进行格式化 + * + * @param format 要使用的日期时间格式,例如"YYYY-MM-DD HH:MM:SS" + * @param date 要格式化的日期对象 + * @return 格式化后的日期时间字符串 + */ + public static String parseDateToStr(final FormatsType format, final Date date) { + return new SimpleDateFormat(format.getTimeFormat()).format(date); + } + + /** + * 将指定格式的日期时间字符串转换为 Date 对象 + * + * @param format 要解析的日期时间格式,例如"YYYY-MM-DD HH:MM:SS" + * @param ts 要解析的日期时间字符串 + * @return 解析后的 Date 对象 + * @throws RuntimeException 如果解析过程中发生异常 + */ + public static Date parseDateTime(final FormatsType format, final String ts) { try { - return new SimpleDateFormat(format).parse(ts); + return new SimpleDateFormat(format.getTimeFormat()).parse(ts); } catch (ParseException e) { throw new RuntimeException(e); } } /** - * 日期路径 即年/月/日 如2018/08/08 - */ - public static String datePath() { - Date now = new Date(); - return DateFormatUtils.format(now, "yyyy/MM/dd"); - } - - /** - * 日期路径 即年/月/日 如20180808 - */ - public static String dateTime() { - Date now = new Date(); - return DateFormatUtils.format(now, "yyyyMMdd"); - } - - /** - * 日期型字符串转化为日期 格式 + * 将对象转换为日期对象 + * + * @param str 要转换的对象,通常是字符串 + * @return 转换后的日期对象,如果转换失败或输入为null,则返回null */ public static Date parseDate(Object str) { if (str == null) { @@ -115,6 +166,8 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils { /** * 获取服务器启动时间 + * + * @return 服务器启动时间的 Date 对象表示 */ public static Date getServerStartDate() { long time = ManagementFactory.getRuntimeMXBean().getStartTime(); @@ -122,35 +175,66 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils { } /** - * 计算相差天数 + * 计算两个日期之间的天数差(以毫秒为单位) + * + * @param date1 第一个日期 + * @param date2 第二个日期 + * @return 两个日期之间的天数差的绝对值 */ public static int differentDaysByMillisecond(Date date1, Date date2) { return Math.abs((int) ((date2.getTime() - date1.getTime()) / (1000 * 3600 * 24))); } /** - * 计算两个时间差 + * 计算两个日期之间的时间差,并以天、小时和分钟的格式返回 + * + * @param endDate 结束日期 + * @param nowDate 当前日期 + * @return 表示时间差的字符串,格式为"天 小时 分钟" */ public static String getDatePoor(Date endDate, Date nowDate) { - long nd = 1000 * 24 * 60 * 60; - long nh = 1000 * 60 * 60; - long nm = 1000 * 60; - // long ns = 1000; - // 获得两个时间的毫秒时间差异 - long diff = endDate.getTime() - nowDate.getTime(); - // 计算差多少天 - long day = diff / nd; - // 计算差多少小时 - long hour = diff % nd / nh; - // 计算差多少分钟 - long min = diff % nd % nh / nm; - // 计算差多少秒//输出结果 - // long sec = diff % nd % nh % nm / ns; - return day + "天" + hour + "小时" + min + "分钟"; + long diffInMillis = endDate.getTime() - nowDate.getTime(); + long day = TimeUnit.MILLISECONDS.toDays(diffInMillis); + long hour = TimeUnit.MILLISECONDS.toHours(diffInMillis) % 24; + long min = TimeUnit.MILLISECONDS.toMinutes(diffInMillis) % 60; + return String.format("%d天 %d小时 %d分钟", day, hour, min); } /** - * 增加 LocalDateTime ==> Date + * 计算两个时间点的差值(天、小时、分钟、秒),当值为0时不显示该单位 + * + * @param endDate 结束时间 + * @param nowDate 当前时间 + * @return 时间差字符串,格式为 "x天 x小时 x分钟 x秒",若为 0 则不显示 + */ + public static String getTimeDifference(Date endDate, Date nowDate) { + long diffInMillis = endDate.getTime() - nowDate.getTime(); + long day = TimeUnit.MILLISECONDS.toDays(diffInMillis); + long hour = TimeUnit.MILLISECONDS.toHours(diffInMillis) % 24; + long min = TimeUnit.MILLISECONDS.toMinutes(diffInMillis) % 60; + long sec = TimeUnit.MILLISECONDS.toSeconds(diffInMillis) % 60; + // 构建时间差字符串,条件是值不为0才显示 + StringBuilder result = new StringBuilder(); + if (day > 0) { + result.append(String.format("%d天 ", day)); + } + if (hour > 0) { + result.append(String.format("%d小时 ", hour)); + } + if (min > 0) { + result.append(String.format("%d分钟 ", min)); + } + if (sec > 0) { + result.append(String.format("%d秒", sec)); + } + return result.length() > 0 ? result.toString().trim() : "0秒"; + } + + /** + * 将 LocalDateTime 对象转换为 Date 对象 + * + * @param temporalAccessor 要转换的 LocalDateTime 对象 + * @return 转换后的 Date 对象 */ public static Date toDate(LocalDateTime temporalAccessor) { ZonedDateTime zdt = temporalAccessor.atZone(ZoneId.systemDefault()); @@ -158,11 +242,46 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils { } /** - * 增加 LocalDate ==> Date + * 将 LocalDate 对象转换为 Date 对象 + * + * @param temporalAccessor 要转换的 LocalDate 对象 + * @return 转换后的 Date 对象 */ public static Date toDate(LocalDate temporalAccessor) { LocalDateTime localDateTime = LocalDateTime.of(temporalAccessor, LocalTime.of(0, 0, 0)); ZonedDateTime zdt = localDateTime.atZone(ZoneId.systemDefault()); return Date.from(zdt.toInstant()); } + + /** + * 校验日期范围 + * + * @param startDate 开始日期 + * @param endDate 结束日期 + * @param maxValue 最大时间跨度的限制值 + * @param unit 时间跨度的单位,可选择 "DAYS"、"HOURS" 或 "MINUTES" + */ + public static void validateDateRange(Date startDate, Date endDate, int maxValue, TimeUnit unit) { + // 校验结束日期不能早于开始日期 + if (endDate.before(startDate)) { + throw new ServiceException("结束日期不能早于开始日期"); + } + + // 计算时间跨度 + long diffInMillis = endDate.getTime() - startDate.getTime(); + + // 根据单位转换时间跨度 + long diff = switch (unit) { + case DAYS -> TimeUnit.MILLISECONDS.toDays(diffInMillis); + case HOURS -> TimeUnit.MILLISECONDS.toHours(diffInMillis); + case MINUTES -> TimeUnit.MILLISECONDS.toMinutes(diffInMillis); + default -> throw new IllegalArgumentException("不支持的时间单位"); + }; + + // 校验时间跨度不超过最大限制 + if (diff > maxValue) { + throw new ServiceException("最大时间跨度为 " + maxValue + " " + unit.toString().toLowerCase()); + } + } + } diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/ObjectUtils.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/ObjectUtils.java new file mode 100644 index 000000000..93617b018 --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/ObjectUtils.java @@ -0,0 +1,60 @@ +package org.dromara.common.core.utils; + +import cn.hutool.core.util.ObjectUtil; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +import java.util.function.Function; + +/** + * 对象工具类 + * + * @author 秋辞未寒 + */ +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class ObjectUtils extends ObjectUtil { + + /** + * 如果对象不为空,则获取对象中的某个字段 ObjectUtils.notNullGetter(user, User::getName); + * + * @param obj 对象 + * @param func 获取方法 + * @return 对象字段 + */ + public static E notNullGetter(T obj, Function func) { + if (isNotNull(obj) && isNotNull(func)) { + return func.apply(obj); + } + return null; + } + + /** + * 如果对象不为空,则获取对象中的某个字段,否则返回默认值 + * + * @param obj 对象 + * @param func 获取方法 + * @param defaultValue 默认值 + * @return 对象字段 + */ + public static E notNullGetter(T obj, Function func, E defaultValue) { + if (isNotNull(obj) && isNotNull(func)) { + return func.apply(obj); + } + return defaultValue; + } + + /** + * 如果值不为空,则返回值,否则返回默认值 + * + * @param obj 对象 + * @param defaultValue 默认值 + * @return 对象字段 + */ + public static T notNull(T obj, T defaultValue) { + if (isNotNull(obj)) { + return obj; + } + return defaultValue; + } + +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/ServletUtils.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/ServletUtils.java index a1316eb85..bd1aab808 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/ServletUtils.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/ServletUtils.java @@ -25,7 +25,7 @@ import java.util.HashMap; import java.util.Map; /** - * 客户端工具类 + * 客户端工具类,提供获取请求参数、响应处理、头部信息等常用操作 * * @author ruoyi */ @@ -33,52 +33,73 @@ import java.util.Map; public class ServletUtils extends JakartaServletUtil { /** - * 获取String参数 + * 获取指定名称的 String 类型的请求参数 + * + * @param name 参数名 + * @return 参数值 */ public static String getParameter(String name) { return getRequest().getParameter(name); } /** - * 获取String参数 + * 获取指定名称的 String 类型的请求参数,若参数不存在,则返回默认值 + * + * @param name 参数名 + * @param defaultValue 默认值 + * @return 参数值或默认值 */ public static String getParameter(String name, String defaultValue) { return Convert.toStr(getRequest().getParameter(name), defaultValue); } /** - * 获取Integer参数 + * 获取指定名称的 Integer 类型的请求参数 + * + * @param name 参数名 + * @return 参数值 */ public static Integer getParameterToInt(String name) { return Convert.toInt(getRequest().getParameter(name)); } /** - * 获取Integer参数 + * 获取指定名称的 Integer 类型的请求参数,若参数不存在,则返回默认值 + * + * @param name 参数名 + * @param defaultValue 默认值 + * @return 参数值或默认值 */ public static Integer getParameterToInt(String name, Integer defaultValue) { return Convert.toInt(getRequest().getParameter(name), defaultValue); } /** - * 获取Boolean参数 + * 获取指定名称的 Boolean 类型的请求参数 + * + * @param name 参数名 + * @return 参数值 */ public static Boolean getParameterToBool(String name) { return Convert.toBool(getRequest().getParameter(name)); } /** - * 获取Boolean参数 + * 获取指定名称的 Boolean 类型的请求参数,若参数不存在,则返回默认值 + * + * @param name 参数名 + * @param defaultValue 默认值 + * @return 参数值或默认值 */ public static Boolean getParameterToBool(String name, Boolean defaultValue) { return Convert.toBool(getRequest().getParameter(name), defaultValue); } /** - * 获得所有请求参数 + * 获取所有请求参数(以 Map 的形式返回) * * @param request 请求对象{@link ServletRequest} - * @return Map + * @return 请求参数的 Map,键为参数名,值为参数值数组 */ public static Map getParams(ServletRequest request) { final Map map = request.getParameterMap(); @@ -86,10 +107,10 @@ public class ServletUtils extends JakartaServletUtil { } /** - * 获得所有请求参数 + * 获取所有请求参数(以 Map 的形式返回,值为字符串形式的拼接) * * @param request 请求对象{@link ServletRequest} - * @return Map + * @return 请求参数的 Map,键为参数名,值为拼接后的字符串 */ public static Map getParamMap(ServletRequest request) { Map params = new HashMap<>(); @@ -100,7 +121,9 @@ public class ServletUtils extends JakartaServletUtil { } /** - * 获取request + * 获取当前 HTTP 请求对象 + * + * @return 当前 HTTP 请求对象 */ public static HttpServletRequest getRequest() { try { @@ -111,7 +134,9 @@ public class ServletUtils extends JakartaServletUtil { } /** - * 获取response + * 获取当前 HTTP 响应对象 + * + * @return 当前 HTTP 响应对象 */ public static HttpServletResponse getResponse() { try { @@ -122,12 +147,25 @@ public class ServletUtils extends JakartaServletUtil { } /** - * 获取session + * 获取当前请求的 HttpSession 对象 + *

+ * 如果当前请求已经关联了一个会话(即已经存在有效的 session ID), + * 则返回该会话对象;如果没有关联会话,则会创建一个新的会话对象并返回。 + *

+ * HttpSession 用于存储会话级别的数据,如用户登录信息、购物车内容等, + * 可以在多个请求之间共享会话数据 + * + * @return 当前请求的 HttpSession 对象 */ public static HttpSession getSession() { return getRequest().getSession(); } + /** + * 获取当前请求的请求属性 + * + * @return {@link ServletRequestAttributes} 请求属性对象 + */ public static ServletRequestAttributes getRequestAttributes() { try { RequestAttributes attributes = RequestContextHolder.getRequestAttributes(); @@ -137,6 +175,13 @@ public class ServletUtils extends JakartaServletUtil { } } + /** + * 获取指定请求头的值,如果头部为空则返回空字符串 + * + * @param request 请求对象 + * @param name 头部名称 + * @return 头部值 + */ public static String getHeader(HttpServletRequest request, String name) { String value = request.getHeader(name); if (StringUtils.isEmpty(value)) { @@ -145,6 +190,12 @@ public class ServletUtils extends JakartaServletUtil { return urlDecode(value); } + /** + * 获取所有请求头的 Map,键为头部名称,值为头部值 + * + * @param request 请求对象 + * @return 请求头的 Map + */ public static Map getHeaders(HttpServletRequest request) { Map map = new LinkedCaseInsensitiveMap<>(); Enumeration enumeration = request.getHeaderNames(); @@ -159,7 +210,7 @@ public class ServletUtils extends JakartaServletUtil { } /** - * 将字符串渲染到客户端 + * 将字符串渲染到客户端(以 JSON 格式返回) * * @param response 渲染对象 * @param string 待渲染的字符串 @@ -176,37 +227,47 @@ public class ServletUtils extends JakartaServletUtil { } /** - * 是否是Ajax异步请求 + * 判断当前请求是否为 Ajax 异步请求 * - * @param request + * @param request 请求对象 + * @return 是否为 Ajax 请求 */ public static boolean isAjaxRequest(HttpServletRequest request) { + // 判断 Accept 头部是否包含 application/json String accept = request.getHeader("accept"); if (accept != null && accept.contains(MediaType.APPLICATION_JSON_VALUE)) { return true; } + // 判断 X-Requested-With 头部是否包含 XMLHttpRequest String xRequestedWith = request.getHeader("X-Requested-With"); if (xRequestedWith != null && xRequestedWith.contains("XMLHttpRequest")) { return true; } + // 判断 URI 后缀是否为 .json 或 .xml String uri = request.getRequestURI(); if (StringUtils.equalsAnyIgnoreCase(uri, ".json", ".xml")) { return true; } + // 判断请求参数 __ajax 是否为 json 或 xml String ajax = request.getParameter("__ajax"); return StringUtils.equalsAnyIgnoreCase(ajax, "json", "xml"); } + /** + * 获取客户端 IP 地址 + * + * @return 客户端 IP 地址 + */ public static String getClientIP() { return getClientIP(getRequest()); } /** - * 内容编码 + * 对内容进行 URL 编码 * * @param str 内容 * @return 编码后的内容 @@ -216,7 +277,7 @@ public class ServletUtils extends JakartaServletUtil { } /** - * 内容解码 + * 对内容进行 URL 解码 * * @param str 内容 * @return 解码后的内容 diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/StringUtils.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/StringUtils.java index dd6ebb119..506bf08d5 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/StringUtils.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/StringUtils.java @@ -4,8 +4,6 @@ import cn.hutool.core.collection.CollUtil; import cn.hutool.core.convert.Convert; import cn.hutool.core.lang.Validator; import cn.hutool.core.util.StrUtil; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; import org.springframework.util.AntPathMatcher; import java.util.*; @@ -17,13 +15,16 @@ import java.util.stream.Collectors; * * @author Lion Li */ -@NoArgsConstructor(access = AccessLevel.PRIVATE) public class StringUtils extends org.apache.commons.lang3.StringUtils { public static final String SEPARATOR = ","; public static final String SLASH = "/"; + @Deprecated + private StringUtils() { + } + /** * 获取参数不为空值 * @@ -320,4 +321,21 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils { .collect(Collectors.toList()); } + /** + * 不区分大小写检查 CharSequence 是否以指定的前缀开头。 + * + * @param str 要检查的 CharSequence 可能为 null + * @param prefixs 要查找的前缀可能为 null + * @return 是否包含 + */ + public static boolean startWithAnyIgnoreCase(CharSequence str, CharSequence... prefixs) { + // 判断是否是以指定字符串开头 + for (CharSequence prefix : prefixs) { + if (StringUtils.startsWithIgnoreCase(str, prefix)) { + return true; + } + } + return false; + } + } diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/Threads.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/Threads.java index ae6cfa322..82ea5caf1 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/Threads.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/Threads.java @@ -14,18 +14,6 @@ import java.util.concurrent.*; @Slf4j @NoArgsConstructor(access = AccessLevel.PRIVATE) public class Threads { - - /** - * sleep等待,单位为毫秒 - */ - public static void sleep(long milliseconds) { - try { - Thread.sleep(milliseconds); - } catch (InterruptedException e) { - return; - } - } - /** * 停止线程池 * 先使用shutdown, 停止接收新任务并尝试完成所有已存在任务. diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/TreeBuildUtils.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/TreeBuildUtils.java index 8e501dfea..2ab42cbc1 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/TreeBuildUtils.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/TreeBuildUtils.java @@ -43,6 +43,23 @@ public class TreeBuildUtils extends TreeUtil { return TreeUtil.build(list, k, DEFAULT_CONFIG, nodeParser); } + /** + * 构建树形结构 + * + * @param 输入节点的类型 + * @param 节点ID的类型 + * @param parentId 顶级节点 + * @param list 节点列表,其中包含了要构建树形结构的所有节点 + * @param nodeParser 解析器,用于将输入节点转换为树节点 + * @return 构建好的树形结构列表 + */ + public static List> build(List list, K parentId, NodeParser nodeParser) { + if (CollUtil.isEmpty(list)) { + return CollUtil.newArrayList(); + } + return TreeUtil.build(list, parentId, DEFAULT_CONFIG, nodeParser); + } + /** * 获取节点列表中所有节点的叶子节点 * diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/sql/SqlUtil.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/sql/SqlUtil.java index fcf9fb4b6..1020c81eb 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/sql/SqlUtil.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/sql/SqlUtil.java @@ -15,7 +15,7 @@ public class SqlUtil { /** * 定义常用的 sql关键字 */ - public static String SQL_REGEX = "and |extractvalue|updatexml|sleep|exec |insert |select |delete |update |drop |count |chr |mid |master |truncate |char |declare |or |union |like |+|/*|user()"; + public static String SQL_REGEX = "\u000B|and |extractvalue|updatexml|sleep|exec |insert |select |delete |update |drop |count |chr |mid |master |truncate |char |declare |or |union |like |+|/*|user()"; /** * 仅支持字母、数字、下划线、空格、逗号、小数点(支持多个字段排序) diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/validate/enumd/EnumPattern.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/validate/enumd/EnumPattern.java new file mode 100644 index 000000000..d4f1c3d01 --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/validate/enumd/EnumPattern.java @@ -0,0 +1,48 @@ +package org.dromara.common.core.validate.enumd; + +import jakarta.validation.Constraint; +import jakarta.validation.Payload; + +import java.lang.annotation.*; + +import static java.lang.annotation.ElementType.*; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * 自定义枚举校验 + * + * @author 秋辞未寒 + * @date 2024-12-09 + */ +@Documented +@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE}) +@Retention(RUNTIME) +@Repeatable(EnumPattern.List.class) // 允许在同一元素上多次使用该注解 +@Constraint(validatedBy = {EnumPatternValidator.class}) +public @interface EnumPattern { + + /** + * 需要校验的枚举类型 + */ + Class> type(); + + /** + * 枚举类型校验值字段名称 + * 需确保该字段实现了 getter 方法 + */ + String fieldName(); + + String message() default "输入值不在枚举范围内"; + + Class[] groups() default {}; + + Class[] payload() default {}; + + @Documented + @Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE}) + @Retention(RUNTIME) + @interface List { + EnumPattern[] value(); + } + +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/validate/enumd/EnumPatternValidator.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/validate/enumd/EnumPatternValidator.java new file mode 100644 index 000000000..6cfa11a33 --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/validate/enumd/EnumPatternValidator.java @@ -0,0 +1,37 @@ +package org.dromara.common.core.validate.enumd; + +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.core.utils.reflect.ReflectUtils; + +/** + * 自定义枚举校验注解实现 + * + * @author 秋辞未寒 + * @date 2024-12-09 + */ +public class EnumPatternValidator implements ConstraintValidator { + + private EnumPattern annotation;; + + @Override + public void initialize(EnumPattern annotation) { + ConstraintValidator.super.initialize(annotation); + this.annotation = annotation; + } + + @Override + public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext) { + if (StringUtils.isNotBlank(value)) { + String fieldName = annotation.fieldName(); + for (Object e : annotation.type().getEnumConstants()) { + if (value.equals(ReflectUtils.invokeGetter(e, fieldName))) { + return true; + } + } + } + return false; + } + +} diff --git a/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/core/EncryptorManager.java b/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/core/EncryptorManager.java index 2d795e074..b5f194d76 100644 --- a/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/core/EncryptorManager.java +++ b/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/core/EncryptorManager.java @@ -1,11 +1,11 @@ package org.dromara.common.encrypt.core; import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ReflectUtil; import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.ibatis.io.Resources; +import org.dromara.common.core.utils.ObjectUtils; import org.dromara.common.core.utils.StringUtils; import org.dromara.common.encrypt.annotation.EncryptField; import org.springframework.context.ConfigurableApplicationContext; @@ -58,10 +58,7 @@ public class EncryptorManager { * 获取类加密字段缓存 */ public Set getFieldCache(Class sourceClazz) { - if (ObjectUtil.isNotNull(fieldCache)) { - return fieldCache.get(sourceClazz); - } - return null; + return ObjectUtils.notNullGetter(fieldCache, f -> f.get(sourceClazz)); } /** diff --git a/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/utils/EncryptUtils.java b/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/utils/EncryptUtils.java index 8e34843a7..2a096eea7 100644 --- a/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/utils/EncryptUtils.java +++ b/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/utils/EncryptUtils.java @@ -19,10 +19,12 @@ import java.util.Map; * @author 老马 */ public class EncryptUtils { + /** * 公钥 */ public static final String PUBLIC_KEY = "publicKey"; + /** * 私钥 */ @@ -51,7 +53,7 @@ public class EncryptUtils { /** * AES加密 * - * @param data 待解密数据 + * @param data 待加密数据 * @param password 秘钥字符串 * @return 加密后字符串, 采用Base64编码 */ @@ -70,7 +72,7 @@ public class EncryptUtils { /** * AES加密 * - * @param data 待解密数据 + * @param data 待加密数据 * @param password 秘钥字符串 * @return 加密后字符串, 采用Hex编码 */ @@ -208,7 +210,7 @@ public class EncryptUtils { /** * sm2私钥解密 * - * @param data 待加密数据 + * @param data 待解密数据 * @param privateKey 私钥 * @return 解密后字符串 */ @@ -266,7 +268,7 @@ public class EncryptUtils { /** * rsa私钥解密 * - * @param data 待加密数据 + * @param data 待解密数据 * @param privateKey 私钥 * @return 解密后字符串 */ diff --git a/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/annotation/ExcelNotation.java b/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/annotation/ExcelNotation.java new file mode 100644 index 000000000..f358afcd6 --- /dev/null +++ b/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/annotation/ExcelNotation.java @@ -0,0 +1,24 @@ +package org.dromara.common.excel.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 批注 + * @author guzhouyanyu + */ +@Target({ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface ExcelNotation { + + /** + * col index + */ + int index() default -1; + /** + * 批注内容 + */ + String value() default ""; +} diff --git a/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/annotation/ExcelRequired.java b/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/annotation/ExcelRequired.java new file mode 100644 index 000000000..15784e140 --- /dev/null +++ b/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/annotation/ExcelRequired.java @@ -0,0 +1,26 @@ +package org.dromara.common.excel.annotation; + +import org.apache.poi.ss.usermodel.IndexedColors; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 是否必填 + * @author guzhouyanyu + */ +@Target({ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface ExcelRequired { + + /** + * col index + */ + int index() default -1; + /** + * 字体颜色 + */ + IndexedColors fontColor() default IndexedColors.RED; +} diff --git a/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/core/ExcelDownHandler.java b/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/core/ExcelDownHandler.java index b3f68ed1e..32fee7a6c 100644 --- a/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/core/ExcelDownHandler.java +++ b/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/core/ExcelDownHandler.java @@ -55,6 +55,7 @@ public class ExcelDownHandler implements SheetWriteHandler { * 下拉可选项 */ private final List dropDownOptions; + private final DictService dictService; /** * 当前单选进度 */ @@ -63,7 +64,6 @@ public class ExcelDownHandler implements SheetWriteHandler { * 当前联动选择进度 */ private int currentLinkedOptionsSheetIndex; - private final DictService dictService; public ExcelDownHandler(List options) { this.dropDownOptions = options; @@ -139,8 +139,8 @@ public class ExcelDownHandler implements SheetWriteHandler { } else if (everyOptions.getOptions().size() > 10) { // 当一级选项参数个数大于10,使用额外表的形式 dropDownWithSheet(helper, workbook, sheet, everyOptions.getIndex(), everyOptions.getOptions()); - } else if (everyOptions.getOptions().size() != 0) { - // 当一级选项个数不为空,使用默认形式 + } else { + // 否则使用默认形式 dropDownWithSimple(helper, sheet, everyOptions.getIndex(), everyOptions.getOptions()); } }); @@ -171,10 +171,24 @@ public class ExcelDownHandler implements SheetWriteHandler { Sheet linkedOptionsDataSheet = workbook.createSheet(WorkbookUtil.createSafeSheetName(linkedOptionsSheetName)); // 将下拉表隐藏 workbook.setSheetHidden(workbook.getSheetIndex(linkedOptionsDataSheet), true); - // 完善横向的一级选项数据表 + // 选项数据 List firstOptions = options.getOptions(); Map> secoundOptionsMap = options.getNextOptions(); + // 采用按行填充数据的方式,避免EasyExcel出现数据无法写入的问题 + // Attempting to write a row in the range that is already written to disk + + // 使用ArrayList记载数据,防止乱序 + List columnNames = new ArrayList<>(); + // 写入第一行,即第一级的数据 + Row firstRow = linkedOptionsDataSheet.createRow(0); + for (int columnIndex = 0; columnIndex < firstOptions.size(); columnIndex++) { + String columnName = firstOptions.get(columnIndex); + firstRow.createCell(columnIndex) + .setCellValue(columnName); + columnNames.add(columnName); + } + // 创建名称管理器 Name name = workbook.createName(); // 设置名称管理器的别名 @@ -190,28 +204,12 @@ public class ExcelDownHandler implements SheetWriteHandler { // 设置数据校验为序列模式,引用的是名称管理器中的别名 this.markOptionsToSheet(helper, sheet, options.getIndex(), helper.createFormulaListConstraint(linkedOptionsSheetName)); - for (int columIndex = 0; columIndex < firstOptions.size(); columIndex++) { - // 先提取主表中一级下拉的列名 + // 创建二级选项的名称管理器 + for (int columIndex = 0; columIndex < columnNames.size(); columIndex++) { + // 列名 String firstOptionsColumnName = getExcelColumnName(columIndex); - // 一次循环是每一个一级选项 - int finalI = columIndex; - // 本次循环的一级选项值 - String thisFirstOptionsValue = firstOptions.get(columIndex); - // 创建第一行的数据 - Optional.ofNullable(linkedOptionsDataSheet.getRow(0)) - // 如果不存在则创建第一行 - .orElseGet(() -> linkedOptionsDataSheet.createRow(finalI)) - // 第一行当前列 - .createCell(columIndex) - // 设置值为当前一级选项值 - .setCellValue(thisFirstOptionsValue); - - // 第二行开始,设置第二级别选项参数 - List secondOptions = secoundOptionsMap.get(thisFirstOptionsValue); - if (CollUtil.isEmpty(secondOptions)) { - // 必须保证至少有一个关联选项,否则将导致Excel解析错误 - secondOptions = Collections.singletonList("暂无_0"); - } + // 对应的一级值 + String thisFirstOptionsValue = columnNames.get(columIndex); // 以该一级选项值创建子名称管理器 Name sonName = workbook.createName(); @@ -222,7 +220,9 @@ public class ExcelDownHandler implements SheetWriteHandler { linkedOptionsSheetName, firstOptionsColumnName, firstOptionsColumnName, - secondOptions.size() + 1 + // 二级选项存在则设置为(选项个数+1)行,否则设置为2行 + Math.max(Optional.ofNullable(secoundOptionsMap.get(thisFirstOptionsValue)) + .orElseGet(ArrayList::new).size(), 1) + 1 ); // 设置名称管理器的引用位置 sonName.setRefersToFormula(sonFunction); @@ -235,25 +235,51 @@ public class ExcelDownHandler implements SheetWriteHandler { // 二级只能主表每一行的每一列添加二级校验 markLinkedOptionsToSheet(helper, sheet, i, options.getNextIndex(), helper.createFormulaListConstraint(secondOptionsFunction)); } + } - for (int rowIndex = 0; rowIndex < secondOptions.size(); rowIndex++) { - // 从第二行开始填充二级选项 - int finalRowIndex = rowIndex + 1; - int finalColumIndex = columIndex; - - Row row = Optional.ofNullable(linkedOptionsDataSheet.getRow(finalRowIndex)) - // 没有则创建 - .orElseGet(() -> linkedOptionsDataSheet.createRow(finalRowIndex)); - Optional - // 在本级一级选项所在的列 - .ofNullable(row.getCell(finalColumIndex)) - // 不存在则创建 - .orElseGet(() -> row.createCell(finalColumIndex)) - // 设置二级选项值 - .setCellValue(secondOptions.get(rowIndex)); + // 将二级数据处理为按行区分 + Map> columnValueMap = new HashMap<>(); + int currentRow = 1; + while (currentRow >= 0) { + boolean flag = false; + List rowData = new ArrayList<>(); + for (String columnName : columnNames) { + List data = secoundOptionsMap.get(columnName); + if (CollUtil.isEmpty(data)) { + // 添加空字符串填充位置 + rowData.add(" "); + continue; + } + // 取第一个 + String str = data.get(0); + rowData.add(str); + // 通过移除的方式避免重复 + data.remove(0); + // 设置可以继续 + flag = true; + } + columnValueMap.put(currentRow, rowData); + // 可以继续,则增加行数,否则置为负数跳出循环 + if (flag) { + currentRow++; + } else { + currentRow = -1; } } + // 填充第二级选项数据 + columnValueMap.forEach((rowIndex, rowValues) -> { + Row row = linkedOptionsDataSheet.createRow(rowIndex); + for (int columnIndex = 0; columnIndex < rowValues.size(); columnIndex++) { + String rowValue = rowValues.get(columnIndex); + // 填充位置的部分不渲染 + if (StrUtil.isNotBlank(rowValue)) { + row.createCell(columnIndex) + .setCellValue(rowValue); + } + } + }); + currentLinkedOptionsSheetIndex++; } diff --git a/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/handler/DataWriteHandler.java b/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/handler/DataWriteHandler.java new file mode 100644 index 000000000..a2aa4951b --- /dev/null +++ b/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/handler/DataWriteHandler.java @@ -0,0 +1,135 @@ +package org.dromara.common.excel.handler; + +import cn.hutool.core.collection.CollUtil; +import com.alibaba.excel.metadata.data.DataFormatData; +import com.alibaba.excel.metadata.data.WriteCellData; +import com.alibaba.excel.util.StyleUtil; +import com.alibaba.excel.write.handler.CellWriteHandler; +import com.alibaba.excel.write.handler.SheetWriteHandler; +import com.alibaba.excel.write.handler.context.CellWriteHandlerContext; +import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; +import com.alibaba.excel.write.metadata.style.WriteCellStyle; +import com.alibaba.excel.write.metadata.style.WriteFont; +import org.apache.poi.ss.usermodel.*; +import org.apache.poi.xssf.usermodel.XSSFClientAnchor; +import org.apache.poi.xssf.usermodel.XSSFRichTextString; +import org.dromara.common.core.utils.reflect.ReflectUtils; +import org.dromara.common.excel.annotation.ExcelNotation; +import org.dromara.common.excel.annotation.ExcelRequired; + +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.Map; + +/** + * 批注、必填 + * + * @author guzhouyanyu + */ +public class DataWriteHandler implements SheetWriteHandler, CellWriteHandler { + + /** + * 批注 + */ + private final Map notationMap; + + /** + * 头列字体颜色 + */ + private final Map headColumnMap; + + + public DataWriteHandler(Class clazz) { + notationMap = getNotationMap(clazz); + headColumnMap = getRequiredMap(clazz); + } + + @Override + public void afterCellDispose(CellWriteHandlerContext context) { + if (CollUtil.isEmpty(notationMap) && CollUtil.isEmpty(headColumnMap)) { + return; + } + WriteCellData cellData = context.getFirstCellData(); + WriteCellStyle writeCellStyle = cellData.getOrCreateStyle(); + + DataFormatData dataFormatData = new DataFormatData(); + // 单元格设置为文本格式 + dataFormatData.setIndex((short) 49); + writeCellStyle.setDataFormatData(dataFormatData); + + if (context.getHead()) { + Cell cell = context.getCell(); + WriteSheetHolder writeSheetHolder = context.getWriteSheetHolder(); + Sheet sheet = writeSheetHolder.getSheet(); + Workbook workbook = writeSheetHolder.getSheet().getWorkbook(); + Drawing drawing = sheet.createDrawingPatriarch(); + // 设置标题字体样式 + WriteFont headWriteFont = new WriteFont(); + // 加粗 + headWriteFont.setBold(true); + if (CollUtil.isNotEmpty(headColumnMap) && headColumnMap.containsKey(cell.getColumnIndex())) { + // 设置字体颜色 + headWriteFont.setColor(headColumnMap.get(cell.getColumnIndex())); + } + writeCellStyle.setWriteFont(headWriteFont); + CellStyle cellStyle = StyleUtil.buildCellStyle(workbook, null, writeCellStyle); + cell.setCellStyle(cellStyle); + + if (CollUtil.isNotEmpty(notationMap) && notationMap.containsKey(cell.getColumnIndex())) { + // 批注内容 + String notationContext = notationMap.get(cell.getColumnIndex()); + // 创建绘图对象 + Comment comment = drawing.createCellComment(new XSSFClientAnchor(0, 0, 0, 0, (short) cell.getColumnIndex(), 0, (short) 5, 5)); + comment.setString(new XSSFRichTextString(notationContext)); + cell.setCellComment(comment); + } + } + } + + /** + * 获取必填列 + */ + private static Map getRequiredMap(Class clazz) { + Map requiredMap = new HashMap<>(); + Field[] fields = clazz.getDeclaredFields(); + // 检查 fields 数组是否为空 + if (fields.length == 0) { + return requiredMap; + } + Field[] filteredFields = ReflectUtils.getFields(clazz, field -> !"serialVersionUID".equals(field.getName())); + + for (int i = 0; i < filteredFields.length; i++) { + Field field = filteredFields[i]; + if (!field.isAnnotationPresent(ExcelRequired.class)) { + continue; + } + ExcelRequired excelRequired = field.getAnnotation(ExcelRequired.class); + int columnIndex = excelRequired.index() == -1 ? i : excelRequired.index(); + requiredMap.put(columnIndex, excelRequired.fontColor().getIndex()); + } + return requiredMap; + } + + /** + * 获取批注 + */ + private static Map getNotationMap(Class clazz) { + Map notationMap = new HashMap<>(); + Field[] fields = clazz.getDeclaredFields(); + // 检查 fields 数组是否为空 + if (fields.length == 0) { + return notationMap; + } + Field[] filteredFields = ReflectUtils.getFields(clazz, field -> !"serialVersionUID".equals(field.getName())); + for (int i = 0; i < filteredFields.length; i++) { + Field field = filteredFields[i]; + if (!field.isAnnotationPresent(ExcelNotation.class)) { + continue; + } + ExcelNotation excelNotation = field.getAnnotation(ExcelNotation.class); + int columnIndex = excelNotation.index() == -1 ? i : excelNotation.index(); + notationMap.put(columnIndex, excelNotation.value()); + } + return notationMap; + } +} diff --git a/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/utils/ExcelUtil.java b/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/utils/ExcelUtil.java index a6c14ad51..b22e6f987 100644 --- a/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/utils/ExcelUtil.java +++ b/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/utils/ExcelUtil.java @@ -18,6 +18,7 @@ import org.dromara.common.core.utils.StringUtils; import org.dromara.common.core.utils.file.FileUtils; import org.dromara.common.excel.convert.ExcelBigNumberConvert; import org.dromara.common.excel.core.*; +import org.dromara.common.excel.handler.DataWriteHandler; import java.io.IOException; import java.io.InputStream; @@ -191,6 +192,7 @@ public class ExcelUtil { .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) // 大数值自动转换 防止失真 .registerConverter(new ExcelBigNumberConvert()) + .registerWriteHandler(new DataWriteHandler(clazz)) .sheet(sheetName); if (merge) { // 合并处理器 @@ -211,7 +213,7 @@ public class ExcelUtil { * @param data 模板需要的数据 * @param response 响应体 */ - public static void exportTemplate(List data, String filename, String templatePath, HttpServletResponse response) { + public static void exportTemplate(List data, String filename, String templatePath, HttpServletResponse response) { try { resetResponse(filename, response); ServletOutputStream os = response.getOutputStream(); @@ -230,20 +232,21 @@ public class ExcelUtil { * @param data 模板需要的数据 * @param os 输出流 */ - public static void exportTemplate(List data, String templatePath, OutputStream os) { + public static void exportTemplate(List data, String templatePath, OutputStream os) { + if (CollUtil.isEmpty(data)) { + throw new IllegalArgumentException("数据为空"); + } ClassPathResource templateResource = new ClassPathResource(templatePath); ExcelWriter excelWriter = EasyExcel.write(os) .withTemplate(templateResource.getStream()) .autoCloseStream(false) // 大数值自动转换 防止失真 .registerConverter(new ExcelBigNumberConvert()) + .registerWriteHandler(new DataWriteHandler(data.get(0).getClass())) .build(); WriteSheet writeSheet = EasyExcel.writerSheet().build(); - if (CollUtil.isEmpty(data)) { - throw new IllegalArgumentException("数据为空"); - } // 单表多数据导出 模板格式为 {.属性} - for (Object d : data) { + for (T d : data) { excelWriter.fill(d, writeSheet); } excelWriter.finish(); @@ -299,6 +302,9 @@ public class ExcelUtil { * @param os 输出流 */ public static void exportTemplateMultiList(Map data, String templatePath, OutputStream os) { + if (CollUtil.isEmpty(data)) { + throw new IllegalArgumentException("数据为空"); + } ClassPathResource templateResource = new ClassPathResource(templatePath); ExcelWriter excelWriter = EasyExcel.write(os) .withTemplate(templateResource.getStream()) @@ -307,9 +313,6 @@ public class ExcelUtil { .registerConverter(new ExcelBigNumberConvert()) .build(); WriteSheet writeSheet = EasyExcel.writerSheet().build(); - if (CollUtil.isEmpty(data)) { - throw new IllegalArgumentException("数据为空"); - } for (Map.Entry map : data.entrySet()) { // 设置列表后续还有数据 FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build(); @@ -333,6 +336,9 @@ public class ExcelUtil { * @param os 输出流 */ public static void exportTemplateMultiSheet(List> data, String templatePath, OutputStream os) { + if (CollUtil.isEmpty(data)) { + throw new IllegalArgumentException("数据为空"); + } ClassPathResource templateResource = new ClassPathResource(templatePath); ExcelWriter excelWriter = EasyExcel.write(os) .withTemplate(templateResource.getStream()) @@ -340,9 +346,6 @@ public class ExcelUtil { // 大数值自动转换 防止失真 .registerConverter(new ExcelBigNumberConvert()) .build(); - if (CollUtil.isEmpty(data)) { - throw new IllegalArgumentException("数据为空"); - } for (int i = 0; i < data.size(); i++) { WriteSheet writeSheet = EasyExcel.writerSheet(i).build(); for (Map.Entry map : data.get(i).entrySet()) { diff --git a/ruoyi-common/ruoyi-common-json/src/main/java/org/dromara/common/json/handler/BigNumberSerializer.java b/ruoyi-common/ruoyi-common-json/src/main/java/org/dromara/common/json/handler/BigNumberSerializer.java index f2a7c2d8c..8752353c5 100644 --- a/ruoyi-common/ruoyi-common-json/src/main/java/org/dromara/common/json/handler/BigNumberSerializer.java +++ b/ruoyi-common/ruoyi-common-json/src/main/java/org/dromara/common/json/handler/BigNumberSerializer.java @@ -32,7 +32,7 @@ public class BigNumberSerializer extends NumberSerializer { @Override public void serialize(Number value, JsonGenerator gen, SerializerProvider provider) throws IOException { - // 超出范围 序列化位字符串 + // 超出范围 序列化为字符串 if (value.longValue() > MIN_SAFE_INTEGER && value.longValue() < MAX_SAFE_INTEGER) { super.serialize(value, gen, provider); } else { diff --git a/ruoyi-common/ruoyi-common-log/src/main/java/org/dromara/common/log/aspect/LogAspect.java b/ruoyi-common/ruoyi-common-log/src/main/java/org/dromara/common/log/aspect/LogAspect.java index 4c6c1a4d6..8ab2719e1 100644 --- a/ruoyi-common/ruoyi-common-log/src/main/java/org/dromara/common/log/aspect/LogAspect.java +++ b/ruoyi-common/ruoyi-common-log/src/main/java/org/dromara/common/log/aspect/LogAspect.java @@ -100,7 +100,7 @@ public class LogAspect { if (e != null) { operLog.setStatus(BusinessStatus.FAIL.ordinal()); - operLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 2000)); + operLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 3800)); } // 设置方法名称 String className = joinPoint.getTarget().getClass().getName(); @@ -113,13 +113,12 @@ public class LogAspect { // 设置消耗时间 StopWatch stopWatch = KEY_CACHE.get(); stopWatch.stop(); - operLog.setCostTime(stopWatch.getTime()); + operLog.setCostTime(stopWatch.getDuration().toMillis()); // 发布事件保存数据库 SpringUtils.context().publishEvent(operLog); } catch (Exception exp) { // 记录本地异常日志 log.error("异常信息:{}", exp.getMessage()); - exp.printStackTrace(); } finally { KEY_CACHE.remove(); } @@ -146,7 +145,7 @@ public class LogAspect { } // 是否需要保存response,参数和值 if (log.isSaveResponseData() && ObjectUtil.isNotNull(jsonResult)) { - operLog.setJsonResult(StringUtils.substring(JsonUtils.toJsonString(jsonResult), 0, 2000)); + operLog.setJsonResult(StringUtils.substring(JsonUtils.toJsonString(jsonResult), 0, 3800)); } } @@ -161,11 +160,11 @@ public class LogAspect { String requestMethod = operLog.getRequestMethod(); if (MapUtil.isEmpty(paramsMap) && StringUtils.equalsAny(requestMethod, HttpMethod.PUT.name(), HttpMethod.POST.name(), HttpMethod.DELETE.name())) { String params = argsArrayToString(joinPoint.getArgs(), excludeParamNames); - operLog.setOperParam(StringUtils.substring(params, 0, 2000)); + operLog.setOperParam(StringUtils.substring(params, 0, 3800)); } else { MapUtil.removeAny(paramsMap, EXCLUDE_PROPERTIES); MapUtil.removeAny(paramsMap, excludeParamNames); - operLog.setOperParam(StringUtils.substring(JsonUtils.toJsonString(paramsMap), 0, 2000)); + operLog.setOperParam(StringUtils.substring(JsonUtils.toJsonString(paramsMap), 0, 3800)); } } diff --git a/ruoyi-common/ruoyi-common-mail/src/main/java/org/dromara/common/mail/config/properties/MailProperties.java b/ruoyi-common/ruoyi-common-mail/src/main/java/org/dromara/common/mail/config/properties/MailProperties.java index d0e78a2ca..e44aa3da3 100644 --- a/ruoyi-common/ruoyi-common-mail/src/main/java/org/dromara/common/mail/config/properties/MailProperties.java +++ b/ruoyi-common/ruoyi-common-mail/src/main/java/org/dromara/common/mail/config/properties/MailProperties.java @@ -43,7 +43,13 @@ public class MailProperties { private String pass; /** - * 发送方,遵循RFC-822标准 + * 发送方,遵循RFC-822标准
+ * 发件人可以是以下形式: + * + *
+     * 1. user@xxx.xx
+     * 2.  name <user@xxx.xx>
+     * 
*/ private String from; diff --git a/ruoyi-common/ruoyi-common-mybatis/pom.xml b/ruoyi-common/ruoyi-common-mybatis/pom.xml index a58064a8a..d79ba284a 100644 --- a/ruoyi-common/ruoyi-common-mybatis/pom.xml +++ b/ruoyi-common/ruoyi-common-mybatis/pom.xml @@ -37,6 +37,11 @@ mybatis-plus-spring-boot3-starter + + com.baomidou + mybatis-plus-jsqlparser + + p6spy diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/aspect/DataPermissionAspect.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/aspect/DataPermissionAspect.java new file mode 100644 index 000000000..1c83cc392 --- /dev/null +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/aspect/DataPermissionAspect.java @@ -0,0 +1,50 @@ +package org.dromara.common.mybatis.aspect; + +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.AfterReturning; +import org.aspectj.lang.annotation.AfterThrowing; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.dromara.common.mybatis.annotation.DataPermission; +import org.dromara.common.mybatis.helper.DataPermissionHelper; + +/** + * 数据权限处理 + * + * @author Lion Li + */ +@Slf4j +@Aspect +public class DataPermissionAspect { + + /** + * 处理请求前执行 + */ + @Before(value = "@annotation(dataPermission)") + public void doBefore(JoinPoint joinPoint, DataPermission dataPermission) { + DataPermissionHelper.setPermission(dataPermission); + } + + /** + * 处理完请求后执行 + * + * @param joinPoint 切点 + */ + @AfterReturning(pointcut = "@annotation(dataPermission)") + public void doAfterReturning(JoinPoint joinPoint, DataPermission dataPermission) { + DataPermissionHelper.removePermission(); + } + + /** + * 拦截异常操作 + * + * @param joinPoint 切点 + * @param e 异常 + */ + @AfterThrowing(value = "@annotation(dataPermission)", throwing = "e") + public void doAfterThrowing(JoinPoint joinPoint, DataPermission dataPermission, Exception e) { + DataPermissionHelper.removePermission(); + } + +} diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/config/MybatisPlusConfig.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/config/MybatisPlusConfig.java index 0bc5b66a1..00c26912e 100644 --- a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/config/MybatisPlusConfig.java +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/config/MybatisPlusConfig.java @@ -2,6 +2,7 @@ package org.dromara.common.mybatis.config; import cn.hutool.core.net.NetUtil; import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; +import com.baomidou.mybatisplus.core.handlers.PostInitTableInfoHandler; import com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator; import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator; import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; @@ -10,8 +11,10 @@ import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerIntercept import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor; import org.dromara.common.core.factory.YmlPropertySourceFactory; import org.dromara.common.core.utils.SpringUtils; +import org.dromara.common.mybatis.aspect.DataPermissionAspect; import org.dromara.common.mybatis.handler.InjectionMetaObjectHandler; import org.dromara.common.mybatis.handler.MybatisExceptionHandler; +import org.dromara.common.mybatis.handler.PlusPostInitTableInfoHandler; import org.dromara.common.mybatis.interceptor.PlusDataPermissionInterceptor; import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.BeansException; @@ -54,6 +57,14 @@ public class MybatisPlusConfig { return new PlusDataPermissionInterceptor(SpringUtils.getProperty("mybatis-plus.mapperPackage")); } + /** + * 数据权限切面处理器 + */ + @Bean + public DataPermissionAspect dataPermissionAspect() { + return new DataPermissionAspect(); + } + /** * 分页插件,自动识别数据库类型 */ @@ -96,6 +107,14 @@ public class MybatisPlusConfig { return new MybatisExceptionHandler(); } + /** + * 初始化表对象处理器 + */ + @Bean + public PostInitTableInfoHandler postInitTableInfoHandler() { + return new PlusPostInitTableInfoHandler(); + } + /** * PaginationInnerInterceptor 分页插件,自动识别数据库类型 * https://baomidou.com/pages/97710a/ diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/core/page/PageQuery.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/core/page/PageQuery.java index 6ca9b2756..1d5c3c9da 100644 --- a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/core/page/PageQuery.java +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/core/page/PageQuery.java @@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.metadata.OrderItem; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.fasterxml.jackson.annotation.JsonIgnore; import lombok.Data; import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.utils.StringUtils; @@ -113,8 +114,14 @@ public class PageQuery implements Serializable { return list; } + @JsonIgnore public Integer getFirstNum() { return (pageNum - 1) * pageSize; } + public PageQuery(Integer pageSize, Integer pageNum) { + this.pageSize = pageSize; + this.pageNum = pageNum; + } + } diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/core/page/TableDataInfo.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/core/page/TableDataInfo.java index 8ecfb54aa..370f47995 100644 --- a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/core/page/TableDataInfo.java +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/core/page/TableDataInfo.java @@ -50,6 +50,8 @@ public class TableDataInfo implements Serializable { public TableDataInfo(List list, long total) { this.rows = list; this.total = total; + this.code = HttpStatus.HTTP_OK; + this.msg = "查询成功"; } /** diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/enums/DataScopeType.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/enums/DataScopeType.java index 981bd421b..02a5f481f 100644 --- a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/enums/DataScopeType.java +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/enums/DataScopeType.java @@ -48,7 +48,12 @@ public enum DataScopeType { /** * 仅本人数据权限 */ - SELF("5", " #{#userName} = #{#user.userId} ", " 1 = 0 "); + SELF("5", " #{#userName} = #{#user.userId} ", " 1 = 0 "), + + /** + * 部门及以下或本人数据权限 + */ + DEPT_AND_CHILD_OR_SELF("6", " #{#deptName} IN ( #{@sdss.getDeptAndChild( #user.deptId )} ) OR #{#userName} = #{#user.userId} ", " 1 = 0 "); private final String code; diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/InjectionMetaObjectHandler.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/InjectionMetaObjectHandler.java index 7d44d2648..fec25792a 100644 --- a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/InjectionMetaObjectHandler.java +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/InjectionMetaObjectHandler.java @@ -7,6 +7,7 @@ import lombok.extern.slf4j.Slf4j; import org.apache.ibatis.reflection.MetaObject; import org.dromara.common.core.domain.model.LoginUser; import org.dromara.common.core.exception.ServiceException; +import org.dromara.common.core.utils.ObjectUtils; import org.dromara.common.mybatis.core.domain.BaseEntity; import org.dromara.common.satoken.utils.LoginHelper; @@ -31,8 +32,7 @@ public class InjectionMetaObjectHandler implements MetaObjectHandler { try { if (ObjectUtil.isNotNull(metaObject) && metaObject.getOriginalObject() instanceof BaseEntity baseEntity) { // 获取当前时间作为创建时间和更新时间,如果创建时间不为空,则使用创建时间,否则使用当前时间 - Date current = ObjectUtil.isNotNull(baseEntity.getCreateTime()) - ? baseEntity.getCreateTime() : new Date(); + Date current = ObjectUtils.notNull(baseEntity.getCreateTime(), new Date()); baseEntity.setCreateTime(current); baseEntity.setUpdateTime(current); @@ -44,8 +44,7 @@ public class InjectionMetaObjectHandler implements MetaObjectHandler { // 填充创建人、更新人和创建部门信息 baseEntity.setCreateBy(userId); baseEntity.setUpdateBy(userId); - baseEntity.setCreateDept(ObjectUtil.isNotNull(baseEntity.getCreateDept()) - ? baseEntity.getCreateDept() : loginUser.getDeptId()); + baseEntity.setCreateDept(ObjectUtils.notNull(baseEntity.getCreateDept(), loginUser.getDeptId())); } } } else { diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/PlusDataPermissionHandler.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/PlusDataPermissionHandler.java index ab7e0f6e4..a3547075b 100644 --- a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/PlusDataPermissionHandler.java +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/PlusDataPermissionHandler.java @@ -3,6 +3,7 @@ package org.dromara.common.mybatis.handler; import cn.hutool.core.annotation.AnnotationUtil; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; +import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import net.sf.jsqlparser.JSQLParserException; import net.sf.jsqlparser.expression.Expression; @@ -28,19 +29,13 @@ import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.core.io.support.ResourcePatternResolver; import org.springframework.core.type.ClassMetadata; import org.springframework.core.type.classreading.CachingMetadataReaderFactory; -import org.springframework.expression.BeanResolver; -import org.springframework.expression.ExpressionParser; -import org.springframework.expression.ParserContext; +import org.springframework.expression.*; import org.springframework.expression.common.TemplateParserContext; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.expression.spel.support.StandardEvaluationContext; import org.springframework.util.ClassUtils; -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Function; @@ -54,7 +49,7 @@ import java.util.function.Function; public class PlusDataPermissionHandler { /** - * 方法或类(名称) 与 注解的映射关系缓存 + * 类名称与注解的映射关系缓存(由于aop无法拦截mybatis接口类上的注解 只能通过启动预扫描的方式进行) */ private final Map dataPermissionCacheMap = new ConcurrentHashMap<>(); @@ -86,24 +81,24 @@ public class PlusDataPermissionHandler { * @return 数据过滤条件的 SQL 片段 */ public Expression getSqlSegment(Expression where, String mappedStatementId, boolean isSelect) { - // 获取数据权限配置 - DataPermission dataPermission = getDataPermission(mappedStatementId); - // 获取当前登录用户信息 - LoginUser currentUser = DataPermissionHelper.getVariable("user"); - if (ObjectUtil.isNull(currentUser)) { - currentUser = LoginHelper.getLoginUser(); - DataPermissionHelper.setVariable("user", currentUser); - } - // 如果是超级管理员或租户管理员,则不过滤数据 - if (LoginHelper.isSuperAdmin() || LoginHelper.isTenantAdmin()) { - return where; - } - // 构造数据过滤条件的 SQL 片段 - String dataFilterSql = buildDataFilter(dataPermission, isSelect); - if (StringUtils.isBlank(dataFilterSql)) { - return where; - } try { + // 获取数据权限配置 + DataPermission dataPermission = getDataPermission(mappedStatementId); + // 获取当前登录用户信息 + LoginUser currentUser = DataPermissionHelper.getVariable("user"); + if (ObjectUtil.isNull(currentUser)) { + currentUser = LoginHelper.getLoginUser(); + DataPermissionHelper.setVariable("user", currentUser); + } + // 如果是超级管理员或租户管理员,则不过滤数据 + if (LoginHelper.isSuperAdmin() || LoginHelper.isTenantAdmin()) { + return where; + } + // 构造数据过滤条件的 SQL 片段 + String dataFilterSql = buildDataFilter(dataPermission, isSelect); + if (StringUtils.isBlank(dataFilterSql)) { + return where; + } Expression expression = CCJSqlParserUtil.parseExpression(dataFilterSql); // 数据权限使用单独的括号 防止与其他条件冲突 ParenthesedExpressionList parenthesis = new ParenthesedExpressionList<>(expression); @@ -114,6 +109,8 @@ public class PlusDataPermissionHandler { } } catch (JSQLParserException e) { throw new ServiceException("数据权限解析异常 => " + e.getMessage()); + } finally { + DataPermissionHelper.removePermission(); } } @@ -132,10 +129,33 @@ public class PlusDataPermissionHandler { joinStr = " " + dataPermission.joinStr() + " "; } LoginUser user = DataPermissionHelper.getVariable("user"); - StandardEvaluationContext context = new StandardEvaluationContext(); + Object defaultValue = "-1"; + NullSafeStandardEvaluationContext context = new NullSafeStandardEvaluationContext(defaultValue); + context.addPropertyAccessor(new NullSafePropertyAccessor(context.getPropertyAccessors().get(0), defaultValue)); context.setBeanResolver(beanResolver); DataPermissionHelper.getContext().forEach(context::setVariable); Set conditions = new HashSet<>(); + // 优先设置变量 + List keys = new ArrayList<>(); + Map ignoreMap = new HashMap<>(); + for (DataColumn dataColumn : dataPermission.value()) { + if (dataColumn.key().length != dataColumn.value().length) { + throw new ServiceException("角色数据范围异常 => key与value长度不匹配"); + } + // 包含权限标识符 这直接跳过 + if (StringUtils.isNotBlank(dataColumn.permission()) && + CollUtil.contains(user.getMenuPermission(), dataColumn.permission()) + ) { + ignoreMap.put(dataColumn, Boolean.TRUE); + continue; + } + // 设置注解变量 key 为表达式变量 value 为变量值 + for (int i = 0; i < dataColumn.key().length; i++) { + context.setVariable(dataColumn.key()[i], dataColumn.value()[i]); + } + keys.addAll(Arrays.stream(dataColumn.key()).map(key -> "#" + key).toList()); + } + for (RoleDTO role : user.getRoles()) { user.setRoleId(role.getRoleId()); // 获取角色权限泛型 @@ -145,33 +165,30 @@ public class PlusDataPermissionHandler { } // 全部数据权限直接返回 if (type == DataScopeType.ALL) { - return ""; + return StringUtils.EMPTY; } boolean isSuccess = false; for (DataColumn dataColumn : dataPermission.value()) { - if (dataColumn.key().length != dataColumn.value().length) { - throw new ServiceException("角色数据范围异常 => key与value长度不匹配"); - } - // 不包含 key 变量 则不处理 - if (!StringUtils.containsAny(type.getSqlTemplate(), - Arrays.stream(dataColumn.key()).map(key -> "#" + key).toArray(String[]::new) - )) { - continue; - } // 包含权限标识符 这直接跳过 - if (StringUtils.isNotBlank(dataColumn.permission()) && - CollUtil.contains(user.getMenuPermission(), dataColumn.permission()) - ) { + if (ignoreMap.containsKey(dataColumn)) { + // 修复多角色与权限标识符共用问题 https://gitee.com/dromara/RuoYi-Vue-Plus/issues/IB4CS4 + conditions.add(joinStr + " 1 = 1 "); isSuccess = true; continue; } - // 设置注解变量 key 为表达式变量 value 为变量值 - for (int i = 0; i < dataColumn.key().length; i++) { - context.setVariable(dataColumn.key()[i], dataColumn.value()[i]); + // 不包含 key 变量 则不处理 + if (!StringUtils.containsAny(type.getSqlTemplate(), keys.toArray(String[]::new))) { + continue; } - + // 当前注解不满足模板 不处理 + if (!StringUtils.containsAny(type.getSqlTemplate(), dataColumn.key())) { + continue; + } + // 忽略数据权限 防止spel表达式内有其他sql查询导致死循环调用 + String sql = DataPermissionHelper.ignore(() -> + parser.parseExpression(type.getSqlTemplate(), parserContext).getValue(context, String.class) + ); // 解析sql模板并填充 - String sql = parser.parseExpression(type.getSqlTemplate(), parserContext).getValue(context, String.class); conditions.add(joinStr + sql); isSuccess = true; } @@ -185,7 +202,7 @@ public class PlusDataPermissionHandler { String sql = StreamUtils.join(conditions, Function.identity(), ""); return sql.substring(joinStr.length()); } - return ""; + return StringUtils.EMPTY; } /** @@ -212,7 +229,10 @@ public class PlusDataPermissionHandler { // 获取资源对应的类对象 Class clazz = Resources.classForName(classMetadata.getClassName()); // 查找类中的特定注解 - findAnnotation(clazz); + if (AnnotationUtil.hasAnnotation(clazz, DataPermission.class)) { + DataPermission dataPermission = AnnotationUtil.getAnnotation(clazz, DataPermission.class); + dataPermissionCacheMap.put(clazz.getName(), dataPermission); + } } } } catch (Exception e) { @@ -220,29 +240,6 @@ public class PlusDataPermissionHandler { } } - /** - * 在指定的类中查找特定的注解 DataPermission,并将带有这个注解的方法或类存储到 dataPermissionCacheMap 中 - * - * @param clazz 要查找的类 - */ - private void findAnnotation(Class clazz) { - DataPermission dataPermission; - for (Method method : clazz.getMethods()) { - if (method.isDefault() || method.isVarArgs()) { - continue; - } - String mappedStatementId = clazz.getName() + "." + method.getName(); - if (AnnotationUtil.hasAnnotation(method, DataPermission.class)) { - dataPermission = AnnotationUtil.getAnnotation(method, DataPermission.class); - dataPermissionCacheMap.put(mappedStatementId, dataPermission); - } - } - if (AnnotationUtil.hasAnnotation(clazz, DataPermission.class)) { - dataPermission = AnnotationUtil.getAnnotation(clazz, DataPermission.class); - dataPermissionCacheMap.put(clazz.getName(), dataPermission); - } - } - /** * 根据映射语句 ID 或类名获取对应的 DataPermission 注解对象 * @@ -250,9 +247,9 @@ public class PlusDataPermissionHandler { * @return DataPermission 注解对象,如果不存在则返回 null */ public DataPermission getDataPermission(String mapperId) { - // 检查缓存中是否包含映射语句 ID 对应的 DataPermission 注解对象 - if (dataPermissionCacheMap.containsKey(mapperId)) { - return dataPermissionCacheMap.get(mapperId); + // 检查上下文中是否包含映射语句 ID 对应的 DataPermission 注解对象 + if (DataPermissionHelper.getPermission() != null) { + return DataPermissionHelper.getPermission(); } // 如果缓存中不包含映射语句 ID 对应的 DataPermission 注解对象,则尝试使用类名作为键查找 String clazzName = mapperId.substring(0, mapperId.lastIndexOf(".")); @@ -271,4 +268,65 @@ public class PlusDataPermissionHandler { public boolean invalid(String mapperId) { return getDataPermission(mapperId) == null; } + + /** + * 对所有null变量找不到的变量返回默认值 + */ + @AllArgsConstructor + private static class NullSafeStandardEvaluationContext extends StandardEvaluationContext { + + private final Object defaultValue; + + @Override + public Object lookupVariable(String name) { + Object obj = super.lookupVariable(name); + // 如果读取到的值是 null,则返回默认值 + if (obj == null) { + return defaultValue; + } + return obj; + } + + } + + /** + * 对所有null变量找不到的变量返回默认值 委托模式 将不需要处理的方法委托给原处理器 + */ + @AllArgsConstructor + private static class NullSafePropertyAccessor implements PropertyAccessor { + + private final PropertyAccessor delegate; + private final Object defaultValue; + + @Override + public Class[] getSpecificTargetClasses() { + return delegate.getSpecificTargetClasses(); + } + + @Override + public boolean canRead(EvaluationContext context, Object target, String name) throws AccessException { + return delegate.canRead(context, target, name); + } + + @Override + public TypedValue read(EvaluationContext context, Object target, String name) throws AccessException { + TypedValue value = delegate.read(context, target, name); + // 如果读取到的值是 null,则返回默认值 + if (value.getValue() == null) { + return new TypedValue(defaultValue); + } + return value; + } + + @Override + public boolean canWrite(EvaluationContext context, Object target, String name) throws AccessException { + return delegate.canWrite(context, target, name); + } + + @Override + public void write(EvaluationContext context, Object target, String name, Object newValue) throws AccessException { + delegate.write(context, target, name, newValue); + } + } + } diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/PlusPostInitTableInfoHandler.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/PlusPostInitTableInfoHandler.java new file mode 100644 index 000000000..60ca20b4b --- /dev/null +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/PlusPostInitTableInfoHandler.java @@ -0,0 +1,27 @@ +package org.dromara.common.mybatis.handler; + +import cn.hutool.core.convert.Convert; +import com.baomidou.mybatisplus.core.handlers.PostInitTableInfoHandler; +import com.baomidou.mybatisplus.core.metadata.TableInfo; +import org.apache.ibatis.session.Configuration; +import org.dromara.common.core.utils.SpringUtils; +import org.dromara.common.core.utils.reflect.ReflectUtils; + +/** + * 修改表信息初始化方式 + * 目前用于全局修改是否使用逻辑删除 + * + * @author Lion Li + */ +public class PlusPostInitTableInfoHandler implements PostInitTableInfoHandler { + + @Override + public void postTableInfo(TableInfo tableInfo, Configuration configuration) { + String flag = SpringUtils.getProperty("mybatis-plus.enableLogicDelete", "true"); + // 只有关闭时 统一设置false 为true时mp自动判断不处理 + if (!Convert.toBool(flag)) { + ReflectUtils.setFieldValue(tableInfo, "withLogicDelete", false); + } + } + +} diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/helper/DataPermissionHelper.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/helper/DataPermissionHelper.java index 932f17388..f03d74e83 100644 --- a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/helper/DataPermissionHelper.java +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/helper/DataPermissionHelper.java @@ -9,6 +9,7 @@ import com.baomidou.mybatisplus.core.plugins.InterceptorIgnoreHelper; import lombok.AccessLevel; import lombok.NoArgsConstructor; import org.dromara.common.core.utils.reflect.ReflectUtils; +import org.dromara.common.mybatis.annotation.DataPermission; import java.util.HashMap; import java.util.Map; @@ -29,6 +30,33 @@ public class DataPermissionHelper { private static final ThreadLocal> REENTRANT_IGNORE = ThreadLocal.withInitial(Stack::new); + private static final ThreadLocal PERMISSION_CACHE = new ThreadLocal<>(); + + /** + * 获取当前执行mapper权限注解 + * + * @return 返回当前执行mapper权限注解 + */ + public static DataPermission getPermission() { + return PERMISSION_CACHE.get(); + } + + /** + * 设置当前执行mapper权限注解 + * + * @param dataPermission 数据权限注解 + */ + public static void setPermission(DataPermission dataPermission) { + PERMISSION_CACHE.set(dataPermission); + } + + /** + * 删除当前执行mapper权限注解 + */ + public static void removePermission() { + PERMISSION_CACHE.remove(); + } + /** * 从上下文中获取指定键的变量值,并将其转换为指定的类型 * diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/resources/common-mybatis.yml b/ruoyi-common/ruoyi-common-mybatis/src/main/resources/common-mybatis.yml index f5dc63758..14662e16a 100644 --- a/ruoyi-common/ruoyi-common-mybatis/src/main/resources/common-mybatis.yml +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/resources/common-mybatis.yml @@ -24,8 +24,8 @@ mybatis-plus: # 主键类型 # AUTO 自增 NONE 空 INPUT 用户输入 ASSIGN_ID 雪花 ASSIGN_UUID 唯一 UUID idType: ASSIGN_ID - # 逻辑已删除值(框架表均使用此值 禁止随意修改) - logicDeleteValue: 2 + # 逻辑已删除值(可按需求随意修改) + logicDeleteValue: 1 # 逻辑未删除值 logicNotDeleteValue: 0 insertStrategy: NOT_NULL diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/core/OssClient.java b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/core/OssClient.java index ba924c0bb..e3b20dde3 100644 --- a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/core/OssClient.java +++ b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/core/OssClient.java @@ -9,7 +9,6 @@ import org.dromara.common.core.utils.file.FileUtils; import org.dromara.common.oss.constant.OssConstant; import org.dromara.common.oss.entity.UploadResult; import org.dromara.common.oss.enumd.AccessPolicyType; -import org.dromara.common.oss.enumd.PolicyType; import org.dromara.common.oss.exception.OssException; import org.dromara.common.oss.properties.OssProperties; import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; @@ -22,8 +21,6 @@ import software.amazon.awssdk.services.s3.S3AsyncClient; import software.amazon.awssdk.services.s3.S3Configuration; import software.amazon.awssdk.services.s3.crt.S3CrtHttpConfiguration; import software.amazon.awssdk.services.s3.model.GetObjectResponse; -import software.amazon.awssdk.services.s3.model.NoSuchBucketException; -import software.amazon.awssdk.services.s3.model.S3Exception; import software.amazon.awssdk.services.s3.presigner.S3Presigner; import software.amazon.awssdk.transfer.s3.S3TransferManager; import software.amazon.awssdk.transfer.s3.model.*; @@ -35,6 +32,7 @@ import java.net.URL; import java.nio.file.Files; import java.nio.file.Path; import java.time.Duration; +import java.util.function.Consumer; /** * S3 存储协议 所有兼容S3协议的云厂商均支持 @@ -115,8 +113,6 @@ public class OssClient { .serviceConfiguration(config) .build(); - // 创建存储桶 - createBucket(); } catch (Exception e) { if (e instanceof OssException) { throw e; @@ -125,43 +121,6 @@ public class OssClient { } } - /** - * 同步创建存储桶 - * 如果存储桶不存在,会进行创建;如果存储桶存在,不执行任何操作 - * - * @throws OssException 当创建存储桶时发生异常时抛出 - */ - public void createBucket() { - String bucketName = properties.getBucketName(); - try { - // 尝试获取存储桶的信息 - client.headBucket( - x -> x.bucket(bucketName) - .build()) - .join(); - } catch (Exception ex) { - if (ex.getCause() instanceof NoSuchBucketException) { - try { - // 存储桶不存在,尝试创建存储桶 - client.createBucket( - x -> x.bucket(bucketName)) - .join(); - - // 设置存储桶的访问策略(Bucket Policy) - client.putBucketPolicy( - x -> x.bucket(bucketName) - .policy(getPolicy(bucketName, getAccessPolicy().getPolicyType()))) - .join(); - } catch (S3Exception e) { - // 存储桶创建或策略设置失败 - throw new OssException("创建Bucket失败, 请核对配置信息:[" + e.getMessage() + "]"); - } - } else { - throw new OssException("判断Bucket是否存在失败,请核对配置信息:[" + ex.getMessage() + "]"); - } - } - } - /** * 上传文件到 Amazon S3,并返回上传结果 * @@ -281,10 +240,11 @@ public class OssClient { * * @param key 文件在 Amazon S3 中的对象键 * @param out 输出流 + * @param consumer 自定义处理逻辑 * @return 输出流中写入的字节数(长度) * @throws OssException 如果下载失败,抛出自定义异常 */ - public long download(String key, OutputStream out) { + public void download(String key, OutputStream out, Consumer consumer) { try { // 构建下载请求 DownloadRequest> downloadRequest = DownloadRequest.builder() @@ -300,7 +260,10 @@ public class OssClient { Download> responseFuture = transferManager.download(downloadRequest); // 输出到流中 try (ResponseInputStream responseStream = responseFuture.completionFuture().join().result()) { // auto-closeable stream - return responseStream.transferTo(out); // 阻塞调用线程 blocks the calling thread + if (consumer != null) { + consumer.accept(responseStream.response().contentLength()); + } + responseStream.transferTo(out); // 阻塞调用线程 blocks the calling thread } } catch (Exception e) { throw new OssException("文件下载失败,错误信息:[" + e.getMessage() + "]"); @@ -326,13 +289,13 @@ public class OssClient { /** * 获取私有URL链接 * - * @param objectKey 对象KEY - * @param second 授权时间 + * @param objectKey 对象KEY + * @param expiredTime 链接授权到期时间 */ - public String getPrivateUrl(String objectKey, Integer second) { + public String getPrivateUrl(String objectKey, Duration expiredTime) { // 使用 AWS S3 预签名 URL 的生成器 获取对象的预签名 URL URL url = presigner.presignGetObject( - x -> x.signatureDuration(Duration.ofSeconds(second)) + x -> x.signatureDuration(expiredTime) .getObjectRequest( y -> y.bucket(properties.getBucketName()) .key(objectKey) @@ -529,77 +492,4 @@ public class OssClient { return AccessPolicyType.getByType(properties.getAccessPolicy()); } - /** - * 生成 AWS S3 存储桶访问策略 - * - * @param bucketName 存储桶 - * @param policyType 桶策略类型 - * @return 符合 AWS S3 存储桶访问策略格式的字符串 - */ - private static String getPolicy(String bucketName, PolicyType policyType) { - String policy = switch (policyType) { - case WRITE -> """ - { - "Version": "2012-10-17", - "Statement": [] - } - """; - case READ_WRITE -> """ - { - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Principal": "*", - "Action": [ - "s3:GetBucketLocation", - "s3:ListBucket", - "s3:ListBucketMultipartUploads" - ], - "Resource": "arn:aws:s3:::bucketName" - }, - { - "Effect": "Allow", - "Principal": "*", - "Action": [ - "s3:AbortMultipartUpload", - "s3:DeleteObject", - "s3:GetObject", - "s3:ListMultipartUploadParts", - "s3:PutObject" - ], - "Resource": "arn:aws:s3:::bucketName/*" - } - ] - } - """; - case READ -> """ - { - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Principal": "*", - "Action": ["s3:GetBucketLocation"], - "Resource": "arn:aws:s3:::bucketName" - }, - { - "Effect": "Deny", - "Principal": "*", - "Action": ["s3:ListBucket"], - "Resource": "arn:aws:s3:::bucketName" - }, - { - "Effect": "Allow", - "Principal": "*", - "Action": "s3:GetObject", - "Resource": "arn:aws:s3:::bucketName/*" - } - ] - } - """; - }; - return policy.replaceAll("bucketName", bucketName); - } - } diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/enumd/AccessPolicyType.java b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/enumd/AccessPolicyType.java index 6d39133d5..a257bbae0 100644 --- a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/enumd/AccessPolicyType.java +++ b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/enumd/AccessPolicyType.java @@ -17,17 +17,17 @@ public enum AccessPolicyType { /** * private */ - PRIVATE("0", BucketCannedACL.PRIVATE, ObjectCannedACL.PRIVATE, PolicyType.WRITE), + PRIVATE("0", BucketCannedACL.PRIVATE, ObjectCannedACL.PRIVATE), /** * public */ - PUBLIC("1", BucketCannedACL.PUBLIC_READ_WRITE, ObjectCannedACL.PUBLIC_READ_WRITE, PolicyType.READ_WRITE), + PUBLIC("1", BucketCannedACL.PUBLIC_READ_WRITE, ObjectCannedACL.PUBLIC_READ_WRITE), /** * custom */ - CUSTOM("2", BucketCannedACL.PUBLIC_READ, ObjectCannedACL.PUBLIC_READ, PolicyType.READ); + CUSTOM("2", BucketCannedACL.PUBLIC_READ, ObjectCannedACL.PUBLIC_READ); /** * 桶 权限类型(数据库值) @@ -44,11 +44,6 @@ public enum AccessPolicyType { */ private final ObjectCannedACL objectCannedACL; - /** - * 桶策略类型 - */ - private final PolicyType policyType; - public static AccessPolicyType getByType(String type) { for (AccessPolicyType value : values()) { if (value.getType().equals(type)) { diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/enumd/PolicyType.java b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/enumd/PolicyType.java deleted file mode 100644 index fe96341df..000000000 --- a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/enumd/PolicyType.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.dromara.common.oss.enumd; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * minio策略配置 - * - * @author Lion Li - */ -@Getter -@AllArgsConstructor -public enum PolicyType { - - /** - * 只读 - */ - READ("read-only"), - - /** - * 只写 - */ - WRITE("write-only"), - - /** - * 读写 - */ - READ_WRITE("read-write"); - - /** - * 类型 - */ - private final String type; - -} diff --git a/ruoyi-common/ruoyi-common-ratelimiter/src/main/java/org/dromara/common/ratelimiter/annotation/RateLimiter.java b/ruoyi-common/ruoyi-common-ratelimiter/src/main/java/org/dromara/common/ratelimiter/annotation/RateLimiter.java index de09752a7..79272d41e 100644 --- a/ruoyi-common/ruoyi-common-ratelimiter/src/main/java/org/dromara/common/ratelimiter/annotation/RateLimiter.java +++ b/ruoyi-common/ruoyi-common-ratelimiter/src/main/java/org/dromara/common/ratelimiter/annotation/RateLimiter.java @@ -38,4 +38,10 @@ public @interface RateLimiter { * 提示消息 支持国际化 格式为 {code} */ String message() default "{rate.limiter.message}"; + + /** + * 限流策略超时时间 默认一天(策略存活时间 会清除已存在的策略数据) + */ + int timeout() default 86400; + } diff --git a/ruoyi-common/ruoyi-common-ratelimiter/src/main/java/org/dromara/common/ratelimiter/aspectj/RateLimiterAspect.java b/ruoyi-common/ruoyi-common-ratelimiter/src/main/java/org/dromara/common/ratelimiter/aspectj/RateLimiterAspect.java index 1f4904a3e..2d6d82ea3 100644 --- a/ruoyi-common/ruoyi-common-ratelimiter/src/main/java/org/dromara/common/ratelimiter/aspectj/RateLimiterAspect.java +++ b/ruoyi-common/ruoyi-common-ratelimiter/src/main/java/org/dromara/common/ratelimiter/aspectj/RateLimiterAspect.java @@ -54,13 +54,14 @@ public class RateLimiterAspect { public void doBefore(JoinPoint point, RateLimiter rateLimiter) { int time = rateLimiter.time(); int count = rateLimiter.count(); + int timeout = rateLimiter.timeout(); try { String combineKey = getCombineKey(rateLimiter, point); RateType rateType = RateType.OVERALL; if (rateLimiter.limitType() == LimitType.CLUSTER) { rateType = RateType.PER_CLIENT; } - long number = RedisUtils.rateLimiter(combineKey, rateType, count, time); + long number = RedisUtils.rateLimiter(combineKey, rateType, count, time, timeout); if (number == -1) { String message = rateLimiter.message(); if (StringUtils.startsWith(message, "{") && StringUtils.endsWith(message, "}")) { diff --git a/ruoyi-common/ruoyi-common-redis/pom.xml b/ruoyi-common/ruoyi-common-redis/pom.xml index f56f8aad3..d7d99cacc 100644 --- a/ruoyi-common/ruoyi-common-redis/pom.xml +++ b/ruoyi-common/ruoyi-common-redis/pom.xml @@ -42,6 +42,18 @@ com.fasterxml.jackson.datatype jackson-datatype-jsr310 + + + + + + + + + + + + diff --git a/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/config/RedisConfig.java b/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/config/RedisConfig.java index f8fe79a8c..7ba94751a 100644 --- a/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/config/RedisConfig.java +++ b/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/config/RedisConfig.java @@ -53,6 +53,9 @@ public class RedisConfig { om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); // 指定序列化输入的类型,类必须是非final修饰的。序列化时将对象全类名一起保存下来 om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL); +// LoggerFactory.useSlf4jLogging(true); +// FuryCodec furyCodec = new FuryCodec(); +// CompositeCodec codec = new CompositeCodec(StringCodec.INSTANCE, furyCodec, furyCodec); TypedJsonJacksonCodec jsonCodec = new TypedJsonJacksonCodec(Object.class, om); // 组合序列化 key 使用 String 内容使用通用 json 格式 CompositeCodec codec = new CompositeCodec(StringCodec.INSTANCE, jsonCodec, jsonCodec); diff --git a/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/QueueUtils.java b/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/QueueUtils.java index e436a467f..7c09e3138 100644 --- a/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/QueueUtils.java +++ b/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/QueueUtils.java @@ -174,12 +174,12 @@ public class QueueUtils { * * @param queueName 队列名 * @param capacity 容量 - * @param destroy 已存在是否销毁 + * @param destroy 是否销毁 */ public static boolean trySetBoundedQueueCapacity(String queueName, int capacity, boolean destroy) { RBoundedBlockingQueue boundedBlockingQueue = CLIENT.getBoundedBlockingQueue(queueName); - if (boundedBlockingQueue.isExists() && destroy) { - destroyQueue(queueName); + if (destroy) { + boundedBlockingQueue.delete(); } return boundedBlockingQueue.trySetCapacity(capacity); } diff --git a/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/RedisUtils.java b/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/RedisUtils.java index 6fa3b7485..355cd2931 100644 --- a/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/RedisUtils.java +++ b/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/RedisUtils.java @@ -4,6 +4,7 @@ import lombok.AccessLevel; import lombok.NoArgsConstructor; import org.dromara.common.core.utils.SpringUtils; import org.redisson.api.*; +import org.redisson.api.options.KeysScanOptions; import java.time.Duration; import java.util.Collection; @@ -36,8 +37,22 @@ public class RedisUtils { * @return -1 表示失败 */ public static long rateLimiter(String key, RateType rateType, int rate, int rateInterval) { + return rateLimiter(key, rateType, rate, rateInterval, 0); + } + + /** + * 限流 + * + * @param key 限流key + * @param rateType 限流类型 + * @param rate 速率 + * @param rateInterval 速率间隔 + * @param timeout 超时时间 + * @return -1 表示失败 + */ + public static long rateLimiter(String key, RateType rateType, int rate, int rateInterval, int timeout) { RRateLimiter rateLimiter = CLIENT.getRateLimiter(key); - rateLimiter.trySetRate(rateType, rate, rateInterval, RateIntervalUnit.SECONDS); + rateLimiter.trySetRate(rateType, rate, Duration.ofSeconds(rateInterval), Duration.ofSeconds(timeout)); if (rateLimiter.tryAcquire()) { return rateLimiter.availablePermits(); } else { @@ -518,13 +533,34 @@ public class RedisUtils { /** * 获得缓存的基本对象列表(全局匹配忽略租户 自行拼接租户id) - * + *

+ * limit-设置扫描的限制数量(默认为0,查询全部) + * pattern-设置键的匹配模式(默认为null) + * chunkSize-设置每次扫描的块大小(默认为0,本方法设置为1000) + * type-设置键的类型(默认为null,查询全部类型) + *

+ * @see KeysScanOptions * @param pattern 字符串前缀 * @return 对象列表 */ public static Collection keys(final String pattern) { - Stream stream = CLIENT.getKeys().getKeysStreamByPattern(pattern); - return stream.collect(Collectors.toList()); + return keys(KeysScanOptions.defaults().pattern(pattern).chunkSize(1000)); + } + + /** + * 通过扫描参数获取缓存的基本对象列表 + * @param keysScanOptions 扫描参数 + *

+ * limit-设置扫描的限制数量(默认为0,查询全部) + * pattern-设置键的匹配模式(默认为null) + * chunkSize-设置每次扫描的块大小(默认为0) + * type-设置键的类型(默认为null,查询全部类型) + *

+ * @see KeysScanOptions + */ + public static Collection keys(final KeysScanOptions keysScanOptions) { + Stream keysStream = CLIENT.getKeys().getKeysStream(keysScanOptions); + return keysStream.collect(Collectors.toList()); } /** diff --git a/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/SequenceUtils.java b/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/SequenceUtils.java new file mode 100644 index 000000000..e28c84e89 --- /dev/null +++ b/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/SequenceUtils.java @@ -0,0 +1,165 @@ +package org.dromara.common.redis.utils; + +import cn.hutool.core.date.DatePattern; +import cn.hutool.core.date.DateUtil; +import org.dromara.common.core.utils.SpringUtils; +import org.dromara.common.core.utils.StringUtils; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import org.redisson.api.RIdGenerator; +import org.redisson.api.RedissonClient; + +import java.time.Duration; + +/** + * 发号器工具类 + * + * @author 秋辞未寒 + * @date 2024-12-10 + */ +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class SequenceUtils { + + /** + * 默认初始值 + */ + public static final Long DEFAULT_INIT_VALUE = 1L; + /** + * 默认步长 + */ + public static final Long DEFAULT_STEP_VALUE = 1L; + /** + * 默认过期时间-天 + */ + public static final Duration DEFAULT_EXPIRE_TIME_DAY = Duration.ofDays(1); + /** + * 默认过期时间-分钟 + */ + public static final Duration DEFAULT_EXPIRE_TIME_MINUTE = Duration.ofMinutes(1); + + /** + * 获取Redisson客户端实例 + */ + private static final RedissonClient REDISSON_CLIENT = SpringUtils.getBean(RedissonClient.class); + + /** + * 获取ID生成器 + * + * @param key 业务key + * @param expireTime 过期时间 + * @param initValue ID初始值 + * @param stepValue ID步长 + * @return ID生成器 + */ + private static RIdGenerator getIdGenerator(String key, Duration expireTime, Long initValue, Long stepValue) { + if (initValue == null || initValue <= 0) { + initValue = DEFAULT_INIT_VALUE; + } + if (stepValue == null || stepValue <= 0) { + stepValue = DEFAULT_STEP_VALUE; + } + RIdGenerator idGenerator = REDISSON_CLIENT.getIdGenerator(key); + // 设置初始值和步长 + idGenerator.tryInit(initValue, stepValue); + // 设置过期时间 + idGenerator.expire(expireTime); + return idGenerator; + } + + /** + * 获取指定业务key的唯一id + * + * @param key 业务key + * @param expireTime 过期时间 + * @param initValue ID初始值 + * @param stepValue ID步长 + * @return 唯一id + */ + public static long nextId(String key, Duration expireTime, Long initValue, Long stepValue) { + return getIdGenerator(key, expireTime, initValue, stepValue).nextId(); + } + + /** + * 获取指定业务key的唯一id字符串 + * + * @param key 业务key + * @param expireTime 过期时间 + * @param initValue ID初始值 + * @param stepValue ID步长 + * @return 唯一id + */ + public static String nextIdStr(String key, Duration expireTime, Long initValue, Long stepValue) { + return String.valueOf(nextId(key, expireTime, initValue, stepValue)); + } + + /** + * 获取指定业务key的唯一id (ID初始值=1,ID步长=1) + * + * @param key 业务key + * @param expireTime 过期时间 + * @return 唯一id + */ + public static long nextId(String key, Duration expireTime) { + return getIdGenerator(key, expireTime, DEFAULT_INIT_VALUE, DEFAULT_STEP_VALUE).nextId(); + } + + /** + * 获取指定业务key的唯一id字符串 (ID初始值=1,ID步长=1) + * + * @param key 业务key + * @param expireTime 过期时间 + * @return 唯一id + */ + public static String nextIdStr(String key, Duration expireTime) { + return String.valueOf(nextId(key, expireTime)); + } + + /** + * 获取 yyyyMMdd 开头的唯一id + * + * @return 唯一id + */ + public static String nextIdDate() { + return nextIdDate(""); + } + + /** + * 获取 prefix + yyyyMMdd 开头的唯一id + * + * @param prefix 业务前缀 + * @return 唯一id + */ + public static String nextIdDate(String prefix) { + // 前缀+日期 构建 prefixKey + String prefixKey = StringUtils.format("{}{}", StringUtils.blankToDefault(prefix, ""), DateUtil.format(DateUtil.date(), DatePattern.PURE_DATE_FORMATTER)); + // 获取下一个id + long nextId = getIdGenerator(prefixKey, DEFAULT_EXPIRE_TIME_DAY, DEFAULT_INIT_VALUE, DEFAULT_STEP_VALUE).nextId(); + // 返回完整id + return StringUtils.format("{}{}", prefixKey, nextId); + } + + /** + * 获取 yyyyMMddHHmmss 开头的唯一id + * + * @return 唯一id + */ + public static String nextIdDateTime() { + return nextIdDateTime(""); + } + + /** + * 获取 prefix + yyyyMMddHHmmss 开头的唯一id + * + * @param prefix 业务前缀 + * @return 唯一id + */ + public static String nextIdDateTime(String prefix) { + // 前缀+日期时间 构建 prefixKey + String prefixKey = StringUtils.format("{}{}", StringUtils.blankToDefault(prefix, ""), DateUtil.format(DateUtil.date(), DatePattern.PURE_DATETIME_FORMATTER)); + // 获取下一个id + long nextId = getIdGenerator(prefixKey, DEFAULT_EXPIRE_TIME_MINUTE, DEFAULT_INIT_VALUE, DEFAULT_STEP_VALUE).nextId(); + // 返回完整id + return StringUtils.format("{}{}", prefixKey, nextId); + } + +} diff --git a/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/core/dao/PlusSaTokenDao.java b/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/core/dao/PlusSaTokenDao.java index 38e12c315..a2a152003 100644 --- a/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/core/dao/PlusSaTokenDao.java +++ b/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/core/dao/PlusSaTokenDao.java @@ -51,7 +51,11 @@ public class PlusSaTokenDao implements SaTokenDao { if (timeout == NEVER_EXPIRE) { RedisUtils.setCacheObject(key, value); } else { - RedisUtils.setCacheObject(key, value, Duration.ofSeconds(timeout)); + if (RedisUtils.hasKey(key)) { + RedisUtils.setCacheObject(key, value, true); + } else { + RedisUtils.setCacheObject(key, value, Duration.ofSeconds(timeout)); + } } CAFFEINE.invalidate(key); } @@ -114,7 +118,11 @@ public class PlusSaTokenDao implements SaTokenDao { if (timeout == NEVER_EXPIRE) { RedisUtils.setCacheObject(key, object); } else { - RedisUtils.setCacheObject(key, object, Duration.ofSeconds(timeout)); + if (RedisUtils.hasKey(key)) { + RedisUtils.setCacheObject(key, object, true); + } else { + RedisUtils.setCacheObject(key, object, Duration.ofSeconds(timeout)); + } } CAFFEINE.invalidate(key); } diff --git a/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/utils/LoginHelper.java b/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/utils/LoginHelper.java index 4ab7d4eeb..e2c92366f 100644 --- a/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/utils/LoginHelper.java +++ b/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/utils/LoginHelper.java @@ -8,13 +8,14 @@ import cn.hutool.core.convert.Convert; import cn.hutool.core.util.ObjectUtil; import lombok.AccessLevel; import lombok.NoArgsConstructor; +import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.core.constant.TenantConstants; -import org.dromara.common.core.constant.UserConstants; import org.dromara.common.core.domain.model.LoginUser; import org.dromara.common.core.enums.UserType; import java.util.Set; + /** * 登录鉴权助手 *

@@ -88,6 +89,13 @@ public class LoginHelper { return Convert.toLong(getExtra(USER_KEY)); } + /** + * 获取用户id + */ + public static String getUserIdStr() { + return Convert.toStr(getExtra(USER_KEY)); + } + /** * 获取用户账户 */ @@ -152,7 +160,7 @@ public class LoginHelper { * @return 结果 */ public static boolean isSuperAdmin(Long userId) { - return UserConstants.SUPER_ADMIN_ID.equals(userId); + return SystemConstants.SUPER_ADMIN_ID.equals(userId); } /** diff --git a/ruoyi-common/ruoyi-common-sensitive/src/main/java/org/dromara/common/sensitive/annotation/Sensitive.java b/ruoyi-common/ruoyi-common-sensitive/src/main/java/org/dromara/common/sensitive/annotation/Sensitive.java index 1dfc896ff..e75dc5bf2 100644 --- a/ruoyi-common/ruoyi-common-sensitive/src/main/java/org/dromara/common/sensitive/annotation/Sensitive.java +++ b/ruoyi-common/ruoyi-common-sensitive/src/main/java/org/dromara/common/sensitive/annotation/Sensitive.java @@ -22,7 +22,13 @@ import java.lang.annotation.Target; public @interface Sensitive { SensitiveStrategy strategy(); - String roleKey() default ""; + /** + * 角色标识符 多个角色满足一个即可 + */ + String[] roleKey() default {}; - String perms() default ""; + /** + * 权限标识符 多个权限满足一个即可 + */ + String[] perms() default {}; } diff --git a/ruoyi-common/ruoyi-common-sensitive/src/main/java/org/dromara/common/sensitive/core/SensitiveService.java b/ruoyi-common/ruoyi-common-sensitive/src/main/java/org/dromara/common/sensitive/core/SensitiveService.java index 7b5264b87..03a7f9c75 100644 --- a/ruoyi-common/ruoyi-common-sensitive/src/main/java/org/dromara/common/sensitive/core/SensitiveService.java +++ b/ruoyi-common/ruoyi-common-sensitive/src/main/java/org/dromara/common/sensitive/core/SensitiveService.java @@ -13,6 +13,6 @@ public interface SensitiveService { /** * 是否脱敏 */ - boolean isSensitive(String roleKey, String perms); + boolean isSensitive(String[] roleKey, String[] perms); } diff --git a/ruoyi-common/ruoyi-common-sensitive/src/main/java/org/dromara/common/sensitive/core/SensitiveStrategy.java b/ruoyi-common/ruoyi-common-sensitive/src/main/java/org/dromara/common/sensitive/core/SensitiveStrategy.java index 995dcbd96..7af5cee9e 100644 --- a/ruoyi-common/ruoyi-common-sensitive/src/main/java/org/dromara/common/sensitive/core/SensitiveStrategy.java +++ b/ruoyi-common/ruoyi-common-sensitive/src/main/java/org/dromara/common/sensitive/core/SensitiveStrategy.java @@ -80,12 +80,12 @@ public enum SensitiveStrategy { FIRST_MASK(DesensitizedUtil::firstMask), /** - * 清空为null + * 清空为"" */ CLEAR(s -> DesensitizedUtil.clear()), /** - * 清空为"" + * 清空为null */ CLEAR_TO_NULL(s -> DesensitizedUtil.clearToNull()); diff --git a/ruoyi-common/ruoyi-common-sensitive/src/main/java/org/dromara/common/sensitive/handler/SensitiveHandler.java b/ruoyi-common/ruoyi-common-sensitive/src/main/java/org/dromara/common/sensitive/handler/SensitiveHandler.java index c76c83a98..d454724d7 100644 --- a/ruoyi-common/ruoyi-common-sensitive/src/main/java/org/dromara/common/sensitive/handler/SensitiveHandler.java +++ b/ruoyi-common/ruoyi-common-sensitive/src/main/java/org/dromara/common/sensitive/handler/SensitiveHandler.java @@ -26,8 +26,8 @@ import java.util.Objects; public class SensitiveHandler extends JsonSerializer implements ContextualSerializer { private SensitiveStrategy strategy; - private String roleKey; - private String perms; + private String[] roleKey; + private String[] perms; @Override public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException { diff --git a/ruoyi-common/ruoyi-common-sms/src/main/java/org/dromara/common/sms/core/dao/PlusSmsDao.java b/ruoyi-common/ruoyi-common-sms/src/main/java/org/dromara/common/sms/core/dao/PlusSmsDao.java index 91d8d243a..a757655ce 100644 --- a/ruoyi-common/ruoyi-common-sms/src/main/java/org/dromara/common/sms/core/dao/PlusSmsDao.java +++ b/ruoyi-common/ruoyi-common-sms/src/main/java/org/dromara/common/sms/core/dao/PlusSmsDao.java @@ -66,7 +66,7 @@ public class PlusSmsDao implements SmsDao { */ @Override public void clean() { - RedisUtils.deleteObject(GlobalConstants.GLOBAL_REDIS_KEY + "sms:"); + RedisUtils.deleteKeys(GlobalConstants.GLOBAL_REDIS_KEY + "sms:*"); } } diff --git a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/maxkey/AuthMaxKeyRequest.java b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/maxkey/AuthMaxKeyRequest.java index b95c19ee8..97774ac5d 100644 --- a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/maxkey/AuthMaxKeyRequest.java +++ b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/maxkey/AuthMaxKeyRequest.java @@ -30,7 +30,7 @@ public class AuthMaxKeyRequest extends AuthDefaultRequest { } @Override - protected AuthToken getAccessToken(AuthCallback authCallback) { + public AuthToken getAccessToken(AuthCallback authCallback) { String body = doPostAuthorizationCode(authCallback.getCode()); Dict object = JsonUtils.parseMap(body); // oauth/token 验证异常 @@ -51,7 +51,7 @@ public class AuthMaxKeyRequest extends AuthDefaultRequest { } @Override - protected AuthUser getUserInfo(AuthToken authToken) { + public AuthUser getUserInfo(AuthToken authToken) { String body = doGetUserInfo(authToken); Dict object = JsonUtils.parseMap(body); // oauth/token 验证异常 diff --git a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/topiam/AuthTopIamRequest.java b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/topiam/AuthTopIamRequest.java index 13649f9fd..080c97a93 100644 --- a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/topiam/AuthTopIamRequest.java +++ b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/topiam/AuthTopIamRequest.java @@ -1,7 +1,10 @@ package org.dromara.common.social.topiam; +import cn.hutool.core.codec.Base64; import cn.hutool.core.lang.Dict; import cn.hutool.core.util.StrUtil; +import cn.hutool.http.HttpRequest; +import cn.hutool.http.HttpResponse; import com.xkcoding.http.support.HttpHeader; import lombok.extern.slf4j.Slf4j; import me.zhyd.oauth.cache.AuthStateCache; @@ -16,7 +19,7 @@ import me.zhyd.oauth.utils.UrlBuilder; import org.dromara.common.core.utils.SpringUtils; import org.dromara.common.json.utils.JsonUtils; -import static org.dromara.common.social.topiam.AuthTopiamSource.TOPIAM; +import static org.dromara.common.social.topiam.AuthTopIamSource.TOPIAM; /** * TopIAM 认证请求 @@ -41,7 +44,7 @@ public class AuthTopIamRequest extends AuthDefaultRequest { } @Override - protected AuthToken getAccessToken(AuthCallback authCallback) { + public AuthToken getAccessToken(AuthCallback authCallback) { String body = doPostAuthorizationCode(authCallback.getCode()); Dict object = JsonUtils.parseMap(body); checkResponse(object); @@ -55,7 +58,7 @@ public class AuthTopIamRequest extends AuthDefaultRequest { } @Override - protected AuthUser getUserInfo(AuthToken authToken) { + public AuthUser getUserInfo(AuthToken authToken) { String body = doGetUserInfo(authToken); Dict object = JsonUtils.parseMap(body); checkResponse(object); @@ -70,6 +73,16 @@ public class AuthTopIamRequest extends AuthDefaultRequest { .build(); } + @Override + protected String doPostAuthorizationCode(String code) { + HttpRequest request = HttpRequest.post(source.accessToken()) + .header("Authorization", "Basic " + Base64.encode("%s:%s".formatted(config.getClientId(), config.getClientSecret()))) + .form("grant_type", "authorization_code") + .form("code", code) + .form("redirect_uri", config.getRedirectUri()); + HttpResponse response = request.execute(); + return response.body(); + } @Override protected String doGetUserInfo(AuthToken authToken) { @@ -86,7 +99,7 @@ public class AuthTopIamRequest extends AuthDefaultRequest { .build(); } - public static void checkResponse(Dict object) { + private static void checkResponse(Dict object) { // oauth/token 验证异常 if (object.containsKey("error")) { throw new AuthException(object.getStr("error_description")); diff --git a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/topiam/AuthTopiamSource.java b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/topiam/AuthTopIamSource.java similarity index 95% rename from ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/topiam/AuthTopiamSource.java rename to ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/topiam/AuthTopIamSource.java index e47d6c640..852d7f5cc 100644 --- a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/topiam/AuthTopiamSource.java +++ b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/topiam/AuthTopIamSource.java @@ -9,7 +9,7 @@ import me.zhyd.oauth.request.AuthDefaultRequest; * @author xlsea * @since 2024-01-06 */ -public enum AuthTopiamSource implements AuthSource { +public enum AuthTopIamSource implements AuthSource { /** * 测试 diff --git a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/utils/SocialUtils.java b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/utils/SocialUtils.java index 9191fca77..db696e515 100644 --- a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/utils/SocialUtils.java +++ b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/utils/SocialUtils.java @@ -58,9 +58,9 @@ public class SocialUtils { case "linkedin" -> new AuthLinkedinRequest(builder.build(), STATE_CACHE); case "microsoft" -> new AuthMicrosoftRequest(builder.build(), STATE_CACHE); case "renren" -> new AuthRenrenRequest(builder.build(), STATE_CACHE); - case "stack_overflow" -> new AuthStackOverflowRequest(builder.build(), STATE_CACHE); - case "huawei" -> new AuthHuaweiRequest(builder.build(), STATE_CACHE); - case "wechat_enterprise" -> new AuthWeChatEnterpriseQrcodeRequest(builder.build(), STATE_CACHE); + case "stack_overflow" -> new AuthStackOverflowRequest(builder.stackOverflowKey(obj.getStackOverflowKey()).build(), STATE_CACHE); + case "huawei" -> new AuthHuaweiV3Request(builder.build(), STATE_CACHE); + case "wechat_enterprise" -> new AuthWeChatEnterpriseQrcodeRequest(builder.agentId(obj.getAgentId()).build(), STATE_CACHE); case "gitlab" -> new AuthGitlabRequest(builder.build(), STATE_CACHE); case "wechat_mp" -> new AuthWeChatMpRequest(builder.build(), STATE_CACHE); case "aliyun" -> new AuthAliyunRequest(builder.build(), STATE_CACHE); diff --git a/ruoyi-common/ruoyi-common-sse/src/main/java/org/dromara/common/sse/core/SseEmitterManager.java b/ruoyi-common/ruoyi-common-sse/src/main/java/org/dromara/common/sse/core/SseEmitterManager.java index 0bfe0ca76..ba1ce5696 100644 --- a/ruoyi-common/ruoyi-common-sse/src/main/java/org/dromara/common/sse/core/SseEmitterManager.java +++ b/ruoyi-common/ruoyi-common-sse/src/main/java/org/dromara/common/sse/core/SseEmitterManager.java @@ -1,5 +1,6 @@ package org.dromara.common.sse.core; +import cn.hutool.core.map.MapUtil; import lombok.extern.slf4j.Slf4j; import org.dromara.common.redis.utils.RedisUtils; import org.dromara.common.sse.dto.SseMessageDto; @@ -65,12 +66,16 @@ public class SseEmitterManager { */ public void disconnect(Long userId, String token) { Map emitters = USER_TOKEN_EMITTERS.get(userId); - if (emitters != null) { + if (MapUtil.isNotEmpty(emitters)) { try { - emitters.get(token).send(SseEmitter.event().comment("disconnected")); + SseEmitter sseEmitter = emitters.get(token); + sseEmitter.send(SseEmitter.event().comment("disconnected")); + sseEmitter.complete(); } catch (Exception ignore) { } emitters.remove(token); + } else { + USER_TOKEN_EMITTERS.remove(userId); } } @@ -91,7 +96,7 @@ public class SseEmitterManager { */ public void sendMessage(Long userId, String message) { Map emitters = USER_TOKEN_EMITTERS.get(userId); - if (emitters != null) { + if (MapUtil.isNotEmpty(emitters)) { for (Map.Entry entry : emitters.entrySet()) { try { entry.getValue().send(SseEmitter.event() @@ -101,6 +106,8 @@ public class SseEmitterManager { emitters.remove(entry.getKey()); } } + } else { + USER_TOKEN_EMITTERS.remove(userId); } } diff --git a/ruoyi-common/ruoyi-common-sse/src/main/java/org/dromara/common/sse/utils/SseMessageUtils.java b/ruoyi-common/ruoyi-common-sse/src/main/java/org/dromara/common/sse/utils/SseMessageUtils.java index c6abdc8fd..586103417 100644 --- a/ruoyi-common/ruoyi-common-sse/src/main/java/org/dromara/common/sse/utils/SseMessageUtils.java +++ b/ruoyi-common/ruoyi-common-sse/src/main/java/org/dromara/common/sse/utils/SseMessageUtils.java @@ -16,7 +16,14 @@ import org.dromara.common.sse.dto.SseMessageDto; @NoArgsConstructor(access = AccessLevel.PRIVATE) public class SseMessageUtils { - private final static SseEmitterManager MANAGER = SpringUtils.getBean(SseEmitterManager.class); + private final static Boolean SSE_ENABLE = SpringUtils.getProperty("sse.enabled", Boolean.class, true); + private static SseEmitterManager MANAGER; + + static { + if (isEnable() && MANAGER == null) { + MANAGER = SpringUtils.getBean(SseEmitterManager.class); + } + } /** * 向指定的WebSocket会话发送消息 @@ -25,6 +32,9 @@ public class SseMessageUtils { * @param message 要发送的消息内容 */ public static void sendMessage(Long userId, String message) { + if (!isEnable()) { + return; + } MANAGER.sendMessage(userId, message); } @@ -34,6 +44,9 @@ public class SseMessageUtils { * @param message 要发送的消息内容 */ public static void sendMessage(String message) { + if (!isEnable()) { + return; + } MANAGER.sendMessage(message); } @@ -43,6 +56,9 @@ public class SseMessageUtils { * @param sseMessageDto 要发布的SSE消息对象 */ public static void publishMessage(SseMessageDto sseMessageDto) { + if (!isEnable()) { + return; + } MANAGER.publishMessage(sseMessageDto); } @@ -52,7 +68,17 @@ public class SseMessageUtils { * @param message 要发布的消息内容 */ public static void publishAll(String message) { + if (!isEnable()) { + return; + } MANAGER.publishAll(message); } + /** + * 是否开启 + */ + public static Boolean isEnable() { + return SSE_ENABLE; + } + } diff --git a/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/config/TenantConfig.java b/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/config/TenantConfig.java index 07302bc81..3767fa2f1 100644 --- a/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/config/TenantConfig.java +++ b/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/config/TenantConfig.java @@ -4,7 +4,6 @@ import cn.dev33.satoken.dao.SaTokenDao; import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor; import org.dromara.common.core.utils.reflect.ReflectUtils; -import org.dromara.common.mybatis.config.MybatisPlusConfig; import org.dromara.common.redis.config.RedisConfig; import org.dromara.common.redis.config.properties.RedissonProperties; import org.dromara.common.tenant.core.TenantSaTokenDao; @@ -16,7 +15,7 @@ import org.redisson.config.ClusterServersConfig; import org.redisson.config.SingleServerConfig; import org.redisson.spring.starter.RedissonAutoConfigurationCustomizer; import org.springframework.boot.autoconfigure.AutoConfiguration; -import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.cache.CacheManager; @@ -33,8 +32,8 @@ import org.springframework.context.annotation.Primary; @ConditionalOnProperty(value = "tenant.enable", havingValue = "true") public class TenantConfig { - @ConditionalOnBean(MybatisPlusConfig.class) - @AutoConfiguration(after = {MybatisPlusConfig.class}) + @ConditionalOnClass(TenantLineInnerInterceptor.class) + @AutoConfiguration static class MybatisPlusConfiguration { /** @@ -56,14 +55,12 @@ public class TenantConfig { // 使用单机模式 // 设置多租户 redis key前缀 singleServerConfig.setNameMapper(nameMapper); - ReflectUtils.invokeSetter(config, "singleServerConfig", singleServerConfig); } ClusterServersConfig clusterServersConfig = ReflectUtils.invokeGetter(config, "clusterServersConfig"); // 集群配置方式 参考下方注释 if (ObjectUtil.isNotNull(clusterServersConfig)) { // 设置多租户 redis key前缀 clusterServersConfig.setNameMapper(nameMapper); - ReflectUtils.invokeSetter(config, "clusterServersConfig", clusterServersConfig); } }; } diff --git a/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/handle/TenantKeyPrefixHandler.java b/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/handle/TenantKeyPrefixHandler.java index 65f523395..dcdef6e62 100644 --- a/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/handle/TenantKeyPrefixHandler.java +++ b/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/handle/TenantKeyPrefixHandler.java @@ -27,8 +27,12 @@ public class TenantKeyPrefixHandler extends KeyPrefixHandler { if (StringUtils.isBlank(name)) { return null; } - if (InterceptorIgnoreHelper.willIgnoreTenantLine("")) { - return super.map(name); + try { + if (InterceptorIgnoreHelper.willIgnoreTenantLine("")) { + return super.map(name); + } + } catch (NoClassDefFoundError ignore) { + // 有些服务不需要mp导致类不存在 忽略即可 } if (StringUtils.contains(name, GlobalConstants.GLOBAL_REDIS_KEY)) { return super.map(name); @@ -54,16 +58,20 @@ public class TenantKeyPrefixHandler extends KeyPrefixHandler { if (StringUtils.isBlank(unmap)) { return null; } - if (InterceptorIgnoreHelper.willIgnoreTenantLine("")) { - return super.unmap(name); + try { + if (InterceptorIgnoreHelper.willIgnoreTenantLine("")) { + return unmap; + } + } catch (NoClassDefFoundError ignore) { + // 有些服务不需要mp导致类不存在 忽略即可 } if (StringUtils.contains(name, GlobalConstants.GLOBAL_REDIS_KEY)) { - return super.unmap(name); + return unmap; } String tenantId = TenantHelper.getTenantId(); if (StringUtils.isBlank(tenantId)) { log.debug("无法获取有效的租户id -> Null"); - return super.unmap(name); + return unmap; } if (StringUtils.startsWith(unmap, tenantId + "")) { // 如果存在则删除 diff --git a/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/helper/TenantHelper.java b/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/helper/TenantHelper.java index 1a5ea1a76..4b6981a10 100644 --- a/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/helper/TenantHelper.java +++ b/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/helper/TenantHelper.java @@ -1,5 +1,7 @@ package org.dromara.common.tenant.helper; +import cn.dev33.satoken.context.SaHolder; +import cn.dev33.satoken.context.model.SaStorage; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.convert.Convert; import cn.hutool.core.util.ObjectUtil; @@ -135,6 +137,7 @@ public class TenantHelper { } String cacheKey = DYNAMIC_TENANT_KEY + ":" + LoginHelper.getUserId(); RedisUtils.setCacheObject(cacheKey, tenantId); + SaHolder.getStorage().set(cacheKey, tenantId); } /** @@ -154,8 +157,15 @@ public class TenantHelper { if (StringUtils.isNotBlank(tenantId)) { return tenantId; } + SaStorage storage = SaHolder.getStorage(); String cacheKey = DYNAMIC_TENANT_KEY + ":" + LoginHelper.getUserId(); + tenantId = storage.getString(cacheKey); + // 如果为 -1 说明已经查过redis并且不存在值 则直接返回null + if (StringUtils.isNotBlank(tenantId)) { + return tenantId.equals("-1") ? null : tenantId; + } tenantId = RedisUtils.getCacheObject(cacheKey); + storage.set(cacheKey, StringUtils.isBlank(tenantId) ? "-1" : tenantId); return tenantId; } @@ -173,6 +183,7 @@ public class TenantHelper { TEMP_DYNAMIC_TENANT.remove(); String cacheKey = DYNAMIC_TENANT_KEY + ":" + LoginHelper.getUserId(); RedisUtils.deleteObject(cacheKey); + SaHolder.getStorage().delete(cacheKey); } /** diff --git a/ruoyi-common/ruoyi-common-translation/src/main/java/org/dromara/common/translation/core/handler/TranslationHandler.java b/ruoyi-common/ruoyi-common-translation/src/main/java/org/dromara/common/translation/core/handler/TranslationHandler.java index bb9615bfd..a90f1e1ec 100644 --- a/ruoyi-common/ruoyi-common-translation/src/main/java/org/dromara/common/translation/core/handler/TranslationHandler.java +++ b/ruoyi-common/ruoyi-common-translation/src/main/java/org/dromara/common/translation/core/handler/TranslationHandler.java @@ -39,7 +39,7 @@ public class TranslationHandler extends JsonSerializer implements Contex if (ObjectUtil.isNotNull(trans)) { // 如果映射字段不为空 则取映射字段的值 if (StringUtils.isNotBlank(translation.mapper())) { - value = ReflectUtils.invokeGetter(gen.getCurrentValue(), translation.mapper()); + value = ReflectUtils.invokeGetter(gen.currentValue(), translation.mapper()); } // 如果为 null 直接写出 if (ObjectUtil.isNull(value)) { diff --git a/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/config/UndertowConfig.java b/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/config/UndertowConfig.java index ac50dd29a..84f88ff82 100644 --- a/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/config/UndertowConfig.java +++ b/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/config/UndertowConfig.java @@ -1,6 +1,8 @@ package org.dromara.common.web.config; import io.undertow.server.DefaultByteBufferPool; +import io.undertow.server.handlers.DisallowedMethodsHandler; +import io.undertow.util.HttpString; import io.undertow.websockets.jsr.WebSocketDeploymentInfo; import org.dromara.common.core.utils.SpringUtils; import org.springframework.boot.autoconfigure.AutoConfiguration; @@ -16,18 +18,45 @@ import org.springframework.core.task.VirtualThreadTaskExecutor; @AutoConfiguration public class UndertowConfig implements WebServerFactoryCustomizer { + /** + * 自定义 Undertow 配置 + *

+ * 主要配置内容包括: + * 1. 配置 WebSocket 部署信息 + * 2. 在虚拟线程模式下使用虚拟线程池 + * 3. 禁用不安全的 HTTP 方法,如 CONNECT、TRACE、TRACK + *

+ * + * @param factory Undertow 的 Web 服务器工厂 + */ @Override public void customize(UndertowServletWebServerFactory factory) { factory.addDeploymentInfoCustomizers(deploymentInfo -> { + // 配置 WebSocket 部署信息,设置 WebSocket 使用的缓冲区池 WebSocketDeploymentInfo webSocketDeploymentInfo = new WebSocketDeploymentInfo(); webSocketDeploymentInfo.setBuffers(new DefaultByteBufferPool(true, 1024)); deploymentInfo.addServletContextAttribute("io.undertow.websockets.jsr.WebSocketDeploymentInfo", webSocketDeploymentInfo); - // 使用虚拟线程 + + // 如果启用了虚拟线程,配置 Undertow 使用虚拟线程池 if (SpringUtils.isVirtual()) { + // 创建虚拟线程池,线程池前缀为 "undertow-" VirtualThreadTaskExecutor executor = new VirtualThreadTaskExecutor("undertow-"); + // 设置虚拟线程池为执行器和异步执行器 deploymentInfo.setExecutor(executor); deploymentInfo.setAsyncExecutor(executor); } + + // 配置禁止某些不安全的 HTTP 方法(如 CONNECT、TRACE、TRACK) + deploymentInfo.addInitialHandlerChainWrapper(handler -> { + // 禁止三个方法 CONNECT/TRACE/TRACK 也是不安全的 避免爬虫骚扰 + HttpString[] disallowedHttpMethods = { + HttpString.tryFromString("CONNECT"), + HttpString.tryFromString("TRACE"), + HttpString.tryFromString("TRACK") + }; + // 使用 DisallowedMethodsHandler 拦截并拒绝这些方法的请求 + return new DisallowedMethodsHandler(handler, disallowedHttpMethods); + }); }); } diff --git a/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/handler/GlobalExceptionHandler.java b/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/handler/GlobalExceptionHandler.java index 321c22615..0a60fbcc7 100644 --- a/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/handler/GlobalExceptionHandler.java +++ b/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/handler/GlobalExceptionHandler.java @@ -63,7 +63,7 @@ public class GlobalExceptionHandler { @ExceptionHandler(SseException.class) public String handleNotLoginException(SseException e, HttpServletRequest request) { String requestURI = request.getRequestURI(); - log.error("请求地址'{}',认证失败'{}',无法访问系统资源", requestURI, e.getMessage()); + log.debug("请求地址'{}',认证失败'{}',无法访问系统资源", requestURI, e.getMessage()); return JsonUtils.toJsonString(R.fail(HttpStatus.HTTP_UNAUTHORIZED, "认证失败,无法访问系统资源")); } diff --git a/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/interceptor/PlusWebInvokeTimeInterceptor.java b/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/interceptor/PlusWebInvokeTimeInterceptor.java index 7cb6b7877..f25601572 100644 --- a/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/interceptor/PlusWebInvokeTimeInterceptor.java +++ b/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/interceptor/PlusWebInvokeTimeInterceptor.java @@ -67,7 +67,7 @@ public class PlusWebInvokeTimeInterceptor implements HandlerInterceptor { StopWatch stopWatch = KEY_CACHE.get(); if (ObjectUtil.isNotNull(stopWatch)) { stopWatch.stop(); - log.info("[PLUS]结束请求 => URL[{}],耗时:[{}]毫秒", request.getMethod() + " " + request.getRequestURI(), stopWatch.getTime()); + log.info("[PLUS]结束请求 => URL[{}],耗时:[{}]毫秒", request.getMethod() + " " + request.getRequestURI(), stopWatch.getDuration().toMillis()); KEY_CACHE.remove(); } } diff --git a/ruoyi-common/ruoyi-common-websocket/pom.xml b/ruoyi-common/ruoyi-common-websocket/pom.xml index db86dcbe4..0587cd79a 100644 --- a/ruoyi-common/ruoyi-common-websocket/pom.xml +++ b/ruoyi-common/ruoyi-common-websocket/pom.xml @@ -35,6 +35,12 @@ org.springframework.boot spring-boot-starter-websocket + + + org.springframework.boot + spring-boot-starter-tomcat + + diff --git a/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/holder/WebSocketSessionHolder.java b/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/holder/WebSocketSessionHolder.java index 368801c3d..9c2372b85 100644 --- a/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/holder/WebSocketSessionHolder.java +++ b/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/holder/WebSocketSessionHolder.java @@ -2,6 +2,7 @@ package org.dromara.common.websocket.holder; import lombok.AccessLevel; import lombok.NoArgsConstructor; +import org.springframework.web.socket.CloseStatus; import org.springframework.web.socket.WebSocketSession; import java.util.Map; @@ -25,6 +26,7 @@ public class WebSocketSessionHolder { * @param session 要添加的WebSocket会话 */ public static void addSession(Long sessionKey, WebSocketSession session) { + removeSession(sessionKey); USER_SESSION_MAP.put(sessionKey, session); } @@ -34,8 +36,10 @@ public class WebSocketSessionHolder { * @param sessionKey 要移除的会话键 */ public static void removeSession(Long sessionKey) { - if (USER_SESSION_MAP.containsKey(sessionKey)) { - USER_SESSION_MAP.remove(sessionKey); + WebSocketSession session = USER_SESSION_MAP.remove(sessionKey); + try { + session.close(CloseStatus.BAD_DATA); + } catch (Exception ignored) { } } diff --git a/ruoyi-extend/ruoyi-monitor-admin/Dockerfile b/ruoyi-extend/ruoyi-monitor-admin/Dockerfile index 99aaa7467..d55b95627 100644 --- a/ruoyi-extend/ruoyi-monitor-admin/Dockerfile +++ b/ruoyi-extend/ruoyi-monitor-admin/Dockerfile @@ -1,6 +1,6 @@ # 贝尔实验室 Spring 官方推荐镜像 JDK下载地址 https://bell-sw.com/pages/downloads/ FROM bellsoft/liberica-openjdk-debian:17.0.11-cds -#FROM bellsoft/liberica-openjdk-debian:21.0.3-cds +#FROM bellsoft/liberica-openjdk-debian:21.0.5-cds #FROM findepi/graalvm:java17-native LABEL maintainer="Lion Li" @@ -15,6 +15,8 @@ EXPOSE 9090 ADD ./target/ruoyi-monitor-admin.jar ./app.jar +SHELL ["/bin/bash", "-c"] + ENTRYPOINT java -Djava.security.egd=file:/dev/./urandom \ -XX:+HeapDumpOnOutOfMemoryError -XX:+UseZGC ${JAVA_OPTS} \ -jar app.jar diff --git a/ruoyi-extend/ruoyi-monitor-admin/src/main/resources/application.yml b/ruoyi-extend/ruoyi-monitor-admin/src/main/resources/application.yml index 622c93d3c..b9720cba8 100644 --- a/ruoyi-extend/ruoyi-monitor-admin/src/main/resources/application.yml +++ b/ruoyi-extend/ruoyi-monitor-admin/src/main/resources/application.yml @@ -19,7 +19,6 @@ spring: admin: ui: title: RuoYi-Vue-Plus服务监控中心 - context-path: /admin --- # Actuator 监控端点的配置项 management: @@ -38,7 +37,7 @@ spring.boot.admin.client: # 增加客户端开关 enabled: true # 设置 Spring Boot Admin Server 地址 - url: http://localhost:9090/admin + url: http://localhost:9090 instance: service-host-type: IP metadata: diff --git a/ruoyi-extend/ruoyi-monitor-admin/src/main/resources/logback-plus.xml b/ruoyi-extend/ruoyi-monitor-admin/src/main/resources/logback-plus.xml index 16bb9376b..45cbbba40 100644 --- a/ruoyi-extend/ruoyi-monitor-admin/src/main/resources/logback-plus.xml +++ b/ruoyi-extend/ruoyi-monitor-admin/src/main/resources/logback-plus.xml @@ -4,7 +4,7 @@ logback + value="%cyan(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) %highlight(%-5level) %boldMagenta(%logger{36}%n) - %msg%n"/> @@ -31,4 +31,4 @@ - \ No newline at end of file + diff --git a/ruoyi-extend/ruoyi-snailjob-server/Dockerfile b/ruoyi-extend/ruoyi-snailjob-server/Dockerfile index a66ca66e4..6f4484d33 100644 --- a/ruoyi-extend/ruoyi-snailjob-server/Dockerfile +++ b/ruoyi-extend/ruoyi-snailjob-server/Dockerfile @@ -1,6 +1,6 @@ # 贝尔实验室 Spring 官方推荐镜像 JDK下载地址 https://bell-sw.com/pages/downloads/ FROM bellsoft/liberica-openjdk-debian:17.0.11-cds -#FROM bellsoft/liberica-openjdk-debian:21.0.3-cds +#FROM bellsoft/liberica-openjdk-debian:21.0.5-cds #FROM findepi/graalvm:java17-native LABEL maintainer="Lion Li" @@ -16,6 +16,8 @@ EXPOSE 17888 ADD ./target/ruoyi-snailjob-server.jar ./app.jar +SHELL ["/bin/bash", "-c"] + ENTRYPOINT java -Djava.security.egd=file:/dev/./urandom \ -XX:+HeapDumpOnOutOfMemoryError -XX:+UseZGC ${JAVA_OPTS} \ -jar app.jar diff --git a/ruoyi-extend/ruoyi-snailjob-server/src/main/java/com/aizuda/snailjob/server/starter/filter/SecurityConfig.java b/ruoyi-extend/ruoyi-snailjob-server/src/main/java/com/aizuda/snailjob/server/starter/filter/SecurityConfig.java index 3cae8f58e..5196c77ef 100644 --- a/ruoyi-extend/ruoyi-snailjob-server/src/main/java/com/aizuda/snailjob/server/starter/filter/SecurityConfig.java +++ b/ruoyi-extend/ruoyi-snailjob-server/src/main/java/com/aizuda/snailjob/server/starter/filter/SecurityConfig.java @@ -22,7 +22,7 @@ public class SecurityConfig { public FilterRegistrationBean actuatorFilterRegistrationBean() { FilterRegistrationBean registrationBean = new FilterRegistrationBean<>(); registrationBean.setFilter(new ActuatorAuthFilter(username, password)); - registrationBean.addUrlPatterns("/actuator", "/actuator/**"); + registrationBean.addUrlPatterns("/actuator", "/actuator/*"); return registrationBean; } diff --git a/ruoyi-extend/ruoyi-snailjob-server/src/main/resources/application-dev.yml b/ruoyi-extend/ruoyi-snailjob-server/src/main/resources/application-dev.yml index 3ed797cf6..44f298aba 100644 --- a/ruoyi-extend/ruoyi-snailjob-server/src/main/resources/application-dev.yml +++ b/ruoyi-extend/ruoyi-snailjob-server/src/main/resources/application-dev.yml @@ -20,8 +20,8 @@ snail-job: retry-pull-page-size: 1000 # 拉取重试数据的每批次的大小 job-pull-page-size: 1000 - # 服务端netty端口 - netty-port: 17888 + # 服务器端口 + server-port: 17888 # 一个客户端每秒最多接收的重试数量指令 limiter: 1000 # 号段模式下步长配置 @@ -34,13 +34,16 @@ snail-job: max-count: 288 #间隔时间 trigger-interval: 900 + # 重试每次拉取的次数 retry-max-pull-count: 10 + # RPC通讯类型: netty,grpc + rpc-type: grpc --- # 监控中心配置 spring.boot.admin.client: # 增加客户端开关 enabled: true - url: http://localhost:9090/admin + url: http://localhost:9090 instance: service-host-type: IP metadata: diff --git a/ruoyi-extend/ruoyi-snailjob-server/src/main/resources/application-prod.yml b/ruoyi-extend/ruoyi-snailjob-server/src/main/resources/application-prod.yml index 1d830dbe7..44f298aba 100644 --- a/ruoyi-extend/ruoyi-snailjob-server/src/main/resources/application-prod.yml +++ b/ruoyi-extend/ruoyi-snailjob-server/src/main/resources/application-prod.yml @@ -20,8 +20,8 @@ snail-job: retry-pull-page-size: 1000 # 拉取重试数据的每批次的大小 job-pull-page-size: 1000 - # 服务端 netty 端口 - netty-port: 17888 + # 服务器端口 + server-port: 17888 # 一个客户端每秒最多接收的重试数量指令 limiter: 1000 # 号段模式下步长配置 @@ -34,13 +34,16 @@ snail-job: max-count: 288 #间隔时间 trigger-interval: 900 + # 重试每次拉取的次数 retry-max-pull-count: 10 + # RPC通讯类型: netty,grpc + rpc-type: grpc --- # 监控中心配置 spring.boot.admin.client: # 增加客户端开关 enabled: true - url: http://localhost:9090/admin + url: http://localhost:9090 instance: service-host-type: IP metadata: diff --git a/ruoyi-extend/ruoyi-snailjob-server/src/main/resources/logback-plus.xml b/ruoyi-extend/ruoyi-snailjob-server/src/main/resources/logback-plus.xml index a40262c9f..be588110c 100644 --- a/ruoyi-extend/ruoyi-snailjob-server/src/main/resources/logback-plus.xml +++ b/ruoyi-extend/ruoyi-snailjob-server/src/main/resources/logback-plus.xml @@ -2,7 +2,7 @@ + value="%cyan(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) %highlight(%-5level) %boldMagenta(%logger{36}%n) - %msg%n"/> diff --git a/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/MailController.java b/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/MailController.java index 47b4349da..01f50449f 100644 --- a/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/MailController.java +++ b/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/MailController.java @@ -1,14 +1,16 @@ package org.dromara.demo.controller; +import cn.dev33.satoken.annotation.SaIgnore; +import lombok.RequiredArgsConstructor; import org.dromara.common.core.domain.R; import org.dromara.common.mail.utils.MailUtils; -import lombok.RequiredArgsConstructor; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.io.File; +import java.util.Arrays; /** @@ -16,6 +18,7 @@ import java.io.File; * * @author Michelle.Chung */ +@SaIgnore @Validated @RequiredArgsConstructor @RestController @@ -49,4 +52,19 @@ public class MailController { return R.ok(); } + /** + * 发送邮件(多附件) + * + * @param to 接收人 + * @param subject 标题 + * @param text 内容 + * @param paths 附件路径 + */ + @GetMapping("/sendMessageWithAttachments") + public R sendMessageWithAttachments(String to, String subject, String text, String[] paths) { + File[] array = Arrays.stream(paths).map(File::new).toArray(File[]::new); + MailUtils.sendText(to, subject, text, array); + return R.ok(); + } + } diff --git a/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/RedisCacheController.java b/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/RedisCacheController.java index 341880c5d..303cf885d 100644 --- a/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/RedisCacheController.java +++ b/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/RedisCacheController.java @@ -1,5 +1,6 @@ package org.dromara.demo.controller; +import cn.hutool.core.thread.ThreadUtil; import org.dromara.common.core.constant.CacheNames; import org.dromara.common.core.domain.R; import org.dromara.common.redis.utils.RedisUtils; @@ -83,11 +84,7 @@ public class RedisCacheController { RedisUtils.setCacheObject(key, value); boolean flag = RedisUtils.expire(key, Duration.ofSeconds(10)); System.out.println("***********" + flag); - try { - Thread.sleep(11 * 1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } + ThreadUtil.sleep(11 * 1000); Object obj = RedisUtils.getCacheObject(key); return R.ok(value.equals(obj)); } diff --git a/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/RedisLockController.java b/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/RedisLockController.java index b7e096266..237b6ee2d 100644 --- a/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/RedisLockController.java +++ b/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/RedisLockController.java @@ -1,5 +1,6 @@ package org.dromara.demo.controller; +import cn.hutool.core.thread.ThreadUtil; import com.baomidou.lock.LockInfo; import com.baomidou.lock.LockTemplate; import com.baomidou.lock.annotation.Lock4j; @@ -33,13 +34,9 @@ public class RedisLockController { @Lock4j(keys = {"#key"}) @GetMapping("/testLock4j") public R testLock4j(String key, String value) { - System.out.println("start:" + key + ",time:" + LocalTime.now().toString()); - try { - Thread.sleep(10000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - System.out.println("end :" + key + ",time:" + LocalTime.now().toString()); + System.out.println("start:" + key + ",time:" + LocalTime.now()); + ThreadUtil.sleep(10000); + System.out.println("end :" + key + ",time:" + LocalTime.now()); return R.ok("操作成功", value); } @@ -54,11 +51,7 @@ public class RedisLockController { } // 获取锁成功,处理业务 try { - try { - Thread.sleep(8000); - } catch (InterruptedException e) { - // - } + ThreadUtil.sleep(8000); System.out.println("执行简单方法1 , 当前线程:" + Thread.currentThread().getName()); } finally { //释放锁 diff --git a/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/vo/ExportDemoVo.java b/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/vo/ExportDemoVo.java index 95fa0d140..ef9058ed5 100644 --- a/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/vo/ExportDemoVo.java +++ b/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/vo/ExportDemoVo.java @@ -15,6 +15,9 @@ import org.dromara.common.excel.annotation.ExcelEnumFormat; import org.dromara.common.excel.convert.ExcelDictConvert; import org.dromara.common.excel.convert.ExcelEnumConvert; +import java.io.Serial; +import java.io.Serializable; + /** * 带有下拉选的Excel导出 * @@ -24,8 +27,9 @@ import org.dromara.common.excel.convert.ExcelEnumConvert; @ExcelIgnoreUnannotated @AllArgsConstructor @NoArgsConstructor -public class ExportDemoVo { +public class ExportDemoVo implements Serializable { + @Serial private static final long serialVersionUID = 1L; /** diff --git a/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/vo/TestDemoVo.java b/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/vo/TestDemoVo.java index 016c2f7dc..e7ea8075c 100644 --- a/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/vo/TestDemoVo.java +++ b/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/vo/TestDemoVo.java @@ -2,6 +2,8 @@ package org.dromara.demo.domain.vo; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.alibaba.excel.annotation.ExcelProperty; +import org.dromara.common.excel.annotation.ExcelNotation; +import org.dromara.common.excel.annotation.ExcelRequired; import org.dromara.common.translation.annotation.Translation; import org.dromara.common.translation.constant.TransConstant; import org.dromara.demo.domain.TestDemo; @@ -36,30 +38,35 @@ public class TestDemoVo implements Serializable { /** * 部门id */ + @ExcelRequired @ExcelProperty(value = "部门id") private Long deptId; /** * 用户id */ + @ExcelRequired @ExcelProperty(value = "用户id") private Long userId; /** * 排序号 */ + @ExcelRequired @ExcelProperty(value = "排序号") private Integer orderNum; /** * key键 */ + @ExcelNotation(value = "测试key") @ExcelProperty(value = "key键") private String testKey; /** * 值 */ + @ExcelNotation(value = "测试value") @ExcelProperty(value = "值") private String value; diff --git a/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/mapper/TestDemoMapper.java b/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/mapper/TestDemoMapper.java index 57efdc7da..19b2d52df 100644 --- a/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/mapper/TestDemoMapper.java +++ b/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/mapper/TestDemoMapper.java @@ -34,14 +34,18 @@ public interface TestDemoMapper extends BaseMapperPlus { @DataColumn(key = "deptName", value = "dept_id"), @DataColumn(key = "userName", value = "user_id") }) - List selectList(IPage page, @Param(Constants.WRAPPER) Wrapper queryWrapper); + default

> P selectVoPage(IPage page, Wrapper wrapper) { + return selectVoPage(page, wrapper, this.currentVoClass()); + } @Override @DataPermission({ @DataColumn(key = "deptName", value = "dept_id"), @DataColumn(key = "userName", value = "user_id") }) - List selectList(@Param(Constants.WRAPPER) Wrapper queryWrapper); + default List selectVoList(Wrapper wrapper) { + return selectVoList(wrapper, this.currentVoClass()); + } @Override @DataPermission(value = { diff --git a/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/service/impl/ExportExcelServiceImpl.java b/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/service/impl/ExportExcelServiceImpl.java index 0240e02f2..69cf0a8af 100644 --- a/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/service/impl/ExportExcelServiceImpl.java +++ b/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/service/impl/ExportExcelServiceImpl.java @@ -1,10 +1,11 @@ package org.dromara.demo.service.impl; +import cn.hutool.core.util.RandomUtil; import cn.hutool.core.util.StrUtil; import jakarta.servlet.http.HttpServletResponse; import lombok.Data; import lombok.RequiredArgsConstructor; -import org.dromara.common.core.enums.UserStatus; +import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.core.utils.StreamUtils; import org.dromara.common.excel.core.DropDownOptions; import org.dromara.common.excel.utils.ExcelUtil; @@ -34,7 +35,7 @@ public class ExportExcelServiceImpl implements IExportExcelService { // 模拟数据库中的一条数据 ExportDemoVo everyRowData = new ExportDemoVo(); everyRowData.setNickName("用户-" + i); - everyRowData.setUserStatus(UserStatus.OK.getCode()); + everyRowData.setUserStatus(SystemConstants.NORMAL); everyRowData.setGender("1"); everyRowData.setPhoneNumber(String.format("175%08d", i)); everyRowData.setEmail(String.format("175%08d", i) + "@163.com"); @@ -121,8 +122,9 @@ public class ExportExcelServiceImpl implements IExportExcelService { List provinceList = new ArrayList<>(); // 实际业务中一般采用数据库读取的形式,这里直接拼接创建 - provinceList.add(new DemoCityData(0, null, "安徽省")); - provinceList.add(new DemoCityData(1, null, "江苏省")); + provinceList.add(new DemoCityData(0, null, "P100000")); + provinceList.add(new DemoCityData(1, null, "P200000")); + provinceList.add(new DemoCityData(2, null, "P300000")); return provinceList; } @@ -137,11 +139,11 @@ public class ExportExcelServiceImpl implements IExportExcelService { List cityList = new ArrayList<>(); // 实际业务中一般采用数据库读取的形式,这里直接拼接创建 - cityList.add(new DemoCityData(0, 0, "合肥市")); - cityList.add(new DemoCityData(1, 0, "芜湖市")); - cityList.add(new DemoCityData(2, 1, "南京市")); - cityList.add(new DemoCityData(3, 1, "无锡市")); - cityList.add(new DemoCityData(4, 1, "徐州市")); + cityList.add(new DemoCityData(0, 0, "C110000")); + cityList.add(new DemoCityData(1, 0, "C120000")); + cityList.add(new DemoCityData(2, 1, "C210000")); + cityList.add(new DemoCityData(3, 1, "C220000")); + cityList.add(new DemoCityData(4, 1, "C230000")); selectParentData(provinceList, cityList); @@ -157,17 +159,29 @@ public class ExportExcelServiceImpl implements IExportExcelService { private List getAreaList(List cityList) { List areaList = new ArrayList<>(); + int minCount = 500; + int maxCount = 10000; + // 实际业务中一般采用数据库读取的形式,这里直接拼接创建 - areaList.add(new DemoCityData(0, 0, "瑶海区")); - areaList.add(new DemoCityData(1, 0, "庐江区")); - areaList.add(new DemoCityData(2, 1, "南宁县")); - areaList.add(new DemoCityData(3, 1, "镜湖区")); - areaList.add(new DemoCityData(4, 2, "玄武区")); - areaList.add(new DemoCityData(5, 2, "秦淮区")); - areaList.add(new DemoCityData(6, 3, "宜兴市")); - areaList.add(new DemoCityData(7, 3, "新吴区")); - areaList.add(new DemoCityData(8, 4, "鼓楼区")); - areaList.add(new DemoCityData(9, 4, "丰县")); + for (int i = 0; i < RandomUtil.randomInt(minCount, maxCount); i++) { + areaList.add(new DemoCityData(areaList.size(), 0, String.format("A11%04d", i))); + } + + for (int i = 0; i < RandomUtil.randomInt(minCount, maxCount); i++) { + areaList.add(new DemoCityData(areaList.size(), 1, String.format("A12%04d", i))); + } + + for (int i = 0; i < RandomUtil.randomInt(minCount, maxCount); i++) { + areaList.add(new DemoCityData(areaList.size(), 2, String.format("A21%04d", i))); + } + + for (int i = 0; i < RandomUtil.randomInt(minCount, maxCount); i++) { + areaList.add(new DemoCityData(areaList.size(), 3, String.format("A22%04d", i))); + } + + for (int i = 0; i < RandomUtil.randomInt(minCount, maxCount); i++) { + areaList.add(new DemoCityData(areaList.size(), 4, String.format("A23%04d", i))); + } selectParentData(cityList, areaList); diff --git a/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/domain/GenTableColumn.java b/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/domain/GenTableColumn.java index e1560b421..6b2e429ed 100644 --- a/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/domain/GenTableColumn.java +++ b/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/domain/GenTableColumn.java @@ -159,7 +159,7 @@ public class GenTableColumn extends BaseEntity { } public boolean isEdit() { - return isInsert(this.isEdit); + return isEdit(this.isEdit); } public boolean isEdit(String isEdit) { diff --git a/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java b/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java index bb8b444fc..6b9e60617 100644 --- a/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java +++ b/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java @@ -29,7 +29,6 @@ import org.dromara.common.core.utils.file.FileUtils; import org.dromara.common.json.utils.JsonUtils; import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.TableDataInfo; -import org.dromara.common.satoken.utils.LoginHelper; import org.dromara.generator.constant.GenConstants; import org.dromara.generator.domain.GenTable; import org.dromara.generator.domain.GenTableColumn; @@ -64,7 +63,7 @@ public class GenTableServiceImpl implements IGenTableService { private final GenTableColumnMapper genTableColumnMapper; private final IdentifierGenerator identifierGenerator; - private static final String[] TABLE_IGNORE = new String[]{"sj_", "act_", "flw_", "gen_"}; + private static final String[] TABLE_IGNORE = new String[]{"sj_", "flow_", "gen_"}; /** * 查询业务字段列表 @@ -106,7 +105,8 @@ public class GenTableServiceImpl implements IGenTableService { .like(StringUtils.isNotBlank(genTable.getTableName()), "lower(table_name)", StringUtils.lowerCase(genTable.getTableName())) .like(StringUtils.isNotBlank(genTable.getTableComment()), "lower(table_comment)", StringUtils.lowerCase(genTable.getTableComment())) .between(params.get("beginTime") != null && params.get("endTime") != null, - "create_time", params.get("beginTime"), params.get("endTime")); + "create_time", params.get("beginTime"), params.get("endTime")) + .orderByDesc("update_time"); return wrapper; } @@ -137,7 +137,7 @@ public class GenTableServiceImpl implements IGenTableService { } // 过滤并转换表格数据 List tables = tablesMap.values().stream() - .filter(x -> !startWithAnyIgnoreCase(x.getName(), TABLE_IGNORE)) + .filter(x -> !StringUtils.startWithAnyIgnoreCase(x.getName(), TABLE_IGNORE)) .filter(x -> { if (CollUtil.isEmpty(tableNames)) { return true; @@ -162,10 +162,12 @@ public class GenTableServiceImpl implements IGenTableService { GenTable gen = new GenTable(); gen.setTableName(x.getName()); gen.setTableComment(x.getComment()); - gen.setCreateTime(x.getCreateTime()); + // postgresql的表元数据没有创建时间这个东西(好奇葩) 只能new Date代替 + gen.setCreateTime(ObjectUtil.defaultIfNull(x.getCreateTime(), new Date())); gen.setUpdateTime(x.getUpdateTime()); return gen; - }).toList(); + }).sorted(Comparator.comparing(GenTable::getCreateTime).reversed()) + .toList(); IPage page = pageQuery.build(); page.setTotal(tables.size()); @@ -174,16 +176,6 @@ public class GenTableServiceImpl implements IGenTableService { return TableDataInfo.build(page); } - public static boolean startWithAnyIgnoreCase(CharSequence cs, CharSequence... searchCharSequences) { - // 判断是否是以指定字符串开头 - for (CharSequence searchCharSequence : searchCharSequences) { - if (StringUtils.startsWithIgnoreCase(cs, searchCharSequence)) { - return true; - } - } - return false; - } - /** * 查询据库列表 * @@ -202,7 +194,7 @@ public class GenTableServiceImpl implements IGenTableService { } List> tableList = tablesMap.values().stream() - .filter(x -> !StringUtils.containsAnyIgnoreCase(x.getName(), TABLE_IGNORE)) + .filter(x -> !StringUtils.startWithAnyIgnoreCase(x.getName(), TABLE_IGNORE)) .filter(x -> tableNameSet.contains(x.getName())).toList(); if (CollUtil.isEmpty(tableList)) { @@ -269,11 +261,10 @@ public class GenTableServiceImpl implements IGenTableService { @DSTransactional @Override public void importGenTable(List tableList, String dataName) { - Long operId = LoginHelper.getUserId(); try { for (GenTable table : tableList) { String tableName = table.getTableName(); - GenUtils.initTable(table, operId); + GenUtils.initTable(table); table.setDataName(dataName); int row = baseMapper.insert(table); if (row > 0) { @@ -304,14 +295,18 @@ public class GenTableServiceImpl implements IGenTableService { @DS("#dataName") @Override public List selectDbTableColumnsByName(String tableName, String dataName) { - LinkedHashMap columns = ServiceProxy.metadata().columns(tableName); + Table table = ServiceProxy.metadata().table(tableName); + if (ObjectUtil.isNull(table)) { + return new ArrayList<>(); + } + LinkedHashMap columns = table.getColumns(); List tableColumns = new ArrayList<>(); columns.forEach((columnName, column) -> { GenTableColumn tableColumn = new GenTableColumn(); tableColumn.setIsPk(String.valueOf(column.isPrimaryKey())); tableColumn.setColumnName(column.getName()); tableColumn.setColumnComment(column.getComment()); - tableColumn.setColumnType(column.getTypeName().toLowerCase()); + tableColumn.setColumnType(column.getOriginType().toLowerCase()); tableColumn.setSort(column.getPosition()); tableColumn.setIsRequired(column.isNullable() == 0 ? "1" : "0"); tableColumn.setIsIncrement(column.isAutoIncrement() == -1 ? "0" : "1"); diff --git a/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/util/GenUtils.java b/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/util/GenUtils.java index 2e6b37b6d..996cf9b71 100644 --- a/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/util/GenUtils.java +++ b/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/util/GenUtils.java @@ -22,14 +22,15 @@ public class GenUtils { /** * 初始化表信息 */ - public static void initTable(GenTable genTable, Long operId) { + public static void initTable(GenTable genTable) { genTable.setClassName(convertClassName(genTable.getTableName())); genTable.setPackageName(GenConfig.getPackageName()); genTable.setModuleName(getModuleName(GenConfig.getPackageName())); genTable.setBusinessName(getBusinessName(genTable.getTableName())); genTable.setFunctionName(replaceText(genTable.getTableComment())); genTable.setFunctionAuthor(GenConfig.getAuthor()); - genTable.setCreateBy(operId); + genTable.setCreateTime(null); + genTable.setUpdateTime(null); } /** @@ -37,9 +38,11 @@ public class GenUtils { */ public static void initColumnField(GenTableColumn column, GenTable table) { String dataType = getDbType(column.getColumnType()); - String columnName = column.getColumnName(); + // 统一转小写 避免有些数据库默认大写问题 如果需要特别书写方式 请在实体类增加注解标注别名 + String columnName = column.getColumnName().toLowerCase(); column.setTableId(table.getTableId()); - column.setCreateBy(table.getCreateBy()); + column.setCreateTime(null); + column.setUpdateTime(null); // 设置java字段名 column.setJavaField(StringUtils.toCamelCase(columnName)); // 设置默认类型 @@ -56,20 +59,9 @@ public class GenUtils { column.setHtmlType(GenConstants.HTML_DATETIME); } else if (arraysContains(GenConstants.COLUMNTYPE_NUMBER, dataType)) { column.setHtmlType(GenConstants.HTML_INPUT); - - // 如果是浮点型 统一用BigDecimal - String[] str = StringUtils.split(StringUtils.substringBetween(column.getColumnType(), "(", ")"), StringUtils.SEPARATOR); - if (str != null && str.length == 2 && Integer.parseInt(str[1]) > 0) { - column.setJavaType(GenConstants.TYPE_BIGDECIMAL); - } - // 如果是整形 - else if (str != null && str.length == 1 && Integer.parseInt(str[0]) <= 10) { - column.setJavaType(GenConstants.TYPE_INTEGER); - } - // 长整形 - else { - column.setJavaType(GenConstants.TYPE_LONG); - } + // 数据库的数字字段与java不匹配 且很多数据库的数字字段很模糊 例如oracle只有number没有细分 + // 所以默认数字类型全为Long可在界面上自行编辑想要的类型 有什么特殊需求也可以在这里特殊处理 + column.setJavaType(GenConstants.TYPE_LONG); } // BO对象 默认插入勾选 @@ -80,10 +72,6 @@ public class GenUtils { if (!arraysContains(GenConstants.COLUMNNAME_NOT_EDIT, columnName)) { column.setIsEdit(GenConstants.REQUIRE); } - // BO对象 默认是否必填勾选 - if (!arraysContains(GenConstants.COLUMNNAME_NOT_EDIT, columnName)) { - column.setIsRequired(GenConstants.REQUIRE); - } // VO对象 默认返回勾选 if (!arraysContains(GenConstants.COLUMNNAME_NOT_LIST, columnName)) { column.setIsList(GenConstants.REQUIRE); diff --git a/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/serviceImpl.java.vm b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/serviceImpl.java.vm index 67690ca6e..48cc8b15b 100644 --- a/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/serviceImpl.java.vm +++ b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/serviceImpl.java.vm @@ -95,6 +95,10 @@ public class ${ClassName}ServiceImpl implements I${ClassName}Service { ${ClassName}::get$AttrName ,params.get("begin$AttrName"), params.get("end$AttrName")); #end #end +#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) +#if($column.isPk==1) + lqw.orderByAsc(${ClassName}::get$AttrName); +#end #end return lqw; } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/monitor/SysUserOnlineController.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/monitor/SysUserOnlineController.java index 9b08c2d2c..1cab23251 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/monitor/SysUserOnlineController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/monitor/SysUserOnlineController.java @@ -19,6 +19,7 @@ import org.dromara.system.domain.SysUserOnline; import org.springframework.web.bind.annotation.*; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; @@ -43,7 +44,7 @@ public class SysUserOnlineController extends BaseController { @GetMapping("/list") public TableDataInfo list(String ipaddr, String userName) { // 获取所有未过期的 token - List keys = StpUtil.searchTokenValue("", 0, -1, false); + Collection keys = RedisUtils.keys(CacheConstants.ONLINE_TOKEN_KEY + "*"); List userOnlineDTOList = new ArrayList<>(); for (String key : keys) { String token = StringUtils.substringAfterLast(key, ":"); @@ -113,7 +114,7 @@ public class SysUserOnlineController extends BaseController { * @param tokenId token值 */ @Log(title = "在线设备", businessType = BusinessType.FORCE) - @PostMapping("/{tokenId}") + @DeleteMapping("/myself/{tokenId}") public R remove(@PathVariable("tokenId") String tokenId) { try { // 获取指定账号 id 的 token 集合 diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysClientController.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysClientController.java index 13be4a4a9..eaed06847 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysClientController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysClientController.java @@ -97,7 +97,7 @@ public class SysClientController extends BaseController { @Log(title = "客户端管理", businessType = BusinessType.UPDATE) @PutMapping("/changeStatus") public R changeStatus(@RequestBody SysClientBo bo) { - return toAjax(sysClientService.updateUserStatus(bo.getClientId(), bo.getStatus())); + return toAjax(sysClientService.updateClientStatus(bo.getClientId(), bo.getStatus())); } /** diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysDeptController.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysDeptController.java index 968bbe906..45b841850 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysDeptController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysDeptController.java @@ -3,7 +3,7 @@ package org.dromara.system.controller.system; import cn.dev33.satoken.annotation.SaCheckPermission; import cn.hutool.core.convert.Convert; import lombok.RequiredArgsConstructor; -import org.dromara.common.core.constant.UserConstants; +import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.core.domain.R; import org.dromara.common.core.utils.StringUtils; import org.dromara.common.log.annotation.Log; @@ -94,7 +94,7 @@ public class SysDeptController extends BaseController { return R.fail("修改部门'" + dept.getDeptName() + "'失败,部门名称已存在"); } else if (dept.getParentId().equals(deptId)) { return R.fail("修改部门'" + dept.getDeptName() + "'失败,上级部门不能是自己"); - } else if (StringUtils.equals(UserConstants.DEPT_DISABLE, dept.getStatus())) { + } else if (StringUtils.equals(SystemConstants.DISABLE, dept.getStatus())) { if (deptService.selectNormalChildrenDeptById(deptId) > 0) { return R.fail("该部门包含未停用的子部门!"); } else if (deptService.checkDeptExistUser(deptId)) { diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysMenuController.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysMenuController.java index e5daa0e12..d8cd335ce 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysMenuController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysMenuController.java @@ -4,8 +4,9 @@ import cn.dev33.satoken.annotation.SaCheckPermission; import cn.dev33.satoken.annotation.SaCheckRole; import cn.dev33.satoken.annotation.SaMode; import cn.hutool.core.lang.tree.Tree; +import lombok.RequiredArgsConstructor; +import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.core.constant.TenantConstants; -import org.dromara.common.core.constant.UserConstants; import org.dromara.common.core.domain.R; import org.dromara.common.core.utils.StringUtils; import org.dromara.common.log.annotation.Log; @@ -18,7 +19,6 @@ import org.dromara.system.domain.vo.MenuTreeSelectVo; import org.dromara.system.domain.vo.RouterVo; import org.dromara.system.domain.vo.SysMenuVo; import org.dromara.system.service.ISysMenuService; -import lombok.RequiredArgsConstructor; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -128,7 +128,7 @@ public class SysMenuController extends BaseController { public R add(@Validated @RequestBody SysMenuBo menu) { if (!menuService.checkMenuNameUnique(menu)) { return R.fail("新增菜单'" + menu.getMenuName() + "'失败,菜单名称已存在"); - } else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath())) { + } else if (SystemConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath())) { return R.fail("新增菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头"); } return toAjax(menuService.insertMenu(menu)); @@ -144,7 +144,7 @@ public class SysMenuController extends BaseController { public R edit(@Validated @RequestBody SysMenuBo menu) { if (!menuService.checkMenuNameUnique(menu)) { return R.fail("修改菜单'" + menu.getMenuName() + "'失败,菜单名称已存在"); - } else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath())) { + } else if (SystemConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath())) { return R.fail("修改菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头"); } else if (menu.getMenuId().equals(menu.getParentId())) { return R.fail("修改菜单'" + menu.getMenuName() + "'失败,上级菜单不能选择自己"); diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysOssController.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysOssController.java index 73ada3b84..81200c115 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysOssController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysOssController.java @@ -53,7 +53,7 @@ public class SysOssController extends BaseController { * * @param ossIds OSS对象ID串 */ - @SaCheckPermission("system:oss:list") + @SaCheckPermission("system:oss:query") @GetMapping("/listByIds/{ossIds}") public R> listByIds(@NotEmpty(message = "主键不能为空") @PathVariable Long[] ossIds) { diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysPostController.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysPostController.java index 782bcfc55..5333a4aef 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysPostController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysPostController.java @@ -4,7 +4,7 @@ import cn.dev33.satoken.annotation.SaCheckPermission; import cn.hutool.core.util.ObjectUtil; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; -import org.dromara.common.core.constant.UserConstants; +import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.core.domain.R; import org.dromara.common.excel.utils.ExcelUtil; import org.dromara.common.log.annotation.Log; @@ -91,7 +91,7 @@ public class SysPostController extends BaseController { return R.fail("修改岗位'" + post.getPostName() + "'失败,岗位名称已存在"); } else if (!postService.checkPostCodeUnique(post)) { return R.fail("修改岗位'" + post.getPostName() + "'失败,岗位编码已存在"); - } else if (UserConstants.POST_DISABLE.equals(post.getStatus()) + } else if (SystemConstants.DISABLE.equals(post.getStatus()) && postService.countUserPostById(post.getPostId()) > 0) { return R.fail("该岗位下存在已分配用户,不能禁用!"); } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysProfileController.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysProfileController.java index 893b381e3..5f187cb91 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysProfileController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysProfileController.java @@ -98,8 +98,8 @@ public class SysProfileController extends BaseController { if (BCrypt.checkpw(bo.getNewPassword(), password)) { return R.fail("新密码不能与旧密码相同"); } - - if (userService.resetUserPwd(user.getUserId(), BCrypt.hashpw(bo.getNewPassword())) > 0) { + int rows = DataPermissionHelper.ignore(() -> userService.resetUserPwd(user.getUserId(), BCrypt.hashpw(bo.getNewPassword()))); + if (rows > 0) { return R.ok(); } return R.fail("修改密码异常,请联系管理员"); @@ -121,7 +121,8 @@ public class SysProfileController extends BaseController { } SysOssVo oss = ossService.upload(avatarfile); String avatar = oss.getUrl(); - if (userService.updateUserAvatar(LoginHelper.getUserId(), oss.getOssId())) { + boolean updateSuccess = DataPermissionHelper.ignore(() -> userService.updateUserAvatar(LoginHelper.getUserId(), oss.getOssId())); + if (updateSuccess) { AvatarVo avatarVo = new AvatarVo(); avatarVo.setImgUrl(avatar); return R.ok(avatarVo); diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysTenantController.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysTenantController.java index 10c6777e7..66c1b7ddf 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysTenantController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysTenantController.java @@ -59,7 +59,7 @@ public class SysTenantController extends BaseController { */ @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY) @SaCheckPermission("system:tenant:export") - @Log(title = "租户", businessType = BusinessType.EXPORT) + @Log(title = "租户管理", businessType = BusinessType.EXPORT) @PostMapping("/export") public void export(SysTenantBo bo, HttpServletResponse response) { List list = tenantService.queryList(bo); @@ -85,7 +85,7 @@ public class SysTenantController extends BaseController { @ApiEncrypt @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY) @SaCheckPermission("system:tenant:add") - @Log(title = "租户", businessType = BusinessType.INSERT) + @Log(title = "租户管理", businessType = BusinessType.INSERT) @Lock4j @RepeatSubmit() @PostMapping() @@ -101,7 +101,7 @@ public class SysTenantController extends BaseController { */ @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY) @SaCheckPermission("system:tenant:edit") - @Log(title = "租户", businessType = BusinessType.UPDATE) + @Log(title = "租户管理", businessType = BusinessType.UPDATE) @RepeatSubmit() @PutMapping() public R edit(@Validated(EditGroup.class) @RequestBody SysTenantBo bo) { @@ -117,7 +117,7 @@ public class SysTenantController extends BaseController { */ @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY) @SaCheckPermission("system:tenant:edit") - @Log(title = "租户", businessType = BusinessType.UPDATE) + @Log(title = "租户管理", businessType = BusinessType.UPDATE) @PutMapping("/changeStatus") public R changeStatus(@RequestBody SysTenantBo bo) { tenantService.checkTenantAllowed(bo.getTenantId()); @@ -131,7 +131,7 @@ public class SysTenantController extends BaseController { */ @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY) @SaCheckPermission("system:tenant:remove") - @Log(title = "租户", businessType = BusinessType.DELETE) + @Log(title = "租户管理", businessType = BusinessType.DELETE) @DeleteMapping("/{ids}") public R remove(@NotEmpty(message = "主键不能为空") @PathVariable Long[] ids) { @@ -169,7 +169,7 @@ public class SysTenantController extends BaseController { */ @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY) @SaCheckPermission("system:tenant:edit") - @Log(title = "租户", businessType = BusinessType.UPDATE) + @Log(title = "租户管理", businessType = BusinessType.UPDATE) @GetMapping("/syncTenantPackage") public R syncTenantPackage(@NotBlank(message = "租户ID不能为空") String tenantId, @NotNull(message = "套餐ID不能为空") Long packageId) { @@ -180,7 +180,7 @@ public class SysTenantController extends BaseController { * 同步租户字典 */ @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY) - @Log(title = "同步租户字典", businessType = BusinessType.INSERT) + @Log(title = "租户管理", businessType = BusinessType.INSERT) @GetMapping("/syncTenantDict") public R syncTenantDict() { if (!TenantHelper.isEnable()) { diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysUserController.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysUserController.java index 36104d627..e1e868a6e 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysUserController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysUserController.java @@ -8,7 +8,7 @@ import cn.hutool.core.util.ObjectUtil; import jakarta.servlet.http.HttpServletResponse; import jakarta.validation.constraints.NotNull; import lombok.RequiredArgsConstructor; -import org.dromara.common.core.constant.UserConstants; +import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.core.domain.R; import org.dromara.common.core.domain.model.LoginUser; import org.dromara.common.core.utils.StreamUtils; @@ -128,13 +128,9 @@ public class SysUserController extends BaseController { @SaCheckPermission("system:user:query") @GetMapping(value = {"/", "/{userId}"}) public R getInfo(@PathVariable(value = "userId", required = false) Long userId) { - userService.checkUserDataScope(userId); SysUserInfoVo userInfoVo = new SysUserInfoVo(); - SysRoleBo roleBo = new SysRoleBo(); - roleBo.setStatus(UserConstants.ROLE_NORMAL); - List roles = roleService.selectRoleList(roleBo); - userInfoVo.setRoles(LoginHelper.isSuperAdmin(userId) ? roles : StreamUtils.filter(roles, r -> !r.isSuperAdmin())); if (ObjectUtil.isNotNull(userId)) { + userService.checkUserDataScope(userId); SysUserVo sysUser = userService.selectUserById(userId); userInfoVo.setUser(sysUser); userInfoVo.setRoleIds(roleService.selectRoleListByUserId(userId)); @@ -146,6 +142,10 @@ public class SysUserController extends BaseController { userInfoVo.setPostIds(postService.selectPostListByUserId(userId)); } } + SysRoleBo roleBo = new SysRoleBo(); + roleBo.setStatus(SystemConstants.NORMAL); + List roles = roleService.selectRoleList(roleBo); + userInfoVo.setRoles(LoginHelper.isSuperAdmin(userId) ? roles : StreamUtils.filter(roles, r -> !r.isSuperAdmin())); return R.ok(userInfoVo); } @@ -218,7 +218,7 @@ public class SysUserController extends BaseController { @GetMapping("/optionselect") public R> optionselect(@RequestParam(required = false) Long[] userIds, @RequestParam(required = false) Long deptId) { - return R.ok(userService.selectUserByIds(userIds == null ? null : List.of(userIds), deptId)); + return R.ok(userService.selectUserByIds(ArrayUtil.isEmpty(userIds) ? null : List.of(userIds), deptId)); } /** diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysClient.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysClient.java index 0f681be08..ee2475d08 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysClient.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysClient.java @@ -68,7 +68,7 @@ public class SysClient extends BaseEntity { private String status; /** - * 删除标志(0代表存在 2代表删除) + * 删除标志(0代表存在 1代表删除) */ @TableLogic private String delFlag; diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysDept.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysDept.java index 48ca6821b..b94fd8a31 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysDept.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysDept.java @@ -70,7 +70,7 @@ public class SysDept extends TenantEntity { private String status; /** - * 删除标志(0代表存在 2代表删除) + * 删除标志(0代表存在 1代表删除) */ @TableLogic private String delFlag; diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysDictData.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysDictData.java index 6884fc2db..9d83736e5 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysDictData.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysDictData.java @@ -2,10 +2,10 @@ package org.dromara.system.domain; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; -import org.dromara.common.core.constant.UserConstants; -import org.dromara.common.tenant.core.TenantEntity; import lombok.Data; import lombok.EqualsAndHashCode; +import org.dromara.common.core.constant.SystemConstants; +import org.dromara.common.tenant.core.TenantEntity; /** * 字典数据表 sys_dict_data @@ -65,7 +65,7 @@ public class SysDictData extends TenantEntity { private String remark; public boolean getDefault() { - return UserConstants.YES.equals(this.isDefault); + return SystemConstants.YES.equals(this.isDefault); } } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysMenu.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysMenu.java index 6b498a38e..2df55962b 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysMenu.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysMenu.java @@ -3,12 +3,12 @@ package org.dromara.system.domain; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; -import org.dromara.common.core.constant.Constants; -import org.dromara.common.core.constant.UserConstants; -import org.dromara.common.core.utils.StringUtils; -import org.dromara.common.mybatis.core.domain.BaseEntity; import lombok.Data; import lombok.EqualsAndHashCode; +import org.dromara.common.core.constant.Constants; +import org.dromara.common.core.constant.SystemConstants; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.mybatis.core.domain.BaseEntity; import java.util.ArrayList; import java.util.List; @@ -134,8 +134,8 @@ public class SysMenu extends BaseEntity { routerPath = innerLinkReplaceEach(routerPath); } // 非外链并且是一级目录(类型为目录) - if (0L == getParentId() && UserConstants.TYPE_DIR.equals(getMenuType()) - && UserConstants.NO_FRAME.equals(getIsFrame())) { + if (0L == getParentId() && SystemConstants.TYPE_DIR.equals(getMenuType()) + && SystemConstants.NO_FRAME.equals(getIsFrame())) { routerPath = "/" + this.path; } // 非外链并且是一级目录(类型为菜单) @@ -149,13 +149,13 @@ public class SysMenu extends BaseEntity { * 获取组件信息 */ public String getComponentInfo() { - String component = UserConstants.LAYOUT; + String component = SystemConstants.LAYOUT; if (StringUtils.isNotEmpty(this.component) && !isMenuFrame()) { component = this.component; } else if (StringUtils.isEmpty(this.component) && getParentId() != 0L && isInnerLink()) { - component = UserConstants.INNER_LINK; + component = SystemConstants.INNER_LINK; } else if (StringUtils.isEmpty(this.component) && isParentView()) { - component = UserConstants.PARENT_VIEW; + component = SystemConstants.PARENT_VIEW; } return component; } @@ -164,21 +164,21 @@ public class SysMenu extends BaseEntity { * 是否为菜单内部跳转 */ public boolean isMenuFrame() { - return getParentId() == 0L && UserConstants.TYPE_MENU.equals(menuType) && isFrame.equals(UserConstants.NO_FRAME); + return getParentId() == 0L && SystemConstants.TYPE_MENU.equals(menuType) && isFrame.equals(SystemConstants.NO_FRAME); } /** * 是否为内链组件 */ public boolean isInnerLink() { - return isFrame.equals(UserConstants.NO_FRAME) && StringUtils.ishttp(path); + return isFrame.equals(SystemConstants.NO_FRAME) && StringUtils.ishttp(path); } /** * 是否为parent_view组件 */ public boolean isParentView() { - return getParentId() != 0L && UserConstants.TYPE_DIR.equals(menuType); + return getParentId() != 0L && SystemConstants.TYPE_DIR.equals(menuType); } /** diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysRole.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysRole.java index 2b4246404..a7c0ad5a0 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysRole.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysRole.java @@ -62,7 +62,7 @@ public class SysRole extends TenantEntity { private String status; /** - * 删除标志(0代表存在 2代表删除) + * 删除标志(0代表存在 1代表删除) */ @TableLogic private String delFlag; diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysTenant.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysTenant.java index a564a40c5..9800c3075 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysTenant.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysTenant.java @@ -95,7 +95,7 @@ public class SysTenant extends BaseEntity { private String status; /** - * 删除标志(0代表存在 2代表删除) + * 删除标志(0代表存在 1代表删除) */ @TableLogic private String delFlag; diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysTenantPackage.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysTenantPackage.java index f7e423f0f..5f58e3eca 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysTenantPackage.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysTenantPackage.java @@ -25,28 +25,34 @@ public class SysTenantPackage extends BaseEntity { */ @TableId(value = "package_id") private Long packageId; + /** * 套餐名称 */ private String packageName; + /** * 关联菜单id */ private String menuIds; + /** * 备注 */ private String remark; + /** * 菜单树选择项是否关联显示( 0:父子不互相关联显示 1:父子互相关联显示) */ private Boolean menuCheckStrictly; + /** * 状态(0正常 1停用) */ private String status; + /** - * 删除标志(0代表存在 2代表删除) + * 删除标志(0代表存在 1代表删除) */ @TableLogic private String delFlag; diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysUser.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysUser.java index 8dde40b35..3712f805f 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysUser.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysUser.java @@ -1,11 +1,11 @@ package org.dromara.system.domain; import com.baomidou.mybatisplus.annotation.*; -import org.dromara.common.core.constant.UserConstants; -import org.dromara.common.tenant.core.TenantEntity; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import org.dromara.common.core.constant.SystemConstants; +import org.dromara.common.tenant.core.TenantEntity; import java.util.Date; @@ -83,7 +83,7 @@ public class SysUser extends TenantEntity { private String status; /** - * 删除标志(0代表存在 2代表删除) + * 删除标志(0代表存在 1代表删除) */ @TableLogic private String delFlag; @@ -109,7 +109,7 @@ public class SysUser extends TenantEntity { } public boolean isSuperAdmin() { - return UserConstants.SUPER_ADMIN_ID.equals(this.userId); + return SystemConstants.SUPER_ADMIN_ID.equals(this.userId); } } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysRoleBo.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysRoleBo.java index 0c8b4dca9..3207bad1e 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysRoleBo.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysRoleBo.java @@ -7,7 +7,7 @@ import jakarta.validation.constraints.Size; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; -import org.dromara.common.core.constant.UserConstants; +import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.mybatis.core.domain.BaseEntity; import org.dromara.system.domain.SysRole; @@ -88,7 +88,7 @@ public class SysRoleBo extends BaseEntity { } public boolean isSuperAdmin() { - return UserConstants.SUPER_ADMIN_ID.equals(this.roleId); + return SystemConstants.SUPER_ADMIN_ID.equals(this.roleId); } } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysUserBo.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysUserBo.java index 7ad2759b2..2669a8179 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysUserBo.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysUserBo.java @@ -7,7 +7,7 @@ import jakarta.validation.constraints.Size; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; -import org.dromara.common.core.constant.UserConstants; +import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.core.xss.Xss; import org.dromara.common.mybatis.core.domain.BaseEntity; import org.dromara.system.domain.SysUser; @@ -113,7 +113,7 @@ public class SysUserBo extends BaseEntity { } public boolean isSuperAdmin() { - return UserConstants.SUPER_ADMIN_ID.equals(this.userId); + return SystemConstants.SUPER_ADMIN_ID.equals(this.userId); } } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysRoleVo.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysRoleVo.java index 1e5cd9ee6..ffb2c6d5a 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysRoleVo.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysRoleVo.java @@ -2,12 +2,12 @@ package org.dromara.system.domain.vo; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.alibaba.excel.annotation.ExcelProperty; -import org.dromara.common.core.constant.UserConstants; +import io.github.linpeilie.annotations.AutoMapper; +import lombok.Data; +import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.excel.annotation.ExcelDictFormat; import org.dromara.common.excel.convert.ExcelDictConvert; import org.dromara.system.domain.SysRole; -import io.github.linpeilie.annotations.AutoMapper; -import lombok.Data; import java.io.Serial; import java.io.Serializable; @@ -94,7 +94,7 @@ public class SysRoleVo implements Serializable { private boolean flag = false; public boolean isSuperAdmin() { - return UserConstants.SUPER_ADMIN_ID.equals(this.roleId); + return SystemConstants.SUPER_ADMIN_ID.equals(this.roleId); } } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysDeptMapper.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysDeptMapper.java index 08dda662c..b69624cf0 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysDeptMapper.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysDeptMapper.java @@ -1,13 +1,16 @@ package org.dromara.system.mapper; import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Constants; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.apache.ibatis.annotations.Param; import org.dromara.common.mybatis.annotation.DataColumn; import org.dromara.common.mybatis.annotation.DataPermission; import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; +import org.dromara.common.mybatis.helper.DataBaseHelper; import org.dromara.system.domain.SysDept; import org.dromara.system.domain.vo.SysDeptVo; -import org.apache.ibatis.annotations.Param; import java.util.List; @@ -29,11 +32,40 @@ public interface SysDeptMapper extends BaseMapperPlus { }) List selectDeptList(@Param(Constants.WRAPPER) Wrapper queryWrapper); + /** + * 分页查询部门管理数据 + * + * @param queryWrapper 查询条件 + * @return 部门信息集合 + */ + @DataPermission({ + @DataColumn(key = "deptName", value = "dept_id"), + }) + Page selectPageDeptList(@Param("page") Page page, @Param(Constants.WRAPPER) Wrapper queryWrapper); + + /** + * 统计指定部门ID的部门数量 + * + * @param deptId 部门ID + * @return 该部门ID的部门数量 + */ @DataPermission({ @DataColumn(key = "deptName", value = "dept_id") }) long countDeptById(Long deptId); + /** + * 根据父部门ID查询其所有子部门的列表 + * + * @param parentId 父部门ID + * @return 包含子部门的列表 + */ + default List selectListByParentId(Long parentId) { + return this.selectList(new LambdaQueryWrapper() + .select(SysDept::getDeptId) + .apply(DataBaseHelper.findInSet(parentId, "ancestors"))); + } + /** * 根据角色ID查询部门树信息 * diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysDictDataMapper.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysDictDataMapper.java index c2f1a7cbe..7298db3d0 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysDictDataMapper.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysDictDataMapper.java @@ -14,6 +14,12 @@ import java.util.List; */ public interface SysDictDataMapper extends BaseMapperPlus { + /** + * 根据字典类型查询字典数据列表 + * + * @param dictType 字典类型 + * @return 符合条件的字典数据列表 + */ default List selectDictDataByType(String dictType) { return selectVoList( new LambdaQueryWrapper() diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysMenuMapper.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysMenuMapper.java index ac646c096..205413b3f 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysMenuMapper.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysMenuMapper.java @@ -3,11 +3,11 @@ package org.dromara.system.mapper; import com.baomidou.mybatisplus.core.conditions.Wrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Constants; -import org.dromara.common.core.constant.UserConstants; -import org.dromara.system.domain.SysMenu; -import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; -import org.dromara.system.domain.vo.SysMenuVo; import org.apache.ibatis.annotations.Param; +import org.dromara.common.core.constant.SystemConstants; +import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; +import org.dromara.system.domain.SysMenu; +import org.dromara.system.domain.vo.SysMenuVo; import java.util.List; @@ -49,8 +49,8 @@ public interface SysMenuMapper extends BaseMapperPlus { */ default List selectMenuTreeAll() { LambdaQueryWrapper lqw = new LambdaQueryWrapper() - .in(SysMenu::getMenuType, UserConstants.TYPE_DIR, UserConstants.TYPE_MENU) - .eq(SysMenu::getStatus, UserConstants.MENU_NORMAL) + .in(SysMenu::getMenuType, SystemConstants.TYPE_DIR, SystemConstants.TYPE_MENU) + .eq(SysMenu::getStatus, SystemConstants.NORMAL) .orderByAsc(SysMenu::getParentId) .orderByAsc(SysMenu::getOrderNum); return this.selectList(lqw); diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysPostMapper.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysPostMapper.java index f9bf13485..60da074c7 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysPostMapper.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysPostMapper.java @@ -19,6 +19,13 @@ import java.util.List; */ public interface SysPostMapper extends BaseMapperPlus { + /** + * 分页查询岗位列表 + * + * @param page 分页对象 + * @param queryWrapper 查询条件 + * @return 包含岗位信息的分页结果 + */ @DataPermission({ @DataColumn(key = "deptName", value = "dept_id"), @DataColumn(key = "userName", value = "create_by") diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysRoleMapper.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysRoleMapper.java index ac5a47e54..9cb1ea509 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysRoleMapper.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysRoleMapper.java @@ -19,6 +19,13 @@ import java.util.List; */ public interface SysRoleMapper extends BaseMapperPlus { + /** + * 分页查询角色列表 + * + * @param page 分页对象 + * @param queryWrapper 查询条件 + * @return 包含角色信息的分页结果 + */ @DataPermission({ @DataColumn(key = "deptName", value = "d.dept_id"), @DataColumn(key = "userName", value = "r.create_by") @@ -37,6 +44,12 @@ public interface SysRoleMapper extends BaseMapperPlus { }) List selectRoleList(@Param(Constants.WRAPPER) Wrapper queryWrapper); + /** + * 根据角色ID查询角色信息 + * + * @param roleId 角色ID + * @return 对应的角色信息 + */ @DataPermission({ @DataColumn(key = "deptName", value = "d.dept_id"), @DataColumn(key = "userName", value = "r.create_by") diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysUserMapper.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysUserMapper.java index fc7fc6e16..46695aa4c 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysUserMapper.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysUserMapper.java @@ -20,12 +20,25 @@ import java.util.List; */ public interface SysUserMapper extends BaseMapperPlus { + /** + * 分页查询用户列表,并进行数据权限控制 + * + * @param page 分页参数 + * @param queryWrapper 查询条件 + * @return 分页的用户信息 + */ @DataPermission({ @DataColumn(key = "deptName", value = "u.dept_id"), @DataColumn(key = "userName", value = "u.user_id") }) Page selectPageUserList(@Param("page") Page page, @Param(Constants.WRAPPER) Wrapper queryWrapper); + /** + * 查询用户列表,并进行数据权限控制 + * + * @param queryWrapper 查询条件 + * @return 用户信息集合 + */ @DataPermission({ @DataColumn(key = "deptName", value = "dept_id"), @DataColumn(key = "userName", value = "user_id") @@ -68,12 +81,25 @@ public interface SysUserMapper extends BaseMapperPlus { }) Page selectUnallocatedList(@Param("page") Page page, @Param(Constants.WRAPPER) Wrapper queryWrapper); + /** + * 根据用户ID统计用户数量 + * + * @param userId 用户ID + * @return 用户数量 + */ @DataPermission({ @DataColumn(key = "deptName", value = "dept_id"), @DataColumn(key = "userName", value = "user_id") }) long countUserById(Long userId); + /** + * 根据条件更新用户数据 + * + * @param user 要更新的用户实体 + * @param updateWrapper 更新条件封装器 + * @return 更新操作影响的行数 + */ @Override @DataPermission({ @DataColumn(key = "deptName", value = "dept_id"), @@ -81,6 +107,12 @@ public interface SysUserMapper extends BaseMapperPlus { }) int update(@Param(Constants.ENTITY) SysUser user, @Param(Constants.WRAPPER) Wrapper updateWrapper); + /** + * 根据用户ID更新用户数据 + * + * @param user 要更新的用户实体 + * @return 更新操作影响的行数 + */ @Override @DataPermission({ @DataColumn(key = "deptName", value = "dept_id"), diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysUserRoleMapper.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysUserRoleMapper.java index e2f706c89..83403480e 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysUserRoleMapper.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysUserRoleMapper.java @@ -12,6 +12,12 @@ import java.util.List; */ public interface SysUserRoleMapper extends BaseMapperPlus { + /** + * 根据角色ID查询关联的用户ID列表 + * + * @param roleId 角色ID + * @return 关联到指定角色的用户ID列表 + */ List selectUserIdsByRoleId(Long roleId); } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysClientService.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysClientService.java index d0f8a3cbe..546c3f33a 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysClientService.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysClientService.java @@ -50,7 +50,7 @@ public interface ISysClientService { /** * 修改状态 */ - int updateUserStatus(String clientId, String status); + int updateClientStatus(String clientId, String status); /** * 校验并批量删除客户端管理信息 diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysPostService.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysPostService.java index 3751b23be..a760d497e 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysPostService.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysPostService.java @@ -25,6 +25,14 @@ public interface ISysPostService { */ List selectPostList(SysPostBo post); + /** + * 查询用户所属岗位组 + * + * @param userId 用户ID + * @return 岗位ID + */ + List selectPostsByUserId(Long userId); + /** * 查询所有岗位 * diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysRoleService.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysRoleService.java index 64740aeff..cec4bf775 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysRoleService.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysRoleService.java @@ -197,4 +197,6 @@ public interface ISysRoleService { void cleanOnlineUserByRole(Long roleId); + void cleanOnlineUser(List userIds); + } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysClientServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysClientServiceImpl.java index 1c6924320..4f6e676df 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysClientServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysClientServiceImpl.java @@ -123,7 +123,7 @@ public class SysClientServiceImpl implements ISysClientService { */ @CacheEvict(cacheNames = CacheNames.SYS_CLIENT, key = "#clientId") @Override - public int updateUserStatus(String clientId, String status) { + public int updateClientStatus(String clientId, String status) { return baseMapper.update(null, new LambdaUpdateWrapper() .set(SysClient::getStatus, status) diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysConfigServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysConfigServiceImpl.java index 46526bd98..d92647c44 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysConfigServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysConfigServiceImpl.java @@ -7,10 +7,11 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import org.dromara.common.core.constant.CacheNames; -import org.dromara.common.core.constant.UserConstants; +import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.service.ConfigService; import org.dromara.common.core.utils.MapstructUtils; +import org.dromara.common.core.utils.ObjectUtils; import org.dromara.common.core.utils.SpringUtils; import org.dromara.common.core.utils.StringUtils; import org.dromara.common.mybatis.core.page.PageQuery; @@ -72,10 +73,7 @@ public class SysConfigServiceImpl implements ISysConfigService, ConfigService { public String selectConfigByKey(String configKey) { SysConfig retConfig = baseMapper.selectOne(new LambdaQueryWrapper() .eq(SysConfig::getConfigKey, configKey)); - if (ObjectUtil.isNotNull(retConfig)) { - return retConfig.getConfigValue(); - } - return StringUtils.EMPTY; + return ObjectUtils.notNullGetter(retConfig, SysConfig::getConfigValue, StringUtils.EMPTY); } /** @@ -173,7 +171,7 @@ public class SysConfigServiceImpl implements ISysConfigService, ConfigService { public void deleteConfigByIds(Long[] configIds) { for (Long configId : configIds) { SysConfig config = baseMapper.selectById(configId); - if (StringUtils.equals(UserConstants.YES, config.getConfigType())) { + if (StringUtils.equals(SystemConstants.YES, config.getConfigType())) { throw new ServiceException(String.format("内置参数【%1$s】不能删除 ", config.getConfigKey())); } CacheUtils.evict(CacheNames.SYS_CONFIG, config.getConfigKey()); @@ -197,7 +195,7 @@ public class SysConfigServiceImpl implements ISysConfigService, ConfigService { */ @Override public boolean checkConfigKeyUnique(SysConfigBo config) { - long configId = ObjectUtil.isNull(config.getConfigId()) ? -1L : config.getConfigId(); + long configId = ObjectUtils.notNull(config.getConfigId(), -1L); SysConfig info = baseMapper.selectOne(new LambdaQueryWrapper().eq(SysConfig::getConfigKey, config.getConfigKey())); if (ObjectUtil.isNotNull(info) && info.getConfigId() != configId) { return false; diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDataScopeServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDataScopeServiceImpl.java index 018f9a07a..12a507203 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDataScopeServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDataScopeServiceImpl.java @@ -5,13 +5,14 @@ import cn.hutool.core.convert.Convert; import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import lombok.RequiredArgsConstructor; +import org.dromara.common.core.constant.CacheNames; import org.dromara.common.core.utils.StreamUtils; -import org.dromara.common.mybatis.helper.DataBaseHelper; import org.dromara.system.domain.SysDept; import org.dromara.system.domain.SysRoleDept; import org.dromara.system.mapper.SysDeptMapper; import org.dromara.system.mapper.SysRoleDeptMapper; import org.dromara.system.service.ISysDataScopeService; +import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import java.util.List; @@ -37,6 +38,7 @@ public class SysDataScopeServiceImpl implements ISysDataScopeService { * @param roleId 角色Id * @return 部门Id组 */ + @Cacheable(cacheNames = CacheNames.SYS_ROLE_CUSTOM, key = "#roleId", condition = "#roleId != null") @Override public String getRoleCustom(Long roleId) { if (ObjectUtil.isNull(roleId)) { @@ -58,14 +60,13 @@ public class SysDataScopeServiceImpl implements ISysDataScopeService { * @param deptId 部门Id * @return 部门Id组 */ + @Cacheable(cacheNames = CacheNames.SYS_DEPT_AND_CHILD, key = "#deptId", condition = "#deptId != null") @Override public String getDeptAndChild(Long deptId) { if (ObjectUtil.isNull(deptId)) { return "-1"; } - List deptList = deptMapper.selectList(new LambdaQueryWrapper() - .select(SysDept::getDeptId) - .apply(DataBaseHelper.findInSet(deptId, "ancestors"))); + List deptList = deptMapper.selectListByParentId(deptId); List ids = StreamUtils.toList(deptList, SysDept::getDeptId); ids.add(deptId); if (CollUtil.isNotEmpty(ids)) { diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDeptServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDeptServiceImpl.java index 49b18b7ab..ca062bee6 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDeptServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDeptServiceImpl.java @@ -1,5 +1,6 @@ package org.dromara.system.service.impl; +import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.convert.Convert; import cn.hutool.core.lang.tree.Tree; @@ -9,13 +10,11 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import lombok.RequiredArgsConstructor; import org.dromara.common.core.constant.CacheNames; -import org.dromara.common.core.constant.UserConstants; +import org.dromara.common.core.constant.SystemConstants; +import org.dromara.common.core.domain.dto.DeptDTO; import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.service.DeptService; -import org.dromara.common.core.utils.MapstructUtils; -import org.dromara.common.core.utils.SpringUtils; -import org.dromara.common.core.utils.StringUtils; -import org.dromara.common.core.utils.TreeBuildUtils; +import org.dromara.common.core.utils.*; import org.dromara.common.mybatis.helper.DataBaseHelper; import org.dromara.common.redis.utils.CacheUtils; import org.dromara.common.satoken.utils.LoginHelper; @@ -30,7 +29,9 @@ import org.dromara.system.mapper.SysUserMapper; import org.dromara.system.service.ISysDeptService; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.Cacheable; +import org.springframework.cache.annotation.Caching; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import java.util.ArrayList; import java.util.Arrays; @@ -69,8 +70,6 @@ public class SysDeptServiceImpl implements ISysDeptService, DeptService { */ @Override public List> selectDeptTreeList(SysDeptBo bo) { - // 只查询未禁用部门 - bo.setStatus(UserConstants.DEPT_NORMAL); LambdaQueryWrapper lqw = buildQueryWrapper(bo); List depts = baseMapper.selectDeptList(lqw); return buildDeptTreeSelect(depts); @@ -78,7 +77,7 @@ public class SysDeptServiceImpl implements ISysDeptService, DeptService { private LambdaQueryWrapper buildQueryWrapper(SysDeptBo bo) { LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); - lqw.eq(SysDept::getDelFlag, UserConstants.DEL_FLAG_NORMAL); + lqw.eq(SysDept::getDelFlag, SystemConstants.NORMAL); lqw.eq(ObjectUtil.isNotNull(bo.getDeptId()), SysDept::getDeptId, bo.getDeptId()); lqw.eq(ObjectUtil.isNotNull(bo.getParentId()), SysDept::getParentId, bo.getParentId()); lqw.like(StringUtils.isNotBlank(bo.getDeptName()), SysDept::getDeptName, bo.getDeptName()); @@ -102,11 +101,23 @@ public class SysDeptServiceImpl implements ISysDeptService, DeptService { if (CollUtil.isEmpty(depts)) { return CollUtil.newArrayList(); } - return TreeBuildUtils.build(depts, (dept, tree) -> - tree.setId(dept.getDeptId()) - .setParentId(dept.getParentId()) - .setName(dept.getDeptName()) - .setWeight(dept.getOrderNum())); + // 获取当前列表中每一个节点的parentId,然后在列表中查找是否有id与其parentId对应,若无对应,则表明此时节点列表中,该节点在当前列表中属于顶级节点 + List> treeList = CollUtil.newArrayList(); + for (SysDeptVo d : depts) { + Long parentId = d.getParentId(); + SysDeptVo sysDeptVo = StreamUtils.findFirst(depts, it -> it.getDeptId().longValue() == parentId); + if (ObjectUtil.isNull(sysDeptVo)) { + List> trees = TreeBuildUtils.build(depts, parentId, (dept, tree) -> + tree.setId(dept.getDeptId()) + .setParentId(dept.getParentId()) + .setName(dept.getDeptName()) + .setWeight(dept.getOrderNum()) + .putExtra("disabled", SystemConstants.DISABLE.equals(dept.getStatus()))); + Tree tree = StreamUtils.findFirst(trees, it -> it.getId().longValue() == d.getDeptId()); + treeList.add(tree); + } + } + return treeList; } /** @@ -136,7 +147,7 @@ public class SysDeptServiceImpl implements ISysDeptService, DeptService { } SysDeptVo parentDept = baseMapper.selectVoOne(new LambdaQueryWrapper() .select(SysDept::getDeptName).eq(SysDept::getDeptId, dept.getParentId())); - dept.setParentName(ObjectUtil.isNotNull(parentDept) ? parentDept.getDeptName() : null); + dept.setParentName(ObjectUtils.notNullGetter(parentDept, SysDeptVo::getDeptName)); return dept; } @@ -144,7 +155,7 @@ public class SysDeptServiceImpl implements ISysDeptService, DeptService { public List selectDeptByIds(List deptIds) { return baseMapper.selectDeptList(new LambdaQueryWrapper() .select(SysDept::getDeptId, SysDept::getDeptName, SysDept::getLeader) - .eq(SysDept::getStatus, UserConstants.DEPT_NORMAL) + .eq(SysDept::getStatus, SystemConstants.NORMAL) .in(CollUtil.isNotEmpty(deptIds), SysDept::getDeptId, deptIds)); } @@ -166,6 +177,31 @@ public class SysDeptServiceImpl implements ISysDeptService, DeptService { return String.join(StringUtils.SEPARATOR, list); } + /** + * 根据部门ID查询部门负责人 + * + * @param deptId 部门ID,用于指定需要查询的部门 + * @return 返回该部门的负责人ID + */ + @Override + public Long selectDeptLeaderById(Long deptId) { + SysDeptVo vo = SpringUtils.getAopProxy(this).selectDeptById(deptId); + return vo.getLeader(); + } + + /** + * 查询部门 + * + * @return 部门列表 + */ + @Override + public List selectDeptsByList() { + List list = baseMapper.selectDeptList(new LambdaQueryWrapper() + .select(SysDept::getDeptId, SysDept::getDeptName, SysDept::getParentId) + .eq(SysDept::getStatus, SystemConstants.NORMAL)); + return BeanUtil.copyToList(list, DeptDTO.class); + } + /** * 根据ID查询所有子部门数(正常状态) * @@ -175,7 +211,7 @@ public class SysDeptServiceImpl implements ISysDeptService, DeptService { @Override public long selectNormalChildrenDeptById(Long deptId) { return baseMapper.selectCount(new LambdaQueryWrapper() - .eq(SysDept::getStatus, UserConstants.DEPT_NORMAL) + .eq(SysDept::getStatus, SystemConstants.NORMAL) .apply(DataBaseHelper.findInSet(deptId, "ancestors"))); } @@ -242,11 +278,12 @@ public class SysDeptServiceImpl implements ISysDeptService, DeptService { * @param bo 部门信息 * @return 结果 */ + @CacheEvict(cacheNames = CacheNames.SYS_DEPT_AND_CHILD, allEntries = true) @Override public int insertDept(SysDeptBo bo) { SysDept info = baseMapper.selectById(bo.getParentId()); // 如果父节点不为正常状态,则不允许新增子节点 - if (!UserConstants.DEPT_NORMAL.equals(info.getStatus())) { + if (!SystemConstants.NORMAL.equals(info.getStatus())) { throw new ServiceException("部门停用,不允许新增"); } SysDept dept = MapstructUtils.convert(bo, SysDept.class); @@ -260,16 +297,23 @@ public class SysDeptServiceImpl implements ISysDeptService, DeptService { * @param bo 部门信息 * @return 结果 */ - @CacheEvict(cacheNames = CacheNames.SYS_DEPT, key = "#bo.deptId") + @Caching(evict = { + @CacheEvict(cacheNames = CacheNames.SYS_DEPT, key = "#bo.deptId"), + @CacheEvict(cacheNames = CacheNames.SYS_DEPT_AND_CHILD, allEntries = true) + }) @Override + @Transactional(rollbackFor = Exception.class) public int updateDept(SysDeptBo bo) { SysDept dept = MapstructUtils.convert(bo, SysDept.class); SysDept oldDept = baseMapper.selectById(dept.getDeptId()); + if (ObjectUtil.isNull(oldDept)) { + throw new ServiceException("部门不存在,无法修改"); + } if (!oldDept.getParentId().equals(dept.getParentId())) { // 如果是新父部门 则校验是否具有新父部门权限 避免越权 this.checkDeptDataScope(dept.getParentId()); SysDept newParentDept = baseMapper.selectById(dept.getParentId()); - if (ObjectUtil.isNotNull(newParentDept) && ObjectUtil.isNotNull(oldDept)) { + if (ObjectUtil.isNotNull(newParentDept)) { String newAncestors = newParentDept.getAncestors() + StringUtils.SEPARATOR + newParentDept.getDeptId(); String oldAncestors = oldDept.getAncestors(); dept.setAncestors(newAncestors); @@ -279,8 +323,8 @@ public class SysDeptServiceImpl implements ISysDeptService, DeptService { dept.setAncestors(oldDept.getAncestors()); } int result = baseMapper.updateById(dept); - if (UserConstants.DEPT_NORMAL.equals(dept.getStatus()) && StringUtils.isNotEmpty(dept.getAncestors()) - && !StringUtils.equals(UserConstants.DEPT_NORMAL, dept.getAncestors())) { + if (SystemConstants.NORMAL.equals(dept.getStatus()) && StringUtils.isNotEmpty(dept.getAncestors()) + && !StringUtils.equals(SystemConstants.NORMAL, dept.getAncestors())) { // 如果该部门是启用状态,则启用该部门的所有上级部门 updateParentDeptStatusNormal(dept); } @@ -296,7 +340,7 @@ public class SysDeptServiceImpl implements ISysDeptService, DeptService { String ancestors = dept.getAncestors(); Long[] deptIds = Convert.toLongArray(ancestors); baseMapper.update(null, new LambdaUpdateWrapper() - .set(SysDept::getStatus, UserConstants.DEPT_NORMAL) + .set(SysDept::getStatus, SystemConstants.NORMAL) .in(SysDept::getDeptId, Arrays.asList(deptIds))); } @@ -330,7 +374,10 @@ public class SysDeptServiceImpl implements ISysDeptService, DeptService { * @param deptId 部门ID * @return 结果 */ - @CacheEvict(cacheNames = CacheNames.SYS_DEPT, key = "#deptId") + @Caching(evict = { + @CacheEvict(cacheNames = CacheNames.SYS_DEPT, key = "#deptId"), + @CacheEvict(cacheNames = CacheNames.SYS_DEPT_AND_CHILD, key = "#deptId") + }) @Override public int deleteDeptById(Long deptId) { return baseMapper.deleteById(deptId); diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDictDataServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDictDataServiceImpl.java index 1ab0fafd1..e44fdbc29 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDictDataServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDictDataServiceImpl.java @@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import org.dromara.common.core.constant.CacheNames; import org.dromara.common.core.utils.MapstructUtils; +import org.dromara.common.core.utils.ObjectUtils; import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.system.domain.SysDictData; import org.dromara.common.mybatis.core.page.TableDataInfo; @@ -144,7 +145,7 @@ public class SysDictDataServiceImpl implements ISysDictDataService { */ @Override public boolean checkDictDataUnique(SysDictDataBo dict) { - Long dictCode = ObjectUtil.isNull(dict.getDictCode()) ? -1L : dict.getDictCode(); + Long dictCode = ObjectUtils.notNull(dict.getDictCode(), -1L); SysDictData entity = baseMapper.selectOne(new LambdaQueryWrapper() .eq(SysDictData::getDictType, dict.getDictType()).eq(SysDictData::getDictValue, dict.getDictValue())); if (ObjectUtil.isNotNull(entity) && !dictCode.equals(entity.getDictCode())) { diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysLogininforServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysLogininforServiceImpl.java index b95baf44b..72b497eca 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysLogininforServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysLogininforServiceImpl.java @@ -118,8 +118,7 @@ public class SysLogininforServiceImpl implements ISysLogininforService { .between(params.get("beginTime") != null && params.get("endTime") != null, SysLogininfor::getLoginTime, params.get("beginTime"), params.get("endTime")); if (StringUtils.isBlank(pageQuery.getOrderByColumn())) { - pageQuery.setOrderByColumn("info_id"); - pageQuery.setIsAsc("desc"); + lqw.orderByDesc(SysLogininfor::getInfoId); } Page page = baseMapper.selectVoPage(pageQuery.build(), lqw); return TableDataInfo.build(page); diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysMenuServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysMenuServiceImpl.java index af844c9bd..40643e13d 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysMenuServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysMenuServiceImpl.java @@ -8,7 +8,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import lombok.RequiredArgsConstructor; -import org.dromara.common.core.constant.UserConstants; +import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.core.utils.MapstructUtils; import org.dromara.common.core.utils.StreamUtils; import org.dromara.common.core.utils.StringUtils; @@ -196,7 +196,7 @@ public class SysMenuServiceImpl implements ISysMenuService { router.setQuery(menu.getQueryParam()); router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath())); List cMenus = menu.getChildren(); - if (CollUtil.isNotEmpty(cMenus) && UserConstants.TYPE_DIR.equals(menu.getMenuType())) { + if (CollUtil.isNotEmpty(cMenus) && SystemConstants.TYPE_DIR.equals(menu.getMenuType())) { router.setAlwaysShow(true); router.setRedirect("noRedirect"); router.setChildren(buildMenus(cMenus)); @@ -220,7 +220,7 @@ public class SysMenuServiceImpl implements ISysMenuService { String routerPath = SysMenu.innerLinkReplaceEach(menu.getPath()); String innerLinkName = StringUtils.capitalize(routerPath) + menu.getMenuId(); children.setPath(routerPath); - children.setComponent(UserConstants.INNER_LINK); + children.setComponent(SystemConstants.INNER_LINK); children.setName(innerLinkName); children.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), menu.getPath())); childrenList.add(children); @@ -242,11 +242,14 @@ public class SysMenuServiceImpl implements ISysMenuService { if (CollUtil.isEmpty(menus)) { return CollUtil.newArrayList(); } - return TreeBuildUtils.build(menus, (menu, tree) -> - tree.setId(menu.getMenuId()) + return TreeBuildUtils.build(menus, (menu, tree) -> { + Tree menuTree = tree.setId(menu.getMenuId()) .setParentId(menu.getParentId()) .setName(menu.getMenuName()) - .setWeight(menu.getOrderNum())); + .setWeight(menu.getOrderNum()); + menuTree.put("menuType", menu.getMenuType()); + menuTree.put("icon", menu.getIcon()); + }); } /** diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysNoticeServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysNoticeServiceImpl.java index db63e61d0..19a3ff59a 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysNoticeServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysNoticeServiceImpl.java @@ -1,10 +1,10 @@ package org.dromara.system.service.impl; -import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import org.dromara.common.core.utils.MapstructUtils; +import org.dromara.common.core.utils.ObjectUtils; import org.dromara.common.core.utils.StringUtils; import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.TableDataInfo; @@ -70,7 +70,7 @@ public class SysNoticeServiceImpl implements ISysNoticeService { lqw.eq(StringUtils.isNotBlank(bo.getNoticeType()), SysNotice::getNoticeType, bo.getNoticeType()); if (StringUtils.isNotBlank(bo.getCreateByName())) { SysUserVo sysUser = userMapper.selectVoOne(new LambdaQueryWrapper().eq(SysUser::getUserName, bo.getCreateByName())); - lqw.eq(SysNotice::getCreateBy, ObjectUtil.isNotNull(sysUser) ? sysUser.getUserId() : null); + lqw.eq(SysNotice::getCreateBy, ObjectUtils.notNullGetter(sysUser, SysUserVo::getUserId)); } lqw.orderByAsc(SysNotice::getNoticeId); return lqw; diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOperLogServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOperLogServiceImpl.java index 750e455ac..27c2f32d5 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOperLogServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOperLogServiceImpl.java @@ -53,8 +53,7 @@ public class SysOperLogServiceImpl implements ISysOperLogService { public TableDataInfo selectPageOperLogList(SysOperLogBo operLog, PageQuery pageQuery) { LambdaQueryWrapper lqw = buildQueryWrapper(operLog); if (StringUtils.isBlank(pageQuery.getOrderByColumn())) { - pageQuery.setOrderByColumn("oper_id"); - pageQuery.setIsAsc("desc"); + lqw.orderByDesc(SysOperLog::getOperId); } Page page = baseMapper.selectVoPage(pageQuery.build(), lqw); return TableDataInfo.build(page); diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssConfigServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssConfigServiceImpl.java index a1eefcefd..a67b04ea9 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssConfigServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssConfigServiceImpl.java @@ -11,6 +11,7 @@ import lombok.extern.slf4j.Slf4j; import org.dromara.common.core.constant.CacheNames; import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.utils.MapstructUtils; +import org.dromara.common.core.utils.ObjectUtils; import org.dromara.common.core.utils.StringUtils; import org.dromara.common.json.utils.JsonUtils; import org.dromara.common.mybatis.core.page.PageQuery; @@ -147,7 +148,7 @@ public class SysOssConfigServiceImpl implements ISysOssConfigService { * 判断configKey是否唯一 */ private boolean checkConfigKeyUnique(SysOssConfig sysOssConfig) { - long ossConfigId = ObjectUtil.isNull(sysOssConfig.getOssConfigId()) ? -1L : sysOssConfig.getOssConfigId(); + long ossConfigId = ObjectUtils.notNull(sysOssConfig.getOssConfigId(), -1L); SysOssConfig info = baseMapper.selectOne(new LambdaQueryWrapper() .select(SysOssConfig::getOssConfigId, SysOssConfig::getConfigKey) .eq(SysOssConfig::getConfigKey, sysOssConfig.getConfigKey())); diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java index f58f06166..c2eb08c79 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java @@ -36,6 +36,7 @@ import org.springframework.web.multipart.MultipartFile; import java.io.File; import java.io.IOException; +import java.time.Duration; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -177,8 +178,7 @@ public class SysOssServiceImpl implements ISysOssService, OssService { FileUtils.setAttachmentResponseHeader(response, sysOss.getOriginalName()); response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE + "; charset=UTF-8"); OssClient storage = OssFactory.instance(sysOss.getService()); - long contentLength = storage.download(sysOss.getFileName(), response.getOutputStream()); - response.setContentLengthLong(contentLength); + storage.download(sysOss.getFileName(), response.getOutputStream(), response::setContentLengthLong); } /** @@ -262,7 +262,7 @@ public class SysOssServiceImpl implements ISysOssService, OssService { OssClient storage = OssFactory.instance(oss.getService()); // 仅修改桶类型为 private 的URL,临时URL时长为120s if (AccessPolicyType.PRIVATE == storage.getAccessPolicy()) { - oss.setUrl(storage.getPrivateUrl(oss.getFileName(), 120)); + oss.setUrl(storage.getPrivateUrl(oss.getFileName(), Duration.ofSeconds(120))); } return oss; } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysPostServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysPostServiceImpl.java index 2c38129ac..5888985a7 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysPostServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysPostServiceImpl.java @@ -6,14 +6,14 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import lombok.RequiredArgsConstructor; -import org.dromara.common.core.constant.UserConstants; +import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.core.exception.ServiceException; +import org.dromara.common.core.service.PostService; import org.dromara.common.core.utils.MapstructUtils; import org.dromara.common.core.utils.StreamUtils; import org.dromara.common.core.utils.StringUtils; import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.TableDataInfo; -import org.dromara.common.mybatis.helper.DataBaseHelper; import org.dromara.system.domain.SysDept; import org.dromara.system.domain.SysPost; import org.dromara.system.domain.SysUserPost; @@ -27,7 +27,6 @@ import org.springframework.stereotype.Service; import java.util.Arrays; import java.util.List; -import java.util.stream.Collectors; /** * 岗位信息 服务层处理 @@ -36,7 +35,7 @@ import java.util.stream.Collectors; */ @RequiredArgsConstructor @Service -public class SysPostServiceImpl implements ISysPostService { +public class SysPostServiceImpl implements ISysPostService, PostService { private final SysPostMapper baseMapper; private final SysDeptMapper deptMapper; @@ -59,6 +58,17 @@ public class SysPostServiceImpl implements ISysPostService { return baseMapper.selectVoList(buildQueryWrapper(post)); } + /** + * 查询用户所属岗位组 + * + * @param userId 用户ID + * @return 岗位ID + */ + @Override + public List selectPostsByUserId(Long userId) { + return baseMapper.selectPostsByUserId(userId); + } + /** * 根据查询条件构建查询包装器 * @@ -78,12 +88,8 @@ public class SysPostServiceImpl implements ISysPostService { } else if (ObjectUtil.isNotNull(bo.getBelongDeptId())) { //部门树搜索 wrapper.and(x -> { - List deptIds = deptMapper.selectList(new LambdaQueryWrapper() - .select(SysDept::getDeptId) - .apply(DataBaseHelper.findInSet(bo.getBelongDeptId(), "ancestors"))) - .stream() - .map(SysDept::getDeptId) - .collect(Collectors.toList()); + List deptList = deptMapper.selectListByParentId(bo.getBelongDeptId()); + List deptIds = StreamUtils.toList(deptList, SysDept::getDeptId); deptIds.add(bo.getBelongDeptId()); x.in(SysPost::getDeptId, deptIds); }); @@ -134,7 +140,7 @@ public class SysPostServiceImpl implements ISysPostService { public List selectPostByIds(List postIds) { return baseMapper.selectVoList(new LambdaQueryWrapper() .select(SysPost::getPostId, SysPost::getPostName, SysPost::getPostCode) - .eq(SysPost::getStatus, UserConstants.POST_NORMAL) + .eq(SysPost::getStatus, SystemConstants.NORMAL) .in(CollUtil.isNotEmpty(postIds), SysPost::getPostId, postIds)); } @@ -239,4 +245,5 @@ public class SysPostServiceImpl implements ISysPostService { SysPost post = MapstructUtils.convert(bo, SysPost.class); return baseMapper.updateById(post); } + } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysRoleServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysRoleServiceImpl.java index 9b8b0ecbe..0a2e485f6 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysRoleServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysRoleServiceImpl.java @@ -12,10 +12,12 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import lombok.RequiredArgsConstructor; +import org.dromara.common.core.constant.CacheNames; +import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.core.constant.TenantConstants; -import org.dromara.common.core.constant.UserConstants; import org.dromara.common.core.domain.model.LoginUser; import org.dromara.common.core.exception.ServiceException; +import org.dromara.common.core.service.RoleService; import org.dromara.common.core.utils.MapstructUtils; import org.dromara.common.core.utils.StreamUtils; import org.dromara.common.core.utils.StringUtils; @@ -33,6 +35,7 @@ import org.dromara.system.mapper.SysRoleMapper; import org.dromara.system.mapper.SysRoleMenuMapper; import org.dromara.system.mapper.SysUserRoleMapper; import org.dromara.system.service.ISysRoleService; +import org.springframework.cache.annotation.CacheEvict; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -45,7 +48,7 @@ import java.util.*; */ @RequiredArgsConstructor @Service -public class SysRoleServiceImpl implements ISysRoleService { +public class SysRoleServiceImpl implements ISysRoleService, RoleService { private final SysRoleMapper baseMapper; private final SysRoleMenuMapper roleMenuMapper; @@ -72,7 +75,7 @@ public class SysRoleServiceImpl implements ISysRoleService { private Wrapper buildQueryWrapper(SysRoleBo bo) { Map params = bo.getParams(); QueryWrapper wrapper = Wrappers.query(); - wrapper.eq("r.del_flag", UserConstants.ROLE_NORMAL) + wrapper.eq("r.del_flag", SystemConstants.NORMAL) .eq(ObjectUtil.isNotNull(bo.getRoleId()), "r.role_id", bo.getRoleId()) .like(StringUtils.isNotBlank(bo.getRoleName()), "r.role_name", bo.getRoleName()) .eq(StringUtils.isNotBlank(bo.getStatus()), "r.status", bo.getStatus()) @@ -174,7 +177,7 @@ public class SysRoleServiceImpl implements ISysRoleService { @Override public List selectRoleByIds(List roleIds) { return baseMapper.selectRoleList(new QueryWrapper() - .eq("r.status", UserConstants.ROLE_NORMAL) + .eq("r.status", SystemConstants.NORMAL) .in(CollUtil.isNotEmpty(roleIds), "r.role_id", roleIds)); } @@ -294,7 +297,7 @@ public class SysRoleServiceImpl implements ISysRoleService { public int updateRole(SysRoleBo bo) { SysRole role = MapstructUtils.convert(bo, SysRole.class); - if (UserConstants.ROLE_DISABLE.equals(role.getStatus()) && this.countUserRoleByRoleId(role.getRoleId()) > 0) { + if (SystemConstants.DISABLE.equals(role.getStatus()) && this.countUserRoleByRoleId(role.getRoleId()) > 0) { throw new ServiceException("角色已分配,不能禁用!"); } // 修改角色信息 @@ -313,7 +316,7 @@ public class SysRoleServiceImpl implements ISysRoleService { */ @Override public int updateRoleStatus(Long roleId, String status) { - if (UserConstants.ROLE_DISABLE.equals(status) && this.countUserRoleByRoleId(roleId) > 0) { + if (SystemConstants.DISABLE.equals(status) && this.countUserRoleByRoleId(roleId) > 0) { throw new ServiceException("角色已分配,不能禁用!"); } return baseMapper.update(null, @@ -328,6 +331,7 @@ public class SysRoleServiceImpl implements ISysRoleService { * @param bo 角色信息 * @return 结果 */ + @CacheEvict(cacheNames = CacheNames.SYS_ROLE_CUSTOM, key = "#bo.roleId") @Override @Transactional(rollbackFor = Exception.class) public int authDataScope(SysRoleBo bo) { @@ -348,7 +352,7 @@ public class SysRoleServiceImpl implements ISysRoleService { private int insertRoleMenu(SysRoleBo role) { int rows = 1; // 新增用户与角色管理 - List list = new ArrayList(); + List list = new ArrayList<>(); for (Long menuId : role.getMenuIds()) { SysRoleMenu rm = new SysRoleMenu(); rm.setRoleId(role.getRoleId()); @@ -369,7 +373,7 @@ public class SysRoleServiceImpl implements ISysRoleService { private int insertRoleDept(SysRoleBo role) { int rows = 1; // 新增角色与部门(数据权限)管理 - List list = new ArrayList(); + List list = new ArrayList<>(); for (Long deptId : role.getDeptIds()) { SysRoleDept rd = new SysRoleDept(); rd.setRoleId(role.getRoleId()); @@ -388,6 +392,7 @@ public class SysRoleServiceImpl implements ISysRoleService { * @param roleId 角色ID * @return 结果 */ + @CacheEvict(cacheNames = CacheNames.SYS_ROLE_CUSTOM, key = "#roleId") @Override @Transactional(rollbackFor = Exception.class) public int deleteRoleById(Long roleId) { @@ -404,6 +409,7 @@ public class SysRoleServiceImpl implements ISysRoleService { * @param roleIds 需要删除的角色ID * @return 结果 */ + @CacheEvict(cacheNames = CacheNames.SYS_ROLE_CUSTOM, allEntries = true) @Override @Transactional(rollbackFor = Exception.class) public int deleteRoleByIds(Long[] roleIds) { @@ -435,7 +441,7 @@ public class SysRoleServiceImpl implements ISysRoleService { .eq(SysUserRole::getRoleId, userRole.getRoleId()) .eq(SysUserRole::getUserId, userRole.getUserId())); if (rows > 0) { - cleanOnlineUserByRole(userRole.getRoleId()); + cleanOnlineUser(List.of(userRole.getUserId())); } return rows; } @@ -449,11 +455,12 @@ public class SysRoleServiceImpl implements ISysRoleService { */ @Override public int deleteAuthUsers(Long roleId, Long[] userIds) { + List ids = List.of(userIds); int rows = userRoleMapper.delete(new LambdaQueryWrapper() .eq(SysUserRole::getRoleId, roleId) - .in(SysUserRole::getUserId, Arrays.asList(userIds))); + .in(SysUserRole::getUserId, ids)); if (rows > 0) { - cleanOnlineUserByRole(roleId); + cleanOnlineUser(ids); } return rows; } @@ -469,7 +476,8 @@ public class SysRoleServiceImpl implements ISysRoleService { public int insertAuthUsers(Long roleId, Long[] userIds) { // 新增用户与角色管理 int rows = 1; - List list = StreamUtils.toList(List.of(userIds), userId -> { + List ids = List.of(userIds); + List list = StreamUtils.toList(ids, userId -> { SysUserRole ur = new SysUserRole(); ur.setUserId(userId); ur.setRoleId(roleId); @@ -479,7 +487,7 @@ public class SysRoleServiceImpl implements ISysRoleService { rows = userRoleMapper.insertBatch(list) ? list.size() : 0; } if (rows > 0) { - cleanOnlineUserByRole(roleId); + cleanOnlineUser(ids); } return rows; } @@ -503,6 +511,9 @@ public class SysRoleServiceImpl implements ISysRoleService { return; } LoginUser loginUser = LoginHelper.getLoginUser(token); + if (ObjectUtil.isNull(loginUser) || CollUtil.isEmpty(loginUser.getRoles())) { + return; + } if (loginUser.getRoles().stream().anyMatch(r -> r.getRoleId().equals(roleId))) { try { StpUtil.logoutByTokenValue(token); @@ -511,4 +522,31 @@ public class SysRoleServiceImpl implements ISysRoleService { } }); } + + @Override + public void cleanOnlineUser(List userIds) { + List keys = StpUtil.searchTokenValue("", 0, -1, false); + if (CollUtil.isEmpty(keys)) { + return; + } + // 角色关联的在线用户量过大会导致redis阻塞卡顿 谨慎操作 + keys.parallelStream().forEach(key -> { + String token = StringUtils.substringAfterLast(key, ":"); + // 如果已经过期则跳过 + if (StpUtil.stpLogic.getTokenActiveTimeoutByToken(token) < -1) { + return; + } + LoginUser loginUser = LoginHelper.getLoginUser(token); + if (ObjectUtil.isNull(loginUser)) { + return; + } + if (userIds.contains(loginUser.getUserId())) { + try { + StpUtil.logoutByTokenValue(token); + } catch (NotLoginException ignored) { + } + } + }); + } + } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysSensitiveServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysSensitiveServiceImpl.java index 5f4d121b1..8a0d45ef3 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysSensitiveServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysSensitiveServiceImpl.java @@ -1,7 +1,7 @@ package org.dromara.system.service.impl; import cn.dev33.satoken.stp.StpUtil; -import org.dromara.common.core.utils.StringUtils; +import cn.hutool.core.util.ArrayUtil; import org.dromara.common.satoken.utils.LoginHelper; import org.dromara.common.sensitive.core.SensitiveService; import org.dromara.common.tenant.helper.TenantHelper; @@ -22,19 +22,19 @@ public class SysSensitiveServiceImpl implements SensitiveService { * 是否脱敏 */ @Override - public boolean isSensitive(String roleKey, String perms) { + public boolean isSensitive(String[] roleKey, String[] perms) { if (!LoginHelper.isLogin()) { return true; } - boolean roleExist = StringUtils.isNotBlank(roleKey); - boolean permsExist = StringUtils.isNotBlank(perms); + boolean roleExist = ArrayUtil.isNotEmpty(roleKey); + boolean permsExist = ArrayUtil.isNotEmpty(perms); if (roleExist && permsExist) { - if (StpUtil.hasRole(roleKey) && StpUtil.hasPermission(perms)) { + if (StpUtil.hasRoleOr(roleKey) && StpUtil.hasPermissionOr(perms)) { return false; } - } else if (roleExist && StpUtil.hasRole(roleKey)) { + } else if (roleExist && StpUtil.hasRoleOr(roleKey)) { return false; - } else if (permsExist && StpUtil.hasPermission(perms)) { + } else if (permsExist && StpUtil.hasPermissionOr(perms)) { return false; } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTaskAssigneeServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTaskAssigneeServiceImpl.java new file mode 100644 index 000000000..23dd0520c --- /dev/null +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTaskAssigneeServiceImpl.java @@ -0,0 +1,168 @@ +package org.dromara.system.service.impl; + +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 lombok.RequiredArgsConstructor; +import org.dromara.common.core.constant.SystemConstants; +import org.dromara.common.core.domain.dto.TaskAssigneeDTO; +import org.dromara.common.core.domain.model.TaskAssigneeBody; +import org.dromara.common.core.service.TaskAssigneeService; +import org.dromara.common.core.utils.StreamUtils; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.mybatis.core.page.PageQuery; +import org.dromara.system.domain.SysDept; +import org.dromara.system.domain.SysPost; +import org.dromara.system.domain.SysRole; +import org.dromara.system.domain.SysUser; +import org.dromara.system.domain.vo.SysDeptVo; +import org.dromara.system.domain.vo.SysPostVo; +import org.dromara.system.domain.vo.SysRoleVo; +import org.dromara.system.domain.vo.SysUserVo; +import org.dromara.system.mapper.SysDeptMapper; +import org.dromara.system.mapper.SysPostMapper; +import org.dromara.system.mapper.SysRoleMapper; +import org.dromara.system.mapper.SysUserMapper; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 工作流设计器获取任务执行人 + * + * @author Lion Li + */ +@RequiredArgsConstructor +@Service +public class SysTaskAssigneeServiceImpl implements TaskAssigneeService { + + private final SysPostMapper postMapper; + private final SysDeptMapper deptMapper; + private final SysUserMapper userMapper; + private final SysRoleMapper roleMapper; + + /** + * 查询角色并返回任务指派的列表,支持分页 + * + * @param taskQuery 查询条件 + * @return 办理人 + */ + @Override + public TaskAssigneeDTO selectRolesByTaskAssigneeList(TaskAssigneeBody taskQuery) { + PageQuery pageQuery = new PageQuery(taskQuery.getPageSize(), taskQuery.getPageNum()); + QueryWrapper wrapper = Wrappers.query(); + wrapper.eq("r.del_flag", SystemConstants.NORMAL) + .like(StringUtils.isNotBlank(taskQuery.getHandlerCode()), "r.role_name", taskQuery.getHandlerCode()) + .like(StringUtils.isNotBlank(taskQuery.getHandlerName()), "r.role_key", taskQuery.getHandlerName()) + .between(StringUtils.isNotBlank(taskQuery.getBeginTime()) && StringUtils.isNotBlank(taskQuery.getEndTime()), + "r.create_time", taskQuery.getBeginTime(), taskQuery.getEndTime()) + .orderByAsc("r.role_sort").orderByAsc("r.create_time"); + Page page = roleMapper.selectPageRoleList(pageQuery.build(), wrapper); + // 使用封装的字段映射方法进行转换 + List handlers = TaskAssigneeDTO.convertToHandlerList(page.getRecords(), + SysRoleVo::getRoleId, SysRoleVo::getRoleKey, SysRoleVo::getRoleName, null, SysRoleVo::getCreateTime); + return new TaskAssigneeDTO(page.getTotal(), handlers); + } + + /** + * 查询岗位并返回任务指派的列表,支持分页 + * + * @param taskQuery 查询条件 + * @return 办理人 + */ + @Override + public TaskAssigneeDTO selectPostsByTaskAssigneeList(TaskAssigneeBody taskQuery) { + PageQuery pageQuery = new PageQuery(taskQuery.getPageSize(), taskQuery.getPageNum()); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery() + .like(StringUtils.isNotBlank(taskQuery.getHandlerCode()), SysPost::getPostCategory, taskQuery.getHandlerCode()) + .like(StringUtils.isNotBlank(taskQuery.getHandlerName()), SysPost::getPostName, taskQuery.getHandlerName()) + .between(StringUtils.isNotBlank(taskQuery.getBeginTime()) && StringUtils.isNotBlank(taskQuery.getEndTime()), + SysPost::getCreateTime, taskQuery.getBeginTime(), taskQuery.getEndTime()); + if (StringUtils.isNotBlank(taskQuery.getGroupId())) { + Long belongDeptId = Long.valueOf(taskQuery.getGroupId()); + wrapper.and(x -> { + List deptList = deptMapper.selectListByParentId(belongDeptId); + List deptIds = StreamUtils.toList(deptList, SysDept::getDeptId); + deptIds.add(belongDeptId); + x.in(SysPost::getDeptId, deptIds); + }); + } + Page page = postMapper.selectPagePostList(pageQuery.build(), wrapper); + // 使用封装的字段映射方法进行转换 + List handlers = TaskAssigneeDTO.convertToHandlerList(page.getRecords(), + SysPostVo::getPostId, SysPostVo::getPostCategory, SysPostVo::getPostName, SysPostVo::getDeptId, SysPostVo::getCreateTime); + return new TaskAssigneeDTO(page.getTotal(), handlers); + } + + /** + * 查询部门并返回任务指派的列表,支持分页 + * + * @param taskQuery 查询条件 + * @return 办理人 + */ + @Override + public TaskAssigneeDTO selectDeptsByTaskAssigneeList(TaskAssigneeBody taskQuery) { + PageQuery pageQuery = new PageQuery(taskQuery.getPageSize(), taskQuery.getPageNum()); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery() + .eq(SysDept::getDelFlag, SystemConstants.NORMAL) + .like(StringUtils.isNotBlank(taskQuery.getHandlerCode()), SysDept::getDeptCategory, taskQuery.getHandlerCode()) + .like(StringUtils.isNotBlank(taskQuery.getHandlerName()), SysDept::getDeptName, taskQuery.getHandlerName()) + .between(StringUtils.isNotBlank(taskQuery.getBeginTime()) && StringUtils.isNotBlank(taskQuery.getEndTime()), + SysDept::getCreateTime, taskQuery.getBeginTime(), taskQuery.getEndTime()) + .orderByAsc(SysDept::getAncestors) + .orderByAsc(SysDept::getParentId) + .orderByAsc(SysDept::getOrderNum) + .orderByAsc(SysDept::getDeptId); + if (StringUtils.isNotBlank(taskQuery.getGroupId())) { + //部门树搜索 + wrapper.and(x -> { + Long parentId = Long.valueOf(taskQuery.getGroupId()); + List deptList = deptMapper.selectListByParentId(parentId); + List deptIds = StreamUtils.toList(deptList, SysDept::getDeptId); + deptIds.add(parentId); + x.in(SysDept::getDeptId, deptIds); + }); + } + Page page = deptMapper.selectPageDeptList(pageQuery.build(), wrapper); + // 使用封装的字段映射方法进行转换 + List handlers = TaskAssigneeDTO.convertToHandlerList(page.getRecords(), + SysDeptVo::getDeptId, SysDeptVo::getDeptCategory, SysDeptVo::getDeptName, SysDeptVo::getParentId, SysDeptVo::getCreateTime); + return new TaskAssigneeDTO(page.getTotal(), handlers); + } + + + /** + * 查询用户并返回任务指派的列表,支持分页 + * + * @param taskQuery 查询条件 + * @return 办理人 + */ + @Override + public TaskAssigneeDTO selectUsersByTaskAssigneeList(TaskAssigneeBody taskQuery) { + PageQuery pageQuery = new PageQuery(taskQuery.getPageSize(), taskQuery.getPageNum()); + QueryWrapper wrapper = Wrappers.query(); + wrapper.eq("u.del_flag", SystemConstants.NORMAL) + .like(StringUtils.isNotBlank(taskQuery.getHandlerCode()), "u.user_name", taskQuery.getHandlerCode()) + .like(StringUtils.isNotBlank(taskQuery.getHandlerName()), "u.nick_name", taskQuery.getHandlerName()) + .between(taskQuery.getBeginTime() != null && taskQuery.getEndTime() != null, + "u.create_time", taskQuery.getBeginTime(), taskQuery.getEndTime()) + .orderByAsc("u.user_id"); + if (StringUtils.isNotBlank(taskQuery.getGroupId())) { + //部门树搜索 + wrapper.and(x -> { + Long parentId = Long.valueOf(taskQuery.getGroupId()); + List deptList = deptMapper.selectListByParentId(parentId); + List deptIds = StreamUtils.toList(deptList, SysDept::getDeptId); + deptIds.add(parentId); + x.in("u.dept_id", deptIds); + }); + } + Page page = userMapper.selectPageUserList(pageQuery.build(), wrapper); + // 使用封装的字段映射方法进行转换 + List handlers = TaskAssigneeDTO.convertToHandlerList(page.getRecords(), + SysUserVo::getUserId, SysUserVo::getUserName, SysUserVo::getNickName, SysUserVo::getDeptId, SysUserVo::getCreateTime); + return new TaskAssigneeDTO(page.getTotal(), handlers); + } + +} diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTenantPackageServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTenantPackageServiceImpl.java index d2a72f611..8d69e96ea 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTenantPackageServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTenantPackageServiceImpl.java @@ -6,7 +6,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import lombok.RequiredArgsConstructor; -import org.dromara.common.core.constant.TenantConstants; +import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.utils.MapstructUtils; import org.dromara.common.core.utils.StringUtils; @@ -59,7 +59,7 @@ public class SysTenantPackageServiceImpl implements ISysTenantPackageService { @Override public List selectList() { return baseMapper.selectVoList(new LambdaQueryWrapper() - .eq(SysTenantPackage::getStatus, TenantConstants.NORMAL)); + .eq(SysTenantPackage::getStatus, SystemConstants.NORMAL)); } /** diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTenantServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTenantServiceImpl.java index 747654982..f31bd3027 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTenantServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTenantServiceImpl.java @@ -12,8 +12,10 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import lombok.RequiredArgsConstructor; import org.dromara.common.core.constant.CacheNames; import org.dromara.common.core.constant.Constants; +import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.core.constant.TenantConstants; import org.dromara.common.core.exception.ServiceException; +import org.dromara.common.core.service.WorkflowService; import org.dromara.common.core.utils.MapstructUtils; import org.dromara.common.core.utils.SpringUtils; import org.dromara.common.core.utils.StreamUtils; @@ -120,7 +122,9 @@ public class SysTenantServiceImpl implements ISysTenantService { // 获取所有租户编号 List tenantIds = baseMapper.selectObjs( - new LambdaQueryWrapper().select(SysTenant::getTenantId), x -> {return Convert.toStr(x);}); + new LambdaQueryWrapper().select(SysTenant::getTenantId), x -> { + return Convert.toStr(x); + }); String tenantId = generateTenantId(tenantIds); add.setTenantId(tenantId); boolean flag = baseMapper.insert(add) > 0; @@ -190,6 +194,13 @@ public class SysTenantServiceImpl implements ISysTenantService { config.setTenantId(tenantId); } configMapper.insertBatch(sysConfigList); + + // 未开启工作流不执行下方操作 + if (SpringUtils.getProperty("warm-flow.enabled", Boolean.class, false)) { + WorkflowService workflowService = SpringUtils.getBean(WorkflowService.class); + // 新增租户流程定义 + workflowService.syncDef(tenantId); + } return true; } @@ -231,7 +242,7 @@ public class SysTenantServiceImpl implements ISysTenantService { role.setRoleName(TenantConstants.TENANT_ADMIN_ROLE_NAME); role.setRoleKey(TenantConstants.TENANT_ADMIN_ROLE_KEY); role.setRoleSort(1); - role.setStatus(TenantConstants.NORMAL); + role.setStatus(SystemConstants.NORMAL); roleMapper.insert(role); Long roleId = role.getRoleId(); @@ -398,7 +409,9 @@ public class SysTenantServiceImpl implements ISysTenantService { // 获取所有租户编号 List tenantIds = baseMapper.selectObjs( new LambdaQueryWrapper().select(SysTenant::getTenantId) - .eq(SysTenant::getStatus, TenantConstants.NORMAL), x -> {return Convert.toStr(x);}); + .eq(SysTenant::getStatus, SystemConstants.NORMAL), x -> { + return Convert.toStr(x); + }); List saveTypeList = new ArrayList<>(); List saveDataList = new ArrayList<>(); Set set = new HashSet<>(); diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysUserServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysUserServiceImpl.java index 8c6d1d5f5..40811707b 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysUserServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysUserServiceImpl.java @@ -14,17 +14,13 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.dromara.common.core.constant.CacheNames; -import org.dromara.common.core.constant.UserConstants; +import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.core.domain.dto.UserDTO; import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.service.UserService; -import org.dromara.common.core.utils.MapstructUtils; -import org.dromara.common.core.utils.SpringUtils; -import org.dromara.common.core.utils.StreamUtils; -import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.core.utils.*; import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.TableDataInfo; -import org.dromara.common.mybatis.helper.DataBaseHelper; import org.dromara.common.satoken.utils.LoginHelper; import org.dromara.system.domain.*; import org.dromara.system.domain.bo.SysUserBo; @@ -81,7 +77,7 @@ public class SysUserServiceImpl implements ISysUserService, UserService { private Wrapper buildQueryWrapper(SysUserBo user) { Map params = user.getParams(); QueryWrapper wrapper = Wrappers.query(); - wrapper.eq("u.del_flag", UserConstants.USER_NORMAL) + wrapper.eq("u.del_flag", SystemConstants.NORMAL) .eq(ObjectUtil.isNotNull(user.getUserId()), "u.user_id", user.getUserId()) .like(StringUtils.isNotBlank(user.getUserName()), "u.user_name", user.getUserName()) .eq(StringUtils.isNotBlank(user.getStatus()), "u.status", user.getStatus()) @@ -89,9 +85,7 @@ public class SysUserServiceImpl implements ISysUserService, UserService { .between(params.get("beginTime") != null && params.get("endTime") != null, "u.create_time", params.get("beginTime"), params.get("endTime")) .and(ObjectUtil.isNotNull(user.getDeptId()), w -> { - List deptList = deptMapper.selectList(new LambdaQueryWrapper() - .select(SysDept::getDeptId) - .apply(DataBaseHelper.findInSet(user.getDeptId(), "ancestors"))); + List deptList = deptMapper.selectListByParentId(user.getDeptId()); List ids = StreamUtils.toList(deptList, SysDept::getDeptId); ids.add(user.getDeptId()); w.in("u.dept_id", ids); @@ -111,7 +105,7 @@ public class SysUserServiceImpl implements ISysUserService, UserService { @Override public TableDataInfo selectAllocatedList(SysUserBo user, PageQuery pageQuery) { QueryWrapper wrapper = Wrappers.query(); - wrapper.eq("u.del_flag", UserConstants.USER_NORMAL) + wrapper.eq("u.del_flag", SystemConstants.NORMAL) .eq(ObjectUtil.isNotNull(user.getRoleId()), "r.role_id", user.getRoleId()) .like(StringUtils.isNotBlank(user.getUserName()), "u.user_name", user.getUserName()) .eq(StringUtils.isNotBlank(user.getStatus()), "u.status", user.getStatus()) @@ -131,7 +125,7 @@ public class SysUserServiceImpl implements ISysUserService, UserService { public TableDataInfo selectUnallocatedList(SysUserBo user, PageQuery pageQuery) { List userIds = userRoleMapper.selectUserIdsByRoleId(user.getRoleId()); QueryWrapper wrapper = Wrappers.query(); - wrapper.eq("u.del_flag", UserConstants.USER_NORMAL) + wrapper.eq("u.del_flag", SystemConstants.NORMAL) .and(w -> w.ne("r.role_id", user.getRoleId()).or().isNull("r.role_id")) .notIn(CollUtil.isNotEmpty(userIds), "u.user_id", userIds) .like(StringUtils.isNotBlank(user.getUserName()), "u.user_name", user.getUserName()) @@ -190,7 +184,7 @@ public class SysUserServiceImpl implements ISysUserService, UserService { public List selectUserByIds(List userIds, Long deptId) { return baseMapper.selectUserList(new LambdaQueryWrapper() .select(SysUser::getUserId, SysUser::getUserName, SysUser::getNickName) - .eq(SysUser::getStatus, UserConstants.USER_NORMAL) + .eq(SysUser::getStatus, SystemConstants.NORMAL) .eq(ObjectUtil.isNotNull(deptId), SysUser::getDeptId, deptId) .in(CollUtil.isNotEmpty(userIds), SysUser::getUserId, userIds)); } @@ -473,7 +467,7 @@ public class SysUserServiceImpl implements ISysUserService, UserService { if (ArrayUtil.isNotEmpty(roleIds)) { List roleList = new ArrayList<>(List.of(roleIds)); if (!LoginHelper.isSuperAdmin(userId)) { - roleList.remove(UserConstants.SUPER_ADMIN_ID); + roleList.remove(SystemConstants.SUPER_ADMIN_ID); } // 判断是否具有此角色的操作权限 List roles = roleMapper.selectRoleList( @@ -568,7 +562,7 @@ public class SysUserServiceImpl implements ISysUserService, UserService { public String selectUserNameById(Long userId) { SysUser sysUser = baseMapper.selectOne(new LambdaQueryWrapper() .select(SysUser::getUserName).eq(SysUser::getUserId, userId)); - return ObjectUtil.isNull(sysUser) ? null : sysUser.getUserName(); + return ObjectUtils.notNullGetter(sysUser, SysUser::getUserName); } /** @@ -582,7 +576,7 @@ public class SysUserServiceImpl implements ISysUserService, UserService { public String selectNicknameById(Long userId) { SysUser sysUser = baseMapper.selectOne(new LambdaQueryWrapper() .select(SysUser::getNickName).eq(SysUser::getUserId, userId)); - return ObjectUtil.isNull(sysUser) ? null : sysUser.getNickName(); + return ObjectUtils.notNullGetter(sysUser, SysUser::getNickName); } /** @@ -613,7 +607,7 @@ public class SysUserServiceImpl implements ISysUserService, UserService { public String selectPhonenumberById(Long userId) { SysUser sysUser = baseMapper.selectOne(new LambdaQueryWrapper() .select(SysUser::getPhonenumber).eq(SysUser::getUserId, userId)); - return ObjectUtil.isNull(sysUser) ? null : sysUser.getPhonenumber(); + return ObjectUtils.notNullGetter(sysUser, SysUser::getPhonenumber); } /** @@ -626,7 +620,7 @@ public class SysUserServiceImpl implements ISysUserService, UserService { public String selectEmailById(Long userId) { SysUser sysUser = baseMapper.selectOne(new LambdaQueryWrapper() .select(SysUser::getEmail).eq(SysUser::getUserId, userId)); - return ObjectUtil.isNull(sysUser) ? null : sysUser.getEmail(); + return ObjectUtils.notNullGetter(sysUser, SysUser::getEmail); } /** @@ -642,7 +636,7 @@ public class SysUserServiceImpl implements ISysUserService, UserService { } List list = baseMapper.selectVoList(new LambdaQueryWrapper() .select(SysUser::getUserId, SysUser::getUserName, SysUser::getNickName, SysUser::getEmail, SysUser::getPhonenumber) - .eq(SysUser::getStatus, UserConstants.USER_NORMAL) + .eq(SysUser::getStatus, SystemConstants.NORMAL) .in(SysUser::getUserId, userIds)); return BeanUtil.copyToList(list, UserDTO.class); } @@ -698,8 +692,31 @@ public class SysUserServiceImpl implements ISysUserService, UserService { } List list = baseMapper.selectVoList(new LambdaQueryWrapper() .select(SysUser::getUserId, SysUser::getUserName, SysUser::getNickName, SysUser::getEmail, SysUser::getPhonenumber) - .eq(SysUser::getStatus, UserConstants.USER_NORMAL) + .eq(SysUser::getStatus, SystemConstants.NORMAL) .in(SysUser::getDeptId, deptIds)); return BeanUtil.copyToList(list, UserDTO.class); } + + /** + * 通过岗位ID查询用户 + * + * @param postIds 岗位ids + * @return 用户 + */ + @Override + public List selectUsersByPostIds(List postIds) { + if (CollUtil.isEmpty(postIds)) { + return List.of(); + } + + // 通过岗位ID获取用户岗位信息 + List userPosts = userPostMapper.selectList( + new LambdaQueryWrapper().in(SysUserPost::getPostId, postIds)); + + // 获取用户ID列表 + Set userIds = StreamUtils.toSet(userPosts, SysUserPost::getUserId); + + return selectListByIds(new ArrayList<>(userIds)); + } + } diff --git a/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml b/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml index 6ad866f29..9057a0e22 100644 --- a/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml +++ b/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml @@ -18,6 +18,17 @@ from sys_dept ${ew.getCustomSqlSegment} + + diff --git a/ruoyi-modules/ruoyi-workflow/pom.xml b/ruoyi-modules/ruoyi-workflow/pom.xml index e55839ef7..d195fafa3 100644 --- a/ruoyi-modules/ruoyi-workflow/pom.xml +++ b/ruoyi-modules/ruoyi-workflow/pom.xml @@ -18,57 +18,14 @@ - - org.flowable - flowable-spring-boot-autoconfigure - - - org.flowable - flowable-spring-security - - - - - - org.flowable - flowable-spring-configurator - - - - org.flowable - flowable-spring-boot-starter-actuator - - - - - org.flowable - flowable-image-generator - - - - - org.flowable - flowable-json-converter - 6.8.0 - - - - - org.apache.xmlgraphics - batik-all - 1.17 - - - xalan - xalan - - + org.dromara + ruoyi-common-sse org.dromara - ruoyi-common-websocket + ruoyi-common-doc @@ -113,6 +70,14 @@ org.dromara ruoyi-common-security + + org.dromara.warm + warm-flow-mybatis-plus-sb3-starter + + + org.dromara.warm + warm-flow-plugin-ui-sb-web + diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/ConditionalOnEnable.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/ConditionalOnEnable.java new file mode 100644 index 000000000..5d24b3509 --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/ConditionalOnEnable.java @@ -0,0 +1,14 @@ +package org.dromara.workflow.common; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.TYPE, ElementType.METHOD }) +@ConditionalOnProperty(value = "warm-flow.enabled", havingValue = "true") +public @interface ConditionalOnEnable { +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/constant/FlowConstant.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/constant/FlowConstant.java index c3fcafa87..1b10eb8ea 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/constant/FlowConstant.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/constant/FlowConstant.java @@ -8,83 +8,6 @@ package org.dromara.workflow.common.constant; */ public interface FlowConstant { - String MESSAGE_CURRENT_TASK_IS_NULL = "当前任务不存在或你不是任务办理人!"; - - String MESSAGE_SUSPENDED = "当前任务已挂起不可审批!"; - - /** - * 连线 - */ - String SEQUENCE_FLOW = "sequenceFlow"; - - /** - * 并行网关 - */ - String PARALLEL_GATEWAY = "parallelGateway"; - - /** - * 排它网关 - */ - String EXCLUSIVE_GATEWAY = "exclusiveGateway"; - - /** - * 包含网关 - */ - String INCLUSIVE_GATEWAY = "inclusiveGateway"; - - /** - * 结束节点 - */ - String END_EVENT = "endEvent"; - - - /** - * 流程委派标识 - */ - String PENDING = "PENDING"; - - /** - * 候选人标识 - */ - String CANDIDATE = "candidate"; - - /** - * 会签任务总数 - */ - String NUMBER_OF_INSTANCES = "nrOfInstances"; - - /** - * 正在执行的会签总数 - */ - String NUMBER_OF_ACTIVE_INSTANCES = "nrOfActiveInstances"; - - /** - * 已完成的会签任务总数 - */ - String NUMBER_OF_COMPLETED_INSTANCES = "nrOfCompletedInstances"; - - /** - * 循环的索引值,可以使用elementIndexVariable属性修改loopCounter的变量名 - */ - String LOOP_COUNTER = "loopCounter"; - - String ZIP = "ZIP"; - - /** - * 业务与流程实例关联对象 - */ - String BUSINESS_INSTANCE_DTO = "businessInstanceDTO"; - - /** - * 流程定义配置 - */ - String WF_DEFINITION_CONFIG_VO = "wfDefinitionConfigVo"; - - /** - * 节点配置 - */ - String WF_NODE_CONFIG_VO = "wfNodeConfigVo"; - /** * 流程发起人 */ @@ -98,40 +21,46 @@ public interface FlowConstant { /** * 业务id */ - String BUSINESS_KEY = "businessKey"; + String BUSINESS_ID = "businessId"; /** - * 流程定义id + * 任务id */ - String PROCESS_DEFINITION_ID = "processDefinitionId"; + String TASK_ID = "taskId"; /** - * 开启跳过表达式变量 + * 委托 */ - String FLOWABLE_SKIP_EXPRESSION_ENABLED = "_FLOWABLE_SKIP_EXPRESSION_ENABLED"; + String DELEGATE_TASK = "delegateTask"; /** - * 模型标识key命名规范正则表达式 + * 转办 */ - String MODEL_KEY_PATTERN = "^[a-zA-Z][a-zA-Z0-9_]{0,254}$"; + String TRANSFER_TASK = "transferTask"; /** - * 用户任务 + * 加签 */ - String USER_TASK = "userTask"; + String ADD_SIGNATURE = "addSignature"; /** - * 会签 + * 减签 */ - String MULTI_INSTANCE = "multiInstance"; + String REDUCTION_SIGNATURE = "reductionSignature"; /** - * 是 + * 流程分类Id转名称 */ - String TRUE = "0"; + String CATEGORY_ID_TO_NAME = "category_id_to_name"; /** - * 否 + * 流程分类名称 */ - String FALSE = "1"; + String FLOW_CATEGORY_NAME = "flow_category_name#30d"; + + /** + * 默认租户OA申请分类id + */ + Long FLOW_CATEGORY_ID = 100L; + } diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/FormTypeEnum.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/FormTypeEnum.java deleted file mode 100644 index 083ab7b85..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/FormTypeEnum.java +++ /dev/null @@ -1,54 +0,0 @@ -package org.dromara.workflow.common.enums; - -import cn.hutool.core.util.StrUtil; -import lombok.AllArgsConstructor; -import lombok.Getter; -import org.apache.commons.lang3.StringUtils; - -import java.util.Arrays; - -/** - * 任务状态枚举 - * - * @author may - */ -@Getter -@AllArgsConstructor -public enum FormTypeEnum { - /** - * 自定义表单 - */ - STATIC("static", "自定义表单"), - /** - * 动态表单 - */ - DYNAMIC("dynamic", "动态表单"); - - /** - * 类型 - */ - private final String type; - - /** - * 描述 - */ - private final String desc; - - /** - * 表单类型 - * - * @param formType 表单类型 - */ - public static String findByType(String formType) { - if (StringUtils.isBlank(formType)) { - return StrUtil.EMPTY; - } - - return Arrays.stream(FormTypeEnum.values()) - .filter(statusEnum -> statusEnum.getType().equals(formType)) - .findFirst() - .map(FormTypeEnum::getDesc) - .orElse(StrUtil.EMPTY); - } -} - diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/MessageTypeEnum.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/MessageTypeEnum.java index a28295822..0fe5cfe90 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/MessageTypeEnum.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/MessageTypeEnum.java @@ -3,8 +3,10 @@ package org.dromara.workflow.common.enums; import lombok.AllArgsConstructor; import lombok.Getter; +import java.util.Arrays; import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Function; +import java.util.stream.Collectors; /** * 消息类型枚举 @@ -14,14 +16,17 @@ import java.util.concurrent.ConcurrentHashMap; @Getter @AllArgsConstructor public enum MessageTypeEnum { + /** * 站内信 */ SYSTEM_MESSAGE("1", "站内信"), + /** * 邮箱 */ EMAIL_MESSAGE("2", "邮箱"), + /** * 短信 */ @@ -31,21 +36,18 @@ public enum MessageTypeEnum { private final String desc; - private final static Map MESSAGE_TYPE_ENUM_MAP = new ConcurrentHashMap<>(MessageTypeEnum.values().length); - - static { - for (MessageTypeEnum messageType : MessageTypeEnum.values()) { - MESSAGE_TYPE_ENUM_MAP.put(messageType.code, messageType); - } - } + private static final Map MESSAGE_TYPE_ENUM_MAP = Arrays.stream(values()) + .collect(Collectors.toConcurrentMap(MessageTypeEnum::getCode, Function.identity())); /** * 根据消息类型 code 获取 MessageTypeEnum + * * @param code 消息类型code * @return MessageTypeEnum */ public static MessageTypeEnum getByCode(String code) { - return MESSAGE_TYPE_ENUM_MAP.get(code); + return MESSAGE_TYPE_ENUM_MAP.getOrDefault(code, null); } + } diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/TaskAssigneeEnum.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/TaskAssigneeEnum.java new file mode 100644 index 000000000..60be92fe9 --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/TaskAssigneeEnum.java @@ -0,0 +1,109 @@ +package org.dromara.workflow.common.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.dromara.common.core.exception.ServiceException; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 任务分配人枚举 + * + * @author AprilWind + */ +@Getter +@AllArgsConstructor +public enum TaskAssigneeEnum { + + /** + * 用户 + */ + USER("用户", ""), + + /** + * 角色 + */ + ROLE("角色", "role:"), + + /** + * 部门 + */ + DEPT("部门", "dept:"), + + /** + * 岗位 + */ + POST("岗位", "post:"); + + private final String desc; + private final String code; + + /** + * 根据描述获取对应的枚举类型 + *

+ * 通过传入描述,查找并返回匹配的枚举项。如果未找到匹配项,会抛出 {@link ServiceException}。 + *

+ * + * @param desc 描述,用于匹配对应的枚举项 + * @return TaskAssigneeEnum 返回对应的枚举类型 + * @throws ServiceException 如果未找到匹配的枚举项 + */ + public static TaskAssigneeEnum fromDesc(String desc) { + for (TaskAssigneeEnum type : values()) { + if (type.getDesc().equals(desc)) { + return type; + } + } + throw new ServiceException("未知的办理人类型: " + desc); + } + + /** + * 根据代码获取对应的枚举类型 + *

+ * 通过传入代码,查找并返回匹配的枚举项。如果未找到匹配项,会抛出 {@link ServiceException}。 + *

+ * + * @param code 代码,用于匹配对应的枚举项 + * @return TaskAssigneeEnum 返回对应的枚举类型 + * @throws IllegalArgumentException 如果未找到匹配的枚举项 + */ + public static TaskAssigneeEnum fromCode(String code) { + for (TaskAssigneeEnum type : values()) { + if (type.getCode().equals(code)) { + return type; + } + } + throw new ServiceException("未知的办理人类型代码: " + code); + } + + /** + * 获取所有办理人类型的描述列表 + *

+ * 获取当前枚举类所有项的描述字段列表,通常用于展示选择项。 + *

+ * + * @return List 返回所有办理人类型的描述列表 + */ + public static List getAssigneeTypeList() { + return Arrays.stream(values()) + .map(TaskAssigneeEnum::getDesc) + .collect(Collectors.toList()); + } + + /** + * 获取所有办理人类型的代码列表 + *

+ * 获取当前枚举类所有项的代码字段列表,通常用于程序内部逻辑的判断。 + *

+ * + * @return List 返回所有办理人类型的代码列表 + */ + public static List getAssigneeCodeList() { + return Arrays.stream(values()) + .map(TaskAssigneeEnum::getCode) + .collect(Collectors.toList()); + } +} + diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/TaskAssigneeType.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/TaskAssigneeType.java new file mode 100644 index 000000000..eed1b91fb --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/TaskAssigneeType.java @@ -0,0 +1,49 @@ +package org.dromara.workflow.common.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 人员类型 + * + * @author AprilWind + */ +@Getter +@AllArgsConstructor +public enum TaskAssigneeType { + + /** + * 待办任务的审批人权限 + *

该权限表示用户是待办任务的审批人,负责审核任务的执行情况。

+ */ + APPROVER("1", "待办任务的审批人权限"), + + /** + * 待办任务的转办人权限 + *

该权限表示用户是待办任务的转办人,负责将任务分配给其他人员。

+ */ + TRANSFER("2", "待办任务的转办人权限"), + + /** + * 待办任务的委托人权限 + *

该权限表示用户是待办任务的委托人,能够委托其他人代为处理任务。

+ */ + DELEGATE("3", "待办任务的委托人权限"), + + /** + * 待办任务的抄送人权限 + *

该权限表示用户是待办任务的抄送人,仅接收任务信息的通知,不参与任务的审批或处理。

+ */ + COPY("4", "待办任务的抄送人权限"); + + /** + * 类型 + */ + private final String code; + + /** + * 描述 + */ + private final String description; + +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/TaskStatusEnum.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/TaskStatusEnum.java index 7b2f55c20..d18ebb01d 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/TaskStatusEnum.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/TaskStatusEnum.java @@ -3,9 +3,10 @@ package org.dromara.workflow.common.enums; import cn.hutool.core.util.StrUtil; import lombok.AllArgsConstructor; import lombok.Getter; -import org.apache.commons.lang3.StringUtils; import java.util.Arrays; +import java.util.Map; +import java.util.stream.Collectors; /** * 任务状态枚举 @@ -15,50 +16,62 @@ import java.util.Arrays; @Getter @AllArgsConstructor public enum TaskStatusEnum { + /** * 撤销 */ CANCEL("cancel", "撤销"), + /** * 通过 */ PASS("pass", "通过"), + /** * 待审核 */ WAITING("waiting", "待审核"), + /** * 作废 */ INVALID("invalid", "作废"), + /** * 退回 */ BACK("back", "退回"), + /** * 终止 */ TERMINATION("termination", "终止"), + /** * 转办 */ TRANSFER("transfer", "转办"), + /** * 委托 */ - PENDING("pending", "委托"), + DEPUTE("depute", "委托"), + /** * 抄送 */ COPY("copy", "抄送"), + /** * 加签 */ SIGN("sign", "加签"), + /** * 减签 */ SIGN_OFF("sign_off", "减签"), + /** * 超时 */ @@ -74,21 +87,18 @@ public enum TaskStatusEnum { */ private final String desc; + private static final Map STATUS_DESC_MAP = Arrays.stream(values()) + .collect(Collectors.toConcurrentMap(TaskStatusEnum::getStatus, TaskStatusEnum::getDesc)); + /** * 任务业务状态 * * @param status 状态 */ public static String findByStatus(String status) { - if (StringUtils.isBlank(status)) { - return StrUtil.EMPTY; - } - - return Arrays.stream(TaskStatusEnum.values()) - .filter(statusEnum -> statusEnum.getStatus().equals(status)) - .findFirst() - .map(TaskStatusEnum::getDesc) - .orElse(StrUtil.EMPTY); + // 从缓存中直接获取描述 + return STATUS_DESC_MAP.getOrDefault(status, StrUtil.EMPTY); } + } diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/config/WarmFlowConfig.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/config/WarmFlowConfig.java new file mode 100644 index 000000000..08f1808d1 --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/config/WarmFlowConfig.java @@ -0,0 +1,16 @@ +package org.dromara.workflow.config; + +import org.dromara.workflow.common.ConditionalOnEnable; +import org.springframework.context.annotation.Configuration; + +/** + * warmFlow配置 + * + * @author may + */ +@ConditionalOnEnable +@Configuration +public class WarmFlowConfig { + +} + diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/ActModelController.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/ActModelController.java deleted file mode 100644 index 842d3d667..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/ActModelController.java +++ /dev/null @@ -1,148 +0,0 @@ -package org.dromara.workflow.controller; - -import jakarta.servlet.http.HttpServletResponse; -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotEmpty; -import lombok.RequiredArgsConstructor; -import org.dromara.common.core.domain.R; -import org.dromara.common.core.validate.AddGroup; -import org.dromara.common.core.validate.EditGroup; -import org.dromara.common.idempotent.annotation.RepeatSubmit; -import org.dromara.common.log.annotation.Log; -import org.dromara.common.log.enums.BusinessType; -import org.dromara.common.mybatis.core.page.PageQuery; -import org.dromara.common.mybatis.core.page.TableDataInfo; -import org.dromara.common.web.core.BaseController; -import org.dromara.workflow.domain.bo.ModelBo; -import org.dromara.workflow.domain.vo.ModelVo; -import org.dromara.workflow.service.IActModelService; -import org.flowable.engine.RepositoryService; -import org.flowable.engine.repository.Model; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import java.util.Arrays; -import java.util.List; - -/** - * 模型管理 控制层 - * - * @author may - */ -@Validated -@RequiredArgsConstructor -@RestController -@RequestMapping("/workflow/model") -public class ActModelController extends BaseController { - - @Autowired(required = false) - private RepositoryService repositoryService; - private final IActModelService actModelService; - - - /** - * 分页查询模型 - * - * @param modelBo 模型参数 - */ - @GetMapping("/list") - public TableDataInfo page(ModelBo modelBo, PageQuery pageQuery) { - return actModelService.page(modelBo, pageQuery); - } - - /** - * 新增模型 - * - * @param modelBo 模型请求对象 - */ - @Log(title = "模型管理", businessType = BusinessType.INSERT) - @RepeatSubmit() - @PostMapping("/save") - public R saveNewModel(@Validated(AddGroup.class) @RequestBody ModelBo modelBo) { - return toAjax(actModelService.saveNewModel(modelBo)); - } - - /** - * 查询模型 - * - * @param id 模型id - */ - @GetMapping("/getInfo/{id}") - public R getInfo(@NotBlank(message = "模型id不能为空") @PathVariable String id) { - return R.ok(actModelService.getInfo(id)); - } - - /** - * 修改模型信息 - * - * @param modelBo 模型数据 - */ - @Log(title = "模型管理", businessType = BusinessType.UPDATE) - @RepeatSubmit() - @PutMapping(value = "/update") - public R update(@RequestBody ModelBo modelBo) { - return toAjax(actModelService.update(modelBo)); - } - - /** - * 编辑XMl模型 - * - * @param modelBo 模型数据 - */ - @Log(title = "模型管理", businessType = BusinessType.UPDATE) - @RepeatSubmit() - @PutMapping(value = "/editModelXml") - public R editModel(@Validated(EditGroup.class) @RequestBody ModelBo modelBo) { - return toAjax(actModelService.editModelXml(modelBo)); - } - - /** - * 删除流程模型 - * - * @param ids 模型id - */ - @Log(title = "模型管理", businessType = BusinessType.DELETE) - @RepeatSubmit() - @DeleteMapping("/{ids}") - @Transactional(rollbackFor = Exception.class) - public R delete(@NotEmpty(message = "主键不能为空") @PathVariable String[] ids) { - Arrays.stream(ids).parallel().forEachOrdered(repositoryService::deleteModel); - return R.ok(); - } - - /** - * 模型部署 - * - * @param id 模型id - */ - @Log(title = "模型管理", businessType = BusinessType.INSERT) - @RepeatSubmit() - @PostMapping("/modelDeploy/{id}") - public R deploy(@NotBlank(message = "模型id不能为空") @PathVariable("id") String id) { - return toAjax(actModelService.modelDeploy(id)); - } - - /** - * 导出模型zip压缩包 - * - * @param modelIds 模型id - * @param response 相应 - */ - @GetMapping("/export/zip/{modelIds}") - public void exportZip(@NotEmpty(message = "模型id不能为空") @PathVariable List modelIds, - HttpServletResponse response) { - actModelService.exportZip(modelIds, response); - } - - /** - * 复制模型 - * - * @param modelBo 模型数据 - */ - @PostMapping("/copyModel") - public R copyModel(@RequestBody ModelBo modelBo) { - return toAjax(actModelService.copyModel(modelBo)); - } -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/ActProcessDefinitionController.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/ActProcessDefinitionController.java deleted file mode 100644 index 5198bd164..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/ActProcessDefinitionController.java +++ /dev/null @@ -1,147 +0,0 @@ -package org.dromara.workflow.controller; - -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; -import lombok.RequiredArgsConstructor; -import org.dromara.common.core.domain.R; -import org.dromara.common.idempotent.annotation.RepeatSubmit; -import org.dromara.common.log.annotation.Log; -import org.dromara.common.log.enums.BusinessType; -import org.dromara.common.mybatis.core.page.PageQuery; -import org.dromara.common.mybatis.core.page.TableDataInfo; -import org.dromara.common.web.core.BaseController; -import org.dromara.workflow.domain.bo.ProcessDefinitionBo; -import org.dromara.workflow.domain.vo.ProcessDefinitionVo; -import org.dromara.workflow.service.IActProcessDefinitionService; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; -import org.springframework.web.multipart.MultipartFile; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - - -/** - * 流程定义管理 控制层 - * - * @author may - */ -@Validated -@RequiredArgsConstructor -@RestController -@RequestMapping("/workflow/processDefinition") -public class ActProcessDefinitionController extends BaseController { - - private final IActProcessDefinitionService actProcessDefinitionService; - - /** - * 分页查询 - * - * @param bo 参数 - */ - @GetMapping("/list") - public TableDataInfo page(ProcessDefinitionBo bo, PageQuery pageQuery) { - return actProcessDefinitionService.page(bo, pageQuery); - } - - /** - * 查询历史流程定义列表 - * - * @param key 流程定义key - */ - @GetMapping("/getListByKey/{key}") - public R> getListByKey(@NotEmpty(message = "流程定义key不能为空") @PathVariable String key) { - return R.ok("操作成功", actProcessDefinitionService.getListByKey(key)); - } - - /** - * 查看流程定义图片 - * - * @param processDefinitionId 流程定义id - */ - @GetMapping("/definitionImage/{processDefinitionId}") - public R definitionImage(@PathVariable String processDefinitionId) { - return R.ok("操作成功", actProcessDefinitionService.definitionImage(processDefinitionId)); - } - - /** - * 查看流程定义xml文件 - * - * @param processDefinitionId 流程定义id - */ - @GetMapping("/definitionXml/{processDefinitionId}") - public R> definitionXml(@NotBlank(message = "流程定义id不能为空") @PathVariable String processDefinitionId) { - Map map = new HashMap<>(); - String xmlStr = actProcessDefinitionService.definitionXml(processDefinitionId); - map.put("xml", Arrays.asList(xmlStr.split("\n"))); - map.put("xmlStr", xmlStr); - return R.ok(map); - } - - /** - * 删除流程定义 - * - * @param deploymentIds 部署id - * @param processDefinitionIds 流程定义id - */ - @Log(title = "流程定义管理", businessType = BusinessType.DELETE) - @DeleteMapping("/{deploymentIds}/{processDefinitionIds}") - public R deleteDeployment(@NotNull(message = "流程部署id不能为空") @PathVariable List deploymentIds, - @NotNull(message = "流程定义id不能为空") @PathVariable List processDefinitionIds) { - return toAjax(actProcessDefinitionService.deleteDeployment(deploymentIds, processDefinitionIds)); - } - - /** - * 激活或者挂起流程定义 - * - * @param processDefinitionId 流程定义id - */ - @Log(title = "流程定义管理", businessType = BusinessType.UPDATE) - @RepeatSubmit() - @PutMapping("/updateDefinitionState/{processDefinitionId}") - public R updateDefinitionState(@NotBlank(message = "流程定义id不能为空") @PathVariable String processDefinitionId) { - return toAjax(actProcessDefinitionService.updateDefinitionState(processDefinitionId)); - } - - /** - * 迁移流程定义 - * - * @param currentProcessDefinitionId 当前流程定义id - * @param fromProcessDefinitionId 需要迁移到的流程定义id - */ - @Log(title = "流程定义管理", businessType = BusinessType.UPDATE) - @RepeatSubmit() - @PutMapping("/migrationDefinition/{currentProcessDefinitionId}/{fromProcessDefinitionId}") - public R migrationDefinition(@NotBlank(message = "当前流程定义id") @PathVariable String currentProcessDefinitionId, - @NotBlank(message = "需要迁移到的流程定义id") @PathVariable String fromProcessDefinitionId) { - return toAjax(actProcessDefinitionService.migrationDefinition(currentProcessDefinitionId, fromProcessDefinitionId)); - } - - /** - * 流程定义转换为模型 - * - * @param processDefinitionId 流程定义id - */ - @Log(title = "流程定义管理", businessType = BusinessType.UPDATE) - @RepeatSubmit() - @PutMapping("/convertToModel/{processDefinitionId}") - public R convertToModel(@NotEmpty(message = "流程定义id不能为空") @PathVariable String processDefinitionId) { - return toAjax(actProcessDefinitionService.convertToModel(processDefinitionId)); - } - - /** - * 通过zip或xml部署流程定义 - * - * @param file 文件 - * @param categoryCode 分类 - */ - @Log(title = "流程定义管理", businessType = BusinessType.INSERT) - @PostMapping("/deployByFile") - public void deployByFile(@RequestParam("file") MultipartFile file, @RequestParam("categoryCode") String categoryCode) { - actProcessDefinitionService.deployByFile(file, categoryCode); - } - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/ActProcessInstanceController.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/ActProcessInstanceController.java deleted file mode 100644 index 931b9f568..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/ActProcessInstanceController.java +++ /dev/null @@ -1,160 +0,0 @@ -package org.dromara.workflow.controller; - -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import lombok.RequiredArgsConstructor; -import org.dromara.common.core.domain.R; -import org.dromara.common.core.validate.AddGroup; -import org.dromara.common.idempotent.annotation.RepeatSubmit; -import org.dromara.common.log.annotation.Log; -import org.dromara.common.log.enums.BusinessType; -import org.dromara.common.mybatis.core.page.PageQuery; -import org.dromara.common.mybatis.core.page.TableDataInfo; -import org.dromara.common.web.core.BaseController; -import org.dromara.workflow.domain.bo.ProcessInstanceBo; -import org.dromara.workflow.domain.bo.ProcessInvalidBo; -import org.dromara.workflow.domain.bo.TaskUrgingBo; -import org.dromara.workflow.domain.vo.ActHistoryInfoVo; -import org.dromara.workflow.domain.vo.ProcessInstanceVo; -import org.dromara.workflow.service.IActProcessInstanceService; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import java.util.Arrays; -import java.util.List; -import java.util.Map; - -/** - * 流程实例管理 控制层 - * - * @author may - */ -@Validated -@RequiredArgsConstructor -@RestController -@RequestMapping("/workflow/processInstance") -public class ActProcessInstanceController extends BaseController { - - private final IActProcessInstanceService actProcessInstanceService; - - /** - * 分页查询正在运行的流程实例 - * - * @param bo 参数 - */ - @GetMapping("/getPageByRunning") - public TableDataInfo getPageByRunning(ProcessInstanceBo bo, PageQuery pageQuery) { - return actProcessInstanceService.getPageByRunning(bo, pageQuery); - } - - /** - * 分页查询已结束的流程实例 - * - * @param bo 参数 - */ - @GetMapping("/getPageByFinish") - public TableDataInfo getPageByFinish(ProcessInstanceBo bo, PageQuery pageQuery) { - return actProcessInstanceService.getPageByFinish(bo, pageQuery); - } - - /** - * 通过业务id获取历史流程图 - * - * @param businessKey 业务id - */ - @GetMapping("/getHistoryImage/{businessKey}") - public R getHistoryImage(@NotBlank(message = "业务id不能为空") @PathVariable String businessKey) { - return R.ok("操作成功", actProcessInstanceService.getHistoryImage(businessKey)); - } - - /** - * 通过业务id获取历史流程图运行中,历史等节点 - * - * @param businessKey 业务id - */ - @GetMapping("/getHistoryList/{businessKey}") - public R> getHistoryList(@NotBlank(message = "业务id不能为空") @PathVariable String businessKey) { - return R.ok("操作成功", actProcessInstanceService.getHistoryList(businessKey)); - } - - /** - * 获取审批记录 - * - * @param businessKey 业务id - */ - @GetMapping("/getHistoryRecord/{businessKey}") - public R> getHistoryRecord(@NotBlank(message = "业务id不能为空") @PathVariable String businessKey) { - return R.ok(actProcessInstanceService.getHistoryRecord(businessKey)); - } - - /** - * 作废流程实例,不会删除历史记录(删除运行中的实例) - * - * @param processInvalidBo 参数 - */ - @Log(title = "流程实例管理", businessType = BusinessType.DELETE) - @RepeatSubmit() - @PostMapping("/deleteRunInstance") - public R deleteRunInstance(@Validated(AddGroup.class) @RequestBody ProcessInvalidBo processInvalidBo) { - return toAjax(actProcessInstanceService.deleteRunInstance(processInvalidBo)); - } - - /** - * 运行中的实例 删除程实例,删除历史记录,删除业务与流程关联信息 - * - * @param businessKeys 业务id - */ - @Log(title = "流程实例管理", businessType = BusinessType.DELETE) - @RepeatSubmit() - @DeleteMapping("/deleteRunAndHisInstance/{businessKeys}") - public R deleteRunAndHisInstance(@NotNull(message = "业务id不能为空") @PathVariable String[] businessKeys) { - return toAjax(actProcessInstanceService.deleteRunAndHisInstance(Arrays.asList(businessKeys))); - } - - /** - * 已完成的实例 删除程实例,删除历史记录,删除业务与流程关联信息 - * - * @param businessKeys 业务id - */ - @Log(title = "流程实例管理", businessType = BusinessType.DELETE) - @RepeatSubmit() - @DeleteMapping("/deleteFinishAndHisInstance/{businessKeys}") - public R deleteFinishAndHisInstance(@NotNull(message = "业务id不能为空") @PathVariable String[] businessKeys) { - return toAjax(actProcessInstanceService.deleteFinishAndHisInstance(Arrays.asList(businessKeys))); - } - - /** - * 撤销流程申请 - * - * @param businessKey 业务id - */ - @Log(title = "流程实例管理", businessType = BusinessType.INSERT) - @RepeatSubmit() - @PostMapping("/cancelProcessApply/{businessKey}") - public R cancelProcessApply(@NotBlank(message = "业务id不能为空") @PathVariable String businessKey) { - return toAjax(actProcessInstanceService.cancelProcessApply(businessKey)); - } - - /** - * 分页查询当前登录人单据 - * - * @param bo 参数 - */ - @GetMapping("/getPageByCurrent") - public TableDataInfo getPageByCurrent(ProcessInstanceBo bo, PageQuery pageQuery) { - return actProcessInstanceService.getPageByCurrent(bo, pageQuery); - } - - /** - * 任务催办(给当前任务办理人发送站内信,邮件,短信等) - * - * @param taskUrgingBo 任务催办 - */ - @Log(title = "流程实例管理", businessType = BusinessType.INSERT) - @RepeatSubmit() - @PostMapping("/taskUrging") - public R taskUrging(@RequestBody TaskUrgingBo taskUrgingBo) { - return toAjax(actProcessInstanceService.taskUrging(taskUrgingBo)); - } - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/ActTaskController.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/ActTaskController.java deleted file mode 100644 index 25724b6d9..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/ActTaskController.java +++ /dev/null @@ -1,295 +0,0 @@ -package org.dromara.workflow.controller; - -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.convert.Convert; -import jakarta.validation.constraints.NotBlank; -import lombok.RequiredArgsConstructor; -import org.dromara.common.core.domain.R; -import org.dromara.common.core.validate.AddGroup; -import org.dromara.common.idempotent.annotation.RepeatSubmit; -import org.dromara.common.log.annotation.Log; -import org.dromara.common.log.enums.BusinessType; -import org.dromara.common.mybatis.core.page.PageQuery; -import org.dromara.common.mybatis.core.page.TableDataInfo; -import org.dromara.common.satoken.utils.LoginHelper; -import org.dromara.common.web.core.BaseController; -import org.dromara.workflow.domain.WfTaskBackNode; -import org.dromara.workflow.domain.bo.*; -import org.dromara.workflow.domain.vo.TaskVo; -import org.dromara.workflow.domain.vo.VariableVo; -import org.dromara.workflow.service.IActTaskService; -import org.dromara.workflow.service.IWfTaskBackNodeService; -import org.dromara.workflow.utils.QueryUtils; -import org.flowable.engine.TaskService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import java.util.List; -import java.util.Map; - -/** - * 任务管理 控制层 - * - * @author may - */ -@Validated -@RequiredArgsConstructor -@RestController -@RequestMapping("/workflow/task") -public class ActTaskController extends BaseController { - - @Autowired(required = false) - private TaskService taskService; - private final IActTaskService actTaskService; - private final IWfTaskBackNodeService wfTaskBackNodeService; - - - /** - * 启动任务 - * - * @param startProcessBo 启动流程参数 - */ - @Log(title = "任务管理", businessType = BusinessType.INSERT) - @RepeatSubmit() - @PostMapping("/startWorkFlow") - public R> startWorkFlow(@Validated(AddGroup.class) @RequestBody StartProcessBo startProcessBo) { - Map map = actTaskService.startWorkFlow(startProcessBo); - return R.ok("提交成功", map); - } - - /** - * 办理任务 - * - * @param completeTaskBo 办理任务参数 - */ - @Log(title = "任务管理", businessType = BusinessType.INSERT) - @RepeatSubmit() - @PostMapping("/completeTask") - public R completeTask(@Validated(AddGroup.class) @RequestBody CompleteTaskBo completeTaskBo) { - return toAjax(actTaskService.completeTask(completeTaskBo)); - } - - /** - * 查询当前用户的待办任务 - * - * @param taskBo 参数 - */ - @GetMapping("/getPageByTaskWait") - public TableDataInfo getPageByTaskWait(TaskBo taskBo, PageQuery pageQuery) { - return actTaskService.getPageByTaskWait(taskBo, pageQuery); - } - - /** - * 查询当前租户所有待办任务 - * - * @param taskBo 参数 - */ - @GetMapping("/getPageByAllTaskWait") - public TableDataInfo getPageByAllTaskWait(TaskBo taskBo, PageQuery pageQuery) { - return actTaskService.getPageByAllTaskWait(taskBo, pageQuery); - } - - /** - * 查询当前用户的已办任务 - * - * @param taskBo 参数 - */ - @GetMapping("/getPageByTaskFinish") - public TableDataInfo getPageByTaskFinish(TaskBo taskBo, PageQuery pageQuery) { - return actTaskService.getPageByTaskFinish(taskBo, pageQuery); - } - - /** - * 查询当前用户的抄送 - * - * @param taskBo 参数 - */ - @GetMapping("/getPageByTaskCopy") - public TableDataInfo getPageByTaskCopy(TaskBo taskBo, PageQuery pageQuery) { - return actTaskService.getPageByTaskCopy(taskBo, pageQuery); - } - - /** - * 查询当前租户所有已办任务 - * - * @param taskBo 参数 - */ - @GetMapping("/getPageByAllTaskFinish") - public TableDataInfo getPageByAllTaskFinish(TaskBo taskBo, PageQuery pageQuery) { - return actTaskService.getPageByAllTaskFinish(taskBo, pageQuery); - } - - /** - * 签收(拾取)任务 - * - * @param taskId 任务id - */ - @Log(title = "任务管理", businessType = BusinessType.INSERT) - @RepeatSubmit() - @PostMapping("/claim/{taskId}") - public R claimTask(@NotBlank(message = "任务id不能为空") @PathVariable String taskId) { - try { - taskService.claim(taskId, Convert.toStr(LoginHelper.getUserId())); - return R.ok(); - } catch (Exception e) { - e.printStackTrace(); - return R.fail("签收任务失败:" + e.getMessage()); - } - } - - /** - * 归还(拾取的)任务 - * - * @param taskId 任务id - */ - @Log(title = "任务管理", businessType = BusinessType.INSERT) - @RepeatSubmit() - @PostMapping("/returnTask/{taskId}") - public R returnTask(@NotBlank(message = "任务id不能为空") @PathVariable String taskId) { - try { - taskService.setAssignee(taskId, null); - return R.ok(); - } catch (Exception e) { - e.printStackTrace(); - return R.fail("归还任务失败:" + e.getMessage()); - } - } - - /** - * 委派任务 - * - * @param delegateBo 参数 - */ - @Log(title = "任务管理", businessType = BusinessType.INSERT) - @RepeatSubmit() - @PostMapping("/delegateTask") - public R delegateTask(@Validated({AddGroup.class}) @RequestBody DelegateBo delegateBo) { - return toAjax(actTaskService.delegateTask(delegateBo)); - } - - /** - * 终止任务 - * - * @param terminationBo 参数 - */ - @Log(title = "任务管理", businessType = BusinessType.DELETE) - @RepeatSubmit() - @PostMapping("/terminationTask") - public R terminationTask(@RequestBody TerminationBo terminationBo) { - return toAjax(actTaskService.terminationTask(terminationBo)); - } - - /** - * 转办任务 - * - * @param transmitBo 参数 - */ - @Log(title = "任务管理", businessType = BusinessType.INSERT) - @RepeatSubmit() - @PostMapping("/transferTask") - public R transferTask(@Validated({AddGroup.class}) @RequestBody TransmitBo transmitBo) { - return toAjax(actTaskService.transferTask(transmitBo)); - } - - /** - * 会签任务加签 - * - * @param addMultiBo 参数 - */ - @Log(title = "任务管理", businessType = BusinessType.INSERT) - @RepeatSubmit() - @PostMapping("/addMultiInstanceExecution") - public R addMultiInstanceExecution(@Validated({AddGroup.class}) @RequestBody AddMultiBo addMultiBo) { - return toAjax(actTaskService.addMultiInstanceExecution(addMultiBo)); - } - - /** - * 会签任务减签 - * - * @param deleteMultiBo 参数 - */ - @Log(title = "任务管理", businessType = BusinessType.INSERT) - @RepeatSubmit() - @PostMapping("/deleteMultiInstanceExecution") - public R deleteMultiInstanceExecution(@Validated({AddGroup.class}) @RequestBody DeleteMultiBo deleteMultiBo) { - return toAjax(actTaskService.deleteMultiInstanceExecution(deleteMultiBo)); - } - - /** - * 驳回审批 - * - * @param backProcessBo 参数 - */ - @Log(title = "任务管理", businessType = BusinessType.INSERT) - @RepeatSubmit() - @PostMapping("/backProcess") - public R backProcess(@Validated({AddGroup.class}) @RequestBody BackProcessBo backProcessBo) { - return R.ok("操作成功", actTaskService.backProcess(backProcessBo)); - } - - /** - * 获取当前任务 - * - * @param taskId 任务id - */ - @GetMapping("/getTaskById/{taskId}") - public R getTaskById(@PathVariable String taskId) { - return R.ok(QueryUtils.getTask(taskId)); - } - - - /** - * 修改任务办理人 - * - * @param taskIds 任务id - * @param userId 办理人id - */ - @Log(title = "任务管理", businessType = BusinessType.UPDATE) - @RepeatSubmit() - @PutMapping("/updateAssignee/{taskIds}/{userId}") - public R updateAssignee(@PathVariable String[] taskIds, @PathVariable String userId) { - return toAjax(actTaskService.updateAssignee(taskIds, userId)); - } - - /** - * 查询流程变量 - * - * @param taskId 任务id - */ - @GetMapping("/getInstanceVariable/{taskId}") - public R> getProcessInstVariable(@PathVariable String taskId) { - return R.ok(actTaskService.getInstanceVariable(taskId)); - } - - /** - * 获取可驳回得任务节点 - * - * @param processInstanceId 流程实例id - */ - @GetMapping("/getTaskNodeList/{processInstanceId}") - public R> getNodeList(@PathVariable String processInstanceId) { - return R.ok(CollUtil.reverse(wfTaskBackNodeService.getListByInstanceId(processInstanceId))); - } - - /** - * 查询工作流任务用户选择加签人员 - * - * @param taskId 任务id - */ - @GetMapping("/getTaskUserIdsByAddMultiInstance/{taskId}") - public R getTaskUserIdsByAddMultiInstance(@PathVariable String taskId) { - return R.ok("操作成功", actTaskService.getTaskUserIdsByAddMultiInstance(taskId)); - } - - /** - * 查询工作流选择减签人员 - * - * @param taskId 任务id - */ - @GetMapping("/getListByDeleteMultiInstance/{taskId}") - public R> getListByDeleteMultiInstance(@PathVariable String taskId) { - return R.ok(actTaskService.getListByDeleteMultiInstance(taskId)); - } - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwCategoryController.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwCategoryController.java new file mode 100644 index 000000000..9520cbdef --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwCategoryController.java @@ -0,0 +1,132 @@ +package org.dromara.workflow.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.lang.tree.Tree; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.constraints.NotNull; +import lombok.RequiredArgsConstructor; +import org.dromara.common.core.domain.R; +import org.dromara.common.core.validate.AddGroup; +import org.dromara.common.core.validate.EditGroup; +import org.dromara.common.excel.utils.ExcelUtil; +import org.dromara.common.idempotent.annotation.RepeatSubmit; +import org.dromara.common.log.annotation.Log; +import org.dromara.common.log.enums.BusinessType; +import org.dromara.common.web.core.BaseController; +import org.dromara.workflow.common.ConditionalOnEnable; +import org.dromara.workflow.domain.bo.FlowCategoryBo; +import org.dromara.workflow.domain.vo.FlowCategoryVo; +import org.dromara.workflow.service.IFlwCategoryService; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 流程分类 + * + * @author may + */ +@ConditionalOnEnable +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("/workflow/category") +public class FlwCategoryController extends BaseController { + + private final IFlwCategoryService flwCategoryService; + + /** + * 查询流程分类列表 + */ + @SaCheckPermission("workflow:category:list") + @GetMapping("/list") + public R> list(FlowCategoryBo bo) { + List list = flwCategoryService.queryList(bo); + return R.ok(list); + } + + /** + * 导出流程分类列表 + */ + @SaCheckPermission("workflow:category:export") + @Log(title = "流程分类", businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(FlowCategoryBo bo, HttpServletResponse response) { + List list = flwCategoryService.queryList(bo); + ExcelUtil.exportExcel(list, "流程分类", FlowCategoryVo.class, response); + } + + /** + * 获取流程分类详细信息 + * + * @param categoryId 主键 + */ + @SaCheckPermission("workflow:category:query") + @GetMapping("/{categoryId}") + public R getInfo(@NotNull(message = "主键不能为空") @PathVariable Long categoryId) { + flwCategoryService.checkCategoryDataScope(categoryId); + return R.ok(flwCategoryService.queryById(categoryId)); + } + + /** + * 新增流程分类 + */ + @SaCheckPermission("workflow:category:add") + @Log(title = "流程分类", businessType = BusinessType.INSERT) + @RepeatSubmit() + @PostMapping() + public R add(@Validated(AddGroup.class) @RequestBody FlowCategoryBo category) { + if (!flwCategoryService.checkCategoryNameUnique(category)) { + return R.fail("新增流程分类'" + category.getCategoryName() + "'失败,流程分类名称已存在"); + } + return toAjax(flwCategoryService.insertByBo(category)); + } + + /** + * 修改流程分类 + */ + @SaCheckPermission("workflow:category:edit") + @Log(title = "流程分类", businessType = BusinessType.UPDATE) + @RepeatSubmit() + @PutMapping() + public R edit(@Validated(EditGroup.class) @RequestBody FlowCategoryBo category) { + Long categoryId = category.getCategoryId(); + flwCategoryService.checkCategoryDataScope(categoryId); + if (!flwCategoryService.checkCategoryNameUnique(category)) { + return R.fail("修改流程分类'" + category.getCategoryName() + "'失败,流程分类名称已存在"); + } else if (category.getParentId().equals(categoryId)) { + return R.fail("修改流程分类'" + category.getCategoryName() + "'失败,上级流程分类不能是自己"); + } + return toAjax(flwCategoryService.updateByBo(category)); + } + + /** + * 删除流程分类 + * + * @param categoryId 主键 + */ + @SaCheckPermission("workflow:category:remove") + @Log(title = "流程分类", businessType = BusinessType.DELETE) + @DeleteMapping("/{categoryId}") + public R remove(@PathVariable Long categoryId) { + if (flwCategoryService.hasChildByCategoryId(categoryId)) { + return R.warn("存在下级流程分类,不允许删除"); + } + if (flwCategoryService.checkCategoryExistDefinition(categoryId)) { + return R.warn("流程分类存在流程定义,不允许删除"); + } + return toAjax(flwCategoryService.deleteWithValidById(categoryId)); + } + + /** + * 获取流程分类树列表 + * + * @param categoryBo 流程分类 + */ + @GetMapping("/categoryTree") + public R>> categoryTree(FlowCategoryBo categoryBo) { + return R.ok(flwCategoryService.selectCategoryTreeList(categoryBo)); + } + +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwDefinitionController.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwDefinitionController.java new file mode 100644 index 000000000..10d9de838 --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwDefinitionController.java @@ -0,0 +1,194 @@ +package org.dromara.workflow.controller; + +import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; +import org.dromara.common.core.domain.R; +import org.dromara.common.idempotent.annotation.RepeatSubmit; +import org.dromara.common.log.annotation.Log; +import org.dromara.common.log.enums.BusinessType; +import org.dromara.common.mybatis.core.page.PageQuery; +import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.common.web.core.BaseController; +import org.dromara.warm.flow.core.entity.Definition; +import org.dromara.warm.flow.core.service.DefService; +import org.dromara.warm.flow.orm.entity.FlowDefinition; +import org.dromara.workflow.common.ConditionalOnEnable; +import org.dromara.workflow.domain.vo.FlowDefinitionVo; +import org.dromara.workflow.service.IFlwDefinitionService; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.util.List; + +/** + * 流程定义管理 控制层 + * + * @author may + */ +@ConditionalOnEnable +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("/workflow/definition") +public class FlwDefinitionController extends BaseController { + + private final DefService defService; + private final IFlwDefinitionService flwDefinitionService; + + /** + * 查询流程定义列表 + * + * @param flowDefinition 参数 + * @param pageQuery 分页 + */ + @GetMapping("/list") + public TableDataInfo list(FlowDefinition flowDefinition, PageQuery pageQuery) { + return flwDefinitionService.queryList(flowDefinition, pageQuery); + } + + /** + * 查询未发布的流程定义列表 + * + * @param flowDefinition 参数 + * @param pageQuery 分页 + */ + @GetMapping("/unPublishList") + public TableDataInfo unPublishList(FlowDefinition flowDefinition, PageQuery pageQuery) { + return flwDefinitionService.unPublishList(flowDefinition, pageQuery); + } + + /** + * 获取流程定义详细信息 + * + * @param id 流程定义id + */ + @GetMapping(value = "/{id}") + public R getInfo(@PathVariable Long id) { + return R.ok(defService.getById(id)); + } + + /** + * 新增流程定义 + * + * @param flowDefinition 参数 + */ + @Log(title = "流程定义", businessType = BusinessType.INSERT) + @PostMapping + @RepeatSubmit() + @Transactional(rollbackFor = Exception.class) + public R add(@RequestBody FlowDefinition flowDefinition) { + return R.ok(defService.checkAndSave(flowDefinition)); + } + + /** + * 修改流程定义 + * + * @param flowDefinition 参数 + */ + @Log(title = "流程定义", businessType = BusinessType.UPDATE) + @PutMapping + @RepeatSubmit() + @Transactional(rollbackFor = Exception.class) + public R edit(@RequestBody FlowDefinition flowDefinition) { + return R.ok(defService.updateById(flowDefinition)); + } + + /** + * 发布流程定义 + * + * @param id 流程定义id + */ + @Log(title = "流程定义", businessType = BusinessType.INSERT) + @PutMapping("/publish/{id}") + @RepeatSubmit() + public R publish(@PathVariable Long id) { + return R.ok(flwDefinitionService.publish(id)); + } + + /** + * 取消发布流程定义 + * + * @param id 流程定义id + */ + @Log(title = "流程定义", businessType = BusinessType.INSERT) + @PutMapping("/unPublish/{id}") + @RepeatSubmit() + @Transactional(rollbackFor = Exception.class) + public R unPublish(@PathVariable Long id) { + return R.ok(defService.unPublish(id)); + } + + /** + * 删除流程定义 + */ + @Log(title = "流程定义", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public R remove(@PathVariable List ids) { + return toAjax(flwDefinitionService.removeDef(ids)); + } + + /** + * 复制流程定义 + * + * @param id 流程定义id + */ + @Log(title = "流程定义", businessType = BusinessType.INSERT) + @PostMapping("/copy/{id}") + @RepeatSubmit() + @Transactional(rollbackFor = Exception.class) + public R copy(@PathVariable Long id) { + return R.ok(defService.copyDef(id)); + } + + /** + * 导入流程定义 + * + * @param file 文件 + * @param category 分类 + */ + @Log(title = "流程定义", businessType = BusinessType.IMPORT) + @PostMapping("/importDef") + public R importDef(MultipartFile file, String category) { + return R.ok(flwDefinitionService.importJson(file, category)); + } + + /** + * 导出流程定义 + * + * @param id 流程定义id + * @param response 响应 + * @throws IOException 异常 + */ + @Log(title = "流程定义", businessType = BusinessType.EXPORT) + @PostMapping("/exportDef/{id}") + public void exportDef(@PathVariable Long id, HttpServletResponse response) throws IOException { + flwDefinitionService.exportDef(id, response); + } + + /** + * 获取流程定义JSON字符串 + * + * @param id 流程定义id + */ + @GetMapping("/xmlString/{id}") + public R xmlString(@PathVariable Long id) { + return R.ok("操作成功", defService.exportJson(id)); + } + + /** + * 激活/挂起流程定义 + * + * @param id 流程定义id + * @param active 激活/挂起 + */ + @RepeatSubmit() + @PutMapping("/active/{id}") + @Transactional(rollbackFor = Exception.class) + public R active(@PathVariable Long id, @RequestParam boolean active) { + return R.ok(active ? defService.active(id) : defService.unActive(id)); + } + +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwInstanceController.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwInstanceController.java new file mode 100644 index 000000000..f85b8ff0a --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwInstanceController.java @@ -0,0 +1,157 @@ +package org.dromara.workflow.controller; + +import lombok.RequiredArgsConstructor; +import org.dromara.common.core.domain.R; +import org.dromara.common.idempotent.annotation.RepeatSubmit; +import org.dromara.common.log.annotation.Log; +import org.dromara.common.log.enums.BusinessType; +import org.dromara.common.mybatis.core.page.PageQuery; +import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.common.web.core.BaseController; +import org.dromara.warm.flow.core.service.InsService; +import org.dromara.workflow.common.ConditionalOnEnable; +import org.dromara.workflow.domain.bo.FlowCancelBo; +import org.dromara.workflow.domain.bo.FlowInstanceBo; +import org.dromara.workflow.domain.bo.FlowInvalidBo; +import org.dromara.workflow.domain.vo.FlowInstanceVo; +import org.dromara.workflow.service.IFlwInstanceService; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.Map; + +/** + * 流程实例管理 控制层 + * + * @author may + */ +@ConditionalOnEnable +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("/workflow/instance") +public class FlwInstanceController extends BaseController { + + private final InsService insService; + private final IFlwInstanceService flwInstanceService; + + /** + * 查询正在运行的流程实例列表 + * + * @param flowInstanceBo 流程实例 + * @param pageQuery 分页 + */ + @GetMapping("/pageByRunning") + public TableDataInfo selectRunningInstanceList(FlowInstanceBo flowInstanceBo, PageQuery pageQuery) { + return flwInstanceService.selectRunningInstanceList(flowInstanceBo, pageQuery); + } + + /** + * 查询已结束的流程实例列表 + * + * @param flowInstanceBo 流程实例 + * @param pageQuery 分页 + */ + @GetMapping("/pageByFinish") + public TableDataInfo selectFinishInstanceList(FlowInstanceBo flowInstanceBo, PageQuery pageQuery) { + return flwInstanceService.selectFinishInstanceList(flowInstanceBo, pageQuery); + } + + /** + * 根据业务id查询流程实例详细信息 + * + * @param businessId 业务id + */ + @GetMapping("/getInfo/{businessId}") + public R getInfo(@PathVariable Long businessId) { + return R.ok(flwInstanceService.queryByBusinessId(businessId)); + } + + /** + * 按照业务id删除流程实例 + * + * @param businessIds 业务id + */ + @DeleteMapping("/deleteByBusinessIds/{businessIds}") + public R deleteByBusinessIds(@PathVariable List businessIds) { + return toAjax(flwInstanceService.deleteByBusinessIds(businessIds)); + } + + /** + * 按照实例id删除流程实例 + * + * @param instanceIds 实例id + */ + @DeleteMapping("/deleteByInstanceIds/{instanceIds}") + public R deleteByInstanceIds(@PathVariable List instanceIds) { + return toAjax(flwInstanceService.deleteByInstanceIds(instanceIds)); + } + + /** + * 撤销流程 + * + * @param bo 参数 + */ + @RepeatSubmit() + @PutMapping("/cancelProcessApply") + public R cancelProcessApply(@RequestBody FlowCancelBo bo) { + return toAjax(flwInstanceService.cancelProcessApply(bo)); + } + + /** + * 激活/挂起流程实例 + * + * @param id 流程实例id + * @param active 激活/挂起 + */ + @RepeatSubmit() + @PutMapping("/active/{id}") + public R active(@PathVariable Long id, @RequestParam boolean active) { + return R.ok(active ? insService.active(id) : insService.unActive(id)); + } + + /** + * 获取当前登陆人发起的流程实例 + * + * @param flowInstanceBo 参数 + * @param pageQuery 分页 + */ + @GetMapping("/pageByCurrent") + public TableDataInfo selectCurrentInstanceList(FlowInstanceBo flowInstanceBo, PageQuery pageQuery) { + return flwInstanceService.selectCurrentInstanceList(flowInstanceBo, pageQuery); + } + + /** + * 获取流程图,流程记录 + * + * @param businessId 业务id + */ + @GetMapping("/flowImage/{businessId}") + public R> flowImage(@PathVariable String businessId) { + return R.ok(flwInstanceService.flowImage(businessId)); + } + + /** + * 获取流程变量 + * + * @param instanceId 流程实例id + */ + @GetMapping("/instanceVariable/{instanceId}") + public R> instanceVariable(@PathVariable String instanceId) { + return R.ok(flwInstanceService.instanceVariable(instanceId)); + } + + /** + * 作废流程 + * + * @param bo 参数 + */ + @Log(title = "流程实例管理", businessType = BusinessType.INSERT) + @RepeatSubmit() + @PostMapping("/invalid") + public R invalid(@Validated @RequestBody FlowInvalidBo bo) { + return R.ok(flwInstanceService.processInvalid(bo)); + } + +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwTaskController.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwTaskController.java new file mode 100644 index 000000000..5d9535afc --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwTaskController.java @@ -0,0 +1,201 @@ +package org.dromara.workflow.controller; + +import lombok.RequiredArgsConstructor; +import org.dromara.common.core.domain.R; +import org.dromara.common.core.domain.dto.UserDTO; +import org.dromara.common.core.validate.AddGroup; +import org.dromara.common.idempotent.annotation.RepeatSubmit; +import org.dromara.common.log.annotation.Log; +import org.dromara.common.log.enums.BusinessType; +import org.dromara.common.mybatis.core.page.PageQuery; +import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.common.web.core.BaseController; +import org.dromara.warm.flow.core.entity.Node; +import org.dromara.workflow.common.ConditionalOnEnable; +import org.dromara.workflow.domain.bo.*; +import org.dromara.workflow.domain.vo.FlowHisTaskVo; +import org.dromara.workflow.domain.vo.FlowTaskVo; +import org.dromara.workflow.service.IFlwTaskService; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.Map; + +/** + * 任务管理 控制层 + * + * @author may + */ +@ConditionalOnEnable +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("/workflow/task") +public class FlwTaskController extends BaseController { + + private final IFlwTaskService flwTaskService; + + /** + * 启动任务 + * + * @param startProcessBo 启动流程参数 + */ + @Log(title = "任务管理", businessType = BusinessType.INSERT) + @RepeatSubmit() + @PostMapping("/startWorkFlow") + public R> startWorkFlow(@Validated(AddGroup.class) @RequestBody StartProcessBo startProcessBo) { + Map map = flwTaskService.startWorkFlow(startProcessBo); + return R.ok("提交成功", map); + } + + /** + * 办理任务 + * + * @param completeTaskBo 办理任务参数 + */ + @Log(title = "任务管理", businessType = BusinessType.INSERT) + @RepeatSubmit() + @PostMapping("/completeTask") + public R completeTask(@Validated(AddGroup.class) @RequestBody CompleteTaskBo completeTaskBo) { + return toAjax(flwTaskService.completeTask(completeTaskBo)); + } + + /** + * 查询当前用户的待办任务 + * + * @param flowTaskBo 参数 + * @param pageQuery 分页 + */ + @GetMapping("/pageByTaskWait") + public TableDataInfo pageByTaskWait(FlowTaskBo flowTaskBo, PageQuery pageQuery) { + return flwTaskService.pageByTaskWait(flowTaskBo, pageQuery); + } + + /** + * 查询当前用户的已办任务 + * + * @param flowTaskBo 参数 + * @param pageQuery 分页 + */ + + @GetMapping("/pageByTaskFinish") + public TableDataInfo pageByTaskFinish(FlowTaskBo flowTaskBo, PageQuery pageQuery) { + return flwTaskService.pageByTaskFinish(flowTaskBo, pageQuery); + } + + /** + * 查询待办任务 + * + * @param flowTaskBo 参数 + * @param pageQuery 分页 + */ + @GetMapping("/pageByAllTaskWait") + public TableDataInfo pageByAllTaskWait(FlowTaskBo flowTaskBo, PageQuery pageQuery) { + return flwTaskService.pageByAllTaskWait(flowTaskBo, pageQuery); + } + + /** + * 查询已办任务 + * + * @param flowTaskBo 参数 + * @param pageQuery 分页 + */ + @GetMapping("/pageByAllTaskFinish") + public TableDataInfo pageByAllTaskFinish(FlowTaskBo flowTaskBo, PageQuery pageQuery) { + return flwTaskService.pageByAllTaskFinish(flowTaskBo, pageQuery); + } + + /** + * 查询当前用户的抄送 + * + * @param flowTaskBo 参数 + * @param pageQuery 分页 + */ + @GetMapping("/pageByTaskCopy") + public TableDataInfo pageByTaskCopy(FlowTaskBo flowTaskBo, PageQuery pageQuery) { + return flwTaskService.pageByTaskCopy(flowTaskBo, pageQuery); + } + + /** + * 根据taskId查询代表任务 + * + * @param taskId 任务id + */ + @GetMapping("/getTask/{taskId}") + public R getTask(@PathVariable Long taskId) { + return R.ok(flwTaskService.selectById(taskId)); + } + + /** + * 终止任务 + * + * @param bo 参数 + */ + @Log(title = "任务管理", businessType = BusinessType.INSERT) + @RepeatSubmit() + @PostMapping("/terminationTask") + public R terminationTask(@RequestBody FlowTerminationBo bo) { + return R.ok(flwTaskService.terminationTask(bo)); + } + + /** + * 任务操作 + * + * @param bo 参数 + * @param taskOperation 操作类型,委派 delegateTask、转办 transferTask、加签 addSignature、减签 reductionSignature + */ + @Log(title = "任务管理", businessType = BusinessType.UPDATE) + @RepeatSubmit + @PostMapping("/taskOperation/{taskOperation}") + public R taskOperation(@Validated @RequestBody TaskOperationBo bo, @PathVariable String taskOperation) { + return toAjax(flwTaskService.taskOperation(bo, taskOperation)); + } + + /** + * 修改任务办理人 + * + * @param taskIdList 任务id + * @param userId 办理人id + */ + @Log(title = "任务管理", businessType = BusinessType.UPDATE) + @RepeatSubmit() + @PutMapping("/updateAssignee/{userId}") + public R updateAssignee(@RequestBody List taskIdList, @PathVariable String userId) { + return toAjax(flwTaskService.updateAssignee(taskIdList, userId)); + } + + /** + * 驳回审批 + * + * @param bo 参数 + */ + @Log(title = "任务管理", businessType = BusinessType.INSERT) + @RepeatSubmit() + @PostMapping("/backProcess") + public R backProcess(@Validated({AddGroup.class}) @RequestBody BackProcessBo bo) { + return toAjax(flwTaskService.backProcess(bo)); + } + + /** + * 获取可驳回的前置节点 + * + * @param definitionId 流程定义id + * @param nowNodeCode 当前节点 + */ + @GetMapping("/getBackTaskNode/{definitionId}/{nowNodeCode}") + public R> getBackTaskNode(@PathVariable Long definitionId, @PathVariable String nowNodeCode) { + return R.ok(flwTaskService.getBackTaskNode(definitionId, nowNodeCode)); + } + + /** + * 获取当前任务的所有办理人 + * + * @param taskId 任务id + */ + @GetMapping("/currentTaskAllUser/{taskId}") + public R> currentTaskAllUser(@PathVariable Long taskId) { + return R.ok(flwTaskService.currentTaskAllUser(taskId)); + } + +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/TestLeaveController.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/TestLeaveController.java index e1c246f06..98825d92d 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/TestLeaveController.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/TestLeaveController.java @@ -15,6 +15,7 @@ import org.dromara.common.log.enums.BusinessType; import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.web.core.BaseController; +import org.dromara.workflow.common.ConditionalOnEnable; import org.dromara.workflow.domain.bo.TestLeaveBo; import org.dromara.workflow.domain.vo.TestLeaveVo; import org.dromara.workflow.service.ITestLeaveService; @@ -29,6 +30,7 @@ import java.util.List; * @author may * @date 2023-07-21 */ +@ConditionalOnEnable @Validated @RequiredArgsConstructor @RestController diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/WfCategoryController.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/WfCategoryController.java deleted file mode 100644 index 8dced8929..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/WfCategoryController.java +++ /dev/null @@ -1,106 +0,0 @@ -package org.dromara.workflow.controller; - -import cn.dev33.satoken.annotation.SaCheckPermission; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; -import lombok.RequiredArgsConstructor; -import org.dromara.common.core.domain.R; -import org.dromara.common.core.validate.AddGroup; -import org.dromara.common.core.validate.EditGroup; -import org.dromara.common.excel.utils.ExcelUtil; -import org.dromara.common.idempotent.annotation.RepeatSubmit; -import org.dromara.common.log.annotation.Log; -import org.dromara.common.log.enums.BusinessType; -import org.dromara.common.web.core.BaseController; -import org.dromara.workflow.domain.bo.WfCategoryBo; -import org.dromara.workflow.domain.vo.WfCategoryVo; -import org.dromara.workflow.service.IWfCategoryService; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -/** - * 流程分类 - * - * @author may - * @date 2023-06-28 - */ -@Validated -@RequiredArgsConstructor -@RestController -@RequestMapping("/workflow/category") -public class WfCategoryController extends BaseController { - - private final IWfCategoryService wfCategoryService; - - /** - * 查询流程分类列表 - */ - @SaCheckPermission("workflow:category:list") - @GetMapping("/list") - public R> list(WfCategoryBo bo) { - List list = wfCategoryService.queryList(bo); - return R.ok(list); - - } - - /** - * 导出流程分类列表 - */ - @SaCheckPermission("workflow:category:export") - @Log(title = "流程分类", businessType = BusinessType.EXPORT) - @PostMapping("/export") - public void export(WfCategoryBo bo, HttpServletResponse response) { - List list = wfCategoryService.queryList(bo); - ExcelUtil.exportExcel(list, "流程分类", WfCategoryVo.class, response); - } - - /** - * 获取流程分类详细信息 - * - * @param id 主键 - */ - @SaCheckPermission("workflow:category:query") - @GetMapping("/{id}") - public R getInfo(@NotNull(message = "主键不能为空") - @PathVariable Long id) { - return R.ok(wfCategoryService.queryById(id)); - } - - /** - * 新增流程分类 - */ - @SaCheckPermission("workflow:category:add") - @Log(title = "流程分类", businessType = BusinessType.INSERT) - @RepeatSubmit() - @PostMapping() - public R add(@Validated(AddGroup.class) @RequestBody WfCategoryBo bo) { - return toAjax(wfCategoryService.insertByBo(bo)); - } - - /** - * 修改流程分类 - */ - @SaCheckPermission("workflow:category:edit") - @Log(title = "流程分类", businessType = BusinessType.UPDATE) - @RepeatSubmit() - @PutMapping() - public R edit(@Validated(EditGroup.class) @RequestBody WfCategoryBo bo) { - return toAjax(wfCategoryService.updateByBo(bo)); - } - - /** - * 删除流程分类 - * - * @param ids 主键串 - */ - @SaCheckPermission("workflow:category:remove") - @Log(title = "流程分类", businessType = BusinessType.DELETE) - @DeleteMapping("/{ids}") - public R remove(@NotEmpty(message = "主键不能为空") - @PathVariable Long[] ids) { - return toAjax(wfCategoryService.deleteWithValidByIds(List.of(ids), true)); - } -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/WfDefinitionConfigController.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/WfDefinitionConfigController.java deleted file mode 100644 index 176aba2e4..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/WfDefinitionConfigController.java +++ /dev/null @@ -1,79 +0,0 @@ -package org.dromara.workflow.controller; - -import java.util.List; - -import lombok.RequiredArgsConstructor; -import jakarta.validation.constraints.*; -import org.dromara.workflow.domain.bo.WfDefinitionConfigBo; -import org.springframework.web.bind.annotation.*; -import org.springframework.validation.annotation.Validated; -import org.dromara.common.idempotent.annotation.RepeatSubmit; -import org.dromara.common.log.annotation.Log; -import org.dromara.common.web.core.BaseController; -import org.dromara.common.core.domain.R; -import org.dromara.common.core.validate.AddGroup; -import org.dromara.common.log.enums.BusinessType; -import org.dromara.workflow.domain.vo.WfDefinitionConfigVo; -import org.dromara.workflow.service.IWfDefinitionConfigService; - -/** - * 流程定义配置 - * - * @author may - * @date 2024-03-18 - */ -@Validated -@RequiredArgsConstructor -@RestController -@RequestMapping("/workflow/definitionConfig") -public class WfDefinitionConfigController extends BaseController { - - private final IWfDefinitionConfigService wfDefinitionConfigService; - - - /** - * 获取流程定义配置详细信息 - * - * @param definitionId 主键 - */ - @GetMapping("/getByDefId/{definitionId}") - public R getByDefId(@NotBlank(message = "流程定义ID不能为空") - @PathVariable String definitionId) { - return R.ok(wfDefinitionConfigService.getByDefId(definitionId)); - } - - /** - * 新增流程定义配置 - */ - @Log(title = "流程定义配置", businessType = BusinessType.INSERT) - @RepeatSubmit() - @PostMapping("/saveOrUpdate") - public R saveOrUpdate(@Validated(AddGroup.class) @RequestBody WfDefinitionConfigBo bo) { - return toAjax(wfDefinitionConfigService.saveOrUpdate(bo)); - } - - /** - * 删除流程定义配置 - * - * @param ids 主键串 - */ - @Log(title = "流程定义配置", businessType = BusinessType.DELETE) - @DeleteMapping("/{ids}") - public R remove(@NotEmpty(message = "主键不能为空") - @PathVariable Long[] ids) { - return toAjax(wfDefinitionConfigService.deleteByIds(List.of(ids))); - } - - /** - * 查询流程定义配置排除当前查询的流程定义 - * - * @param tableName 表名 - * @param definitionId 流程定义id - */ - @GetMapping("/getByTableNameNotDefId/{tableName}/{definitionId}") - public R> getByTableNameNotDefId(@NotBlank(message = "表名不能为空") @PathVariable String tableName, - @NotBlank(message = "流程定义ID不能为空") @PathVariable String definitionId) { - return R.ok(wfDefinitionConfigService.getByTableNameNotDefId(tableName, definitionId)); - } - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/WfFormManageController.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/WfFormManageController.java deleted file mode 100644 index 198e233b4..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/WfFormManageController.java +++ /dev/null @@ -1,114 +0,0 @@ -package org.dromara.workflow.controller; - -import java.util.List; - -import lombok.RequiredArgsConstructor; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.validation.constraints.*; -import cn.dev33.satoken.annotation.SaCheckPermission; -import org.springframework.web.bind.annotation.*; -import org.springframework.validation.annotation.Validated; -import org.dromara.common.idempotent.annotation.RepeatSubmit; -import org.dromara.common.log.annotation.Log; -import org.dromara.common.web.core.BaseController; -import org.dromara.common.mybatis.core.page.PageQuery; -import org.dromara.common.core.domain.R; -import org.dromara.common.core.validate.AddGroup; -import org.dromara.common.core.validate.EditGroup; -import org.dromara.common.log.enums.BusinessType; -import org.dromara.common.excel.utils.ExcelUtil; -import org.dromara.workflow.domain.vo.WfFormManageVo; -import org.dromara.workflow.domain.bo.WfFormManageBo; -import org.dromara.workflow.service.IWfFormManageService; -import org.dromara.common.mybatis.core.page.TableDataInfo; - -/** - * 表单管理 - * - * @author may - * @date 2024-03-29 - */ -@Validated -@RequiredArgsConstructor -@RestController -@RequestMapping("/workflow/formManage") -public class WfFormManageController extends BaseController { - - private final IWfFormManageService wfFormManageService; - - /** - * 查询表单管理列表 - */ - @SaCheckPermission("workflow:formManage:list") - @GetMapping("/list") - public TableDataInfo list(WfFormManageBo bo, PageQuery pageQuery) { - return wfFormManageService.queryPageList(bo, pageQuery); - } - - /** - * 查询表单管理列表 - */ - @SaCheckPermission("workflow:formManage:list") - @GetMapping("/list/selectList") - public R> selectList() { - return R.ok(wfFormManageService.selectList()); - } - - /** - * 导出表单管理列表 - */ - @SaCheckPermission("workflow:formManage:export") - @Log(title = "表单管理", businessType = BusinessType.EXPORT) - @PostMapping("/export") - public void export(WfFormManageBo bo, HttpServletResponse response) { - List list = wfFormManageService.queryList(bo); - ExcelUtil.exportExcel(list, "表单管理", WfFormManageVo.class, response); - } - - /** - * 获取表单管理详细信息 - * - * @param id 主键 - */ - @SaCheckPermission("workflow:formManage:query") - @GetMapping("/{id}") - public R getInfo(@NotNull(message = "主键不能为空") - @PathVariable Long id) { - return R.ok(wfFormManageService.queryById(id)); - } - - /** - * 新增表单管理 - */ - @SaCheckPermission("workflow:formManage:add") - @Log(title = "表单管理", businessType = BusinessType.INSERT) - @RepeatSubmit() - @PostMapping() - public R add(@Validated(AddGroup.class) @RequestBody WfFormManageBo bo) { - return toAjax(wfFormManageService.insertByBo(bo)); - } - - /** - * 修改表单管理 - */ - @SaCheckPermission("workflow:formManage:edit") - @Log(title = "表单管理", businessType = BusinessType.UPDATE) - @RepeatSubmit() - @PutMapping() - public R edit(@Validated(EditGroup.class) @RequestBody WfFormManageBo bo) { - return toAjax(wfFormManageService.updateByBo(bo)); - } - - /** - * 删除表单管理 - * - * @param ids 主键串 - */ - @SaCheckPermission("workflow:formManage:remove") - @Log(title = "表单管理", businessType = BusinessType.DELETE) - @DeleteMapping("/{ids}") - public R remove(@NotEmpty(message = "主键不能为空") - @PathVariable Long[] ids) { - return toAjax(wfFormManageService.deleteByIds(List.of(ids))); - } -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/ActHiProcinst.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/ActHiProcinst.java deleted file mode 100644 index e87fb9253..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/ActHiProcinst.java +++ /dev/null @@ -1,152 +0,0 @@ -package org.dromara.workflow.domain; - -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.Data; - -import java.io.Serial; -import java.io.Serializable; -import java.util.Date; - -/** - * 流程实例对象 act_hi_procinst - * - * @author may - * @date 2023-07-22 - */ -@Data -@TableName("act_hi_procinst") -public class ActHiProcinst implements Serializable { - - @Serial - private static final long serialVersionUID = 1L; - - /** - * - */ - @TableId(value = "ID_") - private String id; - - /** - * - */ - @TableField(value = "REV_") - private Long rev; - - /** - * - */ - @TableField(value = "PROC_INST_ID_") - private String procInstId; - - /** - * - */ - @TableField(value = "BUSINESS_KEY_") - private String businessKey; - - /** - * - */ - @TableField(value = "PROC_DEF_ID_") - private String procDefId; - - /** - * - */ - @TableField(value = "START_TIME_") - private Date startTime; - - /** - * - */ - @TableField(value = "END_TIME_") - private Date endTime; - - /** - * - */ - @TableField(value = "DURATION_") - private Long duration; - - /** - * - */ - @TableField(value = "START_USER_ID_") - private String startUserId; - - /** - * - */ - @TableField(value = "START_ACT_ID_") - private String startActId; - - /** - * - */ - @TableField(value = "END_ACT_ID_") - private String endActId; - - /** - * - */ - @TableField(value = "SUPER_PROCESS_INSTANCE_ID_") - private String superProcessInstanceId; - - /** - * - */ - @TableField(value = "DELETE_REASON_") - private String deleteReason; - - /** - * - */ - @TableField(value = "TENANT_ID_") - private String tenantId; - - /** - * - */ - @TableField(value = "NAME_") - private String name; - - /** - * - */ - @TableField(value = "CALLBACK_ID_") - private String callbackId; - - /** - * - */ - @TableField(value = "CALLBACK_TYPE_") - private String callbackType; - - /** - * - */ - @TableField(value = "REFERENCE_ID_") - private String referenceId; - - /** - * - */ - @TableField(value = "REFERENCE_TYPE_") - private String referenceType; - - /** - * - */ - @TableField(value = "PROPAGATED_STAGE_INST_ID_") - private String propagatedStageInstId; - - /** - * - */ - @TableField(value = "BUSINESS_STATUS_") - private String businessStatus; - - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/ActHiTaskinst.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/ActHiTaskinst.java deleted file mode 100644 index abc17b54c..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/ActHiTaskinst.java +++ /dev/null @@ -1,193 +0,0 @@ -package org.dromara.workflow.domain; - -import com.baomidou.mybatisplus.annotation.*; -import lombok.Data; - -import java.io.Serializable; -import java.util.Date; - -import java.io.Serial; - -/** - * 流程历史任务对象 act_hi_taskinst - * - * @author may - * @date 2024-03-02 - */ -@Data -@TableName("act_hi_taskinst") -public class ActHiTaskinst implements Serializable { - - @Serial - private static final long serialVersionUID = 1L; - - /** - * - */ - @TableId(value = "ID_") - private String id; - - /** - * 版本 - */ - @TableField(value = "REV_") - private Long rev; - - /** - * 流程定义id - */ - @TableField(value = "PROC_DEF_ID_") - private String procDefId; - - /** - * - */ - @TableField(value = "TASK_DEF_ID_") - private String taskDefId; - - /** - * 任务节点id - */ - @TableField(value = "TASK_DEF_KEY_") - private String taskDefKey; - - /** - * 流程实例id - */ - @TableField(value = "PROC_INST_ID_") - private String procInstId; - - /** - * 流程执行id - */ - @TableField(value = "EXECUTION_ID") - private String executionId; - - /** - * - */ - @TableField(value = "SCOPE_ID_") - private String scopeId; - - /** - * - */ - @TableField(value = "SUB_SCOPE_ID_") - private String subScopeId; - - /** - * 先用当前字段标识抄送类型 - */ - @TableField(value = "SCOPE_TYPE_") - private String scopeType; - - /** - * - */ - @TableField(value = "SCOPE_DEFINITION_ID_") - private String scopeDefinitionId; - - /** - * - */ - @TableField(value = "PROPAGATED_STAGE_INST_ID_") - private String propagatedStageInstId; - - /** - * 任务名称 - */ - @TableField(value = "NAME_") - private String name; - - /** - * 父级id - */ - @TableField(value = "PARENT_TASK_ID_") - private String parentTaskId; - - /** - * 描述 - */ - @TableField(value = "DESCRIPTION_") - private String description; - - /** - * 办理人 - */ - @TableField(value = "OWNER_") - private String owner; - - /** - * 办理人 - */ - @TableField(value = "ASSIGNEE_") - private String assignee; - - /** - * 开始事件 - */ - @TableField(value = "START_TIME_") - private Date startTime; - - /** - * 认领时间 - */ - @TableField(value = "CLAIM_TIME_") - private Date claimTime; - - /** - * 结束时间 - */ - @TableField(value = "END_TIME_") - private Date endTime; - - /** - * 持续时间 - */ - @TableField(value = "DURATION_") - private Long duration; - - /** - * 删除原因 - */ - @TableField(value = "DELETE_REASON_") - private String deleteReason; - - /** - * 优先级 - */ - @TableField(value = "PRIORITY_") - private Long priority; - - /** - * 到期时间 - */ - @TableField(value = "DUE_DATE_") - private Date dueDate; - - /** - * - */ - @TableField(value = "FORM_KEY_") - private String formKey; - - /** - * 分类 - */ - @TableField(value = "CATEGORY_") - private String category; - - /** - * 最后修改时间 - */ - @TableField(value = "LAST_UPDATED_TIME_") - private Date lastUpdatedTime; - - /** - * 租户id - */ - @TableField(value = "TENANT_ID_") - private String tenantId; - - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/WfCategory.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/FlowCategory.java similarity index 56% rename from ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/WfCategory.java rename to ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/FlowCategory.java index 94a7cf500..86ac1ac32 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/WfCategory.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/FlowCategory.java @@ -1,6 +1,7 @@ package org.dromara.workflow.domain; import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableLogic; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; import lombok.EqualsAndHashCode; @@ -16,37 +17,42 @@ import java.io.Serial; */ @Data @EqualsAndHashCode(callSuper = true) -@TableName("wf_category") -public class WfCategory extends TenantEntity { +@TableName("flow_category") +public class FlowCategory extends TenantEntity { @Serial private static final long serialVersionUID = 1L; /** - * 主键 + * 流程分类ID */ - @TableId(value = "id") - private Long id; + @TableId(value = "category_id") + private Long categoryId; /** - * 分类名称 - */ - private String categoryName; - - /** - * 分类编码 - */ - private String categoryCode; - - /** - * 父级id + * 父流程分类id */ private Long parentId; /** - * 排序 + * 祖级列表 */ - private Long sortNum; + private String ancestors; + /** + * 流程分类名称 + */ + private String categoryName; + + /** + * 显示顺序 + */ + private Long orderNum; + + /** + * 删除标志(0代表存在 1代表删除) + */ + @TableLogic + private String delFlag; } diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/WfDefinitionConfig.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/WfDefinitionConfig.java deleted file mode 100644 index 11dcaa081..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/WfDefinitionConfig.java +++ /dev/null @@ -1,56 +0,0 @@ -package org.dromara.workflow.domain; - -import org.dromara.common.mybatis.core.domain.BaseEntity; -import com.baomidou.mybatisplus.annotation.*; -import lombok.Data; -import lombok.EqualsAndHashCode; - -import java.io.Serial; - -/** - * 流程定义配置对象 wf_definition_config - * - * @author may - * @date 2024-03-18 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@TableName("wf_definition_config") -public class WfDefinitionConfig extends BaseEntity { - - @Serial - private static final long serialVersionUID = 1L; - - /** - * 主键 - */ - @TableId(value = "id") - private Long id; - - /** - * 表名 - */ - private String tableName; - - /** - * 流程定义ID - */ - private String definitionId; - - /** - * 流程KEY - */ - private String processKey; - - /** - * 流程版本 - */ - private Integer version; - - /** - * 备注 - */ - private String remark; - - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/WfFormManage.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/WfFormManage.java deleted file mode 100644 index 47f0d7a58..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/WfFormManage.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.dromara.workflow.domain; - -import org.dromara.common.tenant.core.TenantEntity; -import com.baomidou.mybatisplus.annotation.*; -import lombok.Data; -import lombok.EqualsAndHashCode; - -import java.io.Serial; - -/** - * 表单管理对象 wf_form_manage - * - * @author may - * @date 2024-03-29 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@TableName("wf_form_manage") -public class WfFormManage extends TenantEntity { - - @Serial - private static final long serialVersionUID = 1L; - - /** - * 主键 - */ - @TableId(value = "id") - private Long id; - - /** - * 表单名称 - */ - private String formName; - - /** - * 表单类型 - */ - private String formType; - - /** - * 路由地址/表单ID - */ - private String router; - - /** - * 备注 - */ - private String remark; - - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/WfNodeConfig.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/WfNodeConfig.java deleted file mode 100644 index 999425f53..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/WfNodeConfig.java +++ /dev/null @@ -1,61 +0,0 @@ -package org.dromara.workflow.domain; - -import org.dromara.common.tenant.core.TenantEntity; -import com.baomidou.mybatisplus.annotation.*; -import lombok.Data; -import lombok.EqualsAndHashCode; - -import java.io.Serial; - -/** - * 节点配置对象 wf_node_config - * - * @author may - * @date 2024-03-30 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@TableName("wf_node_config") -public class WfNodeConfig extends TenantEntity { - - @Serial - private static final long serialVersionUID = 1L; - - /** - * 主键 - */ - @TableId(value = "id") - private Long id; - - /** - * 表单id - */ - private Long formId; - - /** - * 表单类型 - */ - private String formType; - - /** - * 节点名称 - */ - private String nodeName; - - /** - * 节点id - */ - private String nodeId; - - /** - * 流程定义id - */ - private String definitionId; - - /** - * 是否为申请人节点 (0是 1否) - */ - private String applyUserTask; - - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/WfTaskBackNode.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/WfTaskBackNode.java deleted file mode 100644 index 6f5972794..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/WfTaskBackNode.java +++ /dev/null @@ -1,61 +0,0 @@ -package org.dromara.workflow.domain; - -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.Data; -import lombok.EqualsAndHashCode; -import org.dromara.common.tenant.core.TenantEntity; - -import java.io.Serial; - -/** - * 节点驳回记录 wf_task_back_node - * - * @author may - * @date 2024-03-13 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@TableName("wf_task_back_node") -public class WfTaskBackNode extends TenantEntity { - - @Serial - private static final long serialVersionUID = 1L; - - /** - * 主键 - */ - @TableId(value = "id") - private Long id; - - /** - * 实例id - */ - private String instanceId; - - /** - * 节点id - */ - private String nodeId; - - /** - * 节点名称 - */ - private String nodeName; - - /** - * 排序 - */ - private Integer orderNo; - - /** - * 节点类型 - */ - private String taskType; - - /** - * 办理人 - */ - private String assignee; - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/AddMultiBo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/AddMultiBo.java deleted file mode 100644 index 320ec64ca..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/AddMultiBo.java +++ /dev/null @@ -1,40 +0,0 @@ -package org.dromara.workflow.domain.bo; - -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotEmpty; -import lombok.Data; -import org.dromara.common.core.validate.AddGroup; - -import java.io.Serial; -import java.io.Serializable; -import java.util.List; - -/** - * 加签参数请求 - * - * @author may - */ -@Data -public class AddMultiBo implements Serializable { - - @Serial - private static final long serialVersionUID = 1L; - - /** - * 任务ID - */ - @NotBlank(message = "任务ID不能为空", groups = AddGroup.class) - private String taskId; - - /** - * 加签人员id - */ - @NotEmpty(message = "加签人员不能为空", groups = AddGroup.class) - private List assignees; - - /** - * 加签人员名称 - */ - @NotEmpty(message = "加签人员不能为空", groups = AddGroup.class) - private List assigneeNames; -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/BackProcessBo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/BackProcessBo.java index d0f436925..80b9691d9 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/BackProcessBo.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/BackProcessBo.java @@ -1,12 +1,16 @@ package org.dromara.workflow.domain.bo; import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; import lombok.Data; import org.dromara.common.core.validate.AddGroup; import java.io.Serial; import java.io.Serializable; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.Objects; /** @@ -23,8 +27,8 @@ public class BackProcessBo implements Serializable { /** * 任务ID */ - @NotBlank(message = "任务ID不能为空", groups = AddGroup.class) - private String taskId; + @NotNull(message = "任务ID不能为空", groups = AddGroup.class) + private Long taskId; /** * 消息类型 @@ -35,10 +39,28 @@ public class BackProcessBo implements Serializable { * 驳回的节点id(目前未使用,直接驳回到申请人) */ @NotBlank(message = "驳回的节点不能为空", groups = AddGroup.class) - private String targetActivityId; + private String nodeCode; /** * 办理意见 */ private String message; + + /** + * 通知 + */ + private String notice; + + /** + * 流程变量 + */ + private Map variables; + + public Map getVariables() { + if (variables == null) { + return new HashMap<>(16); + } + variables.entrySet().removeIf(entry -> Objects.isNull(entry.getValue())); + return variables; + } } diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/CompleteTaskBo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/CompleteTaskBo.java index 062390551..9fdf48478 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/CompleteTaskBo.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/CompleteTaskBo.java @@ -1,9 +1,8 @@ package org.dromara.workflow.domain.bo; -import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; import lombok.Data; import org.dromara.common.core.validate.AddGroup; -import org.dromara.workflow.domain.vo.WfCopy; import java.io.Serial; import java.io.Serializable; @@ -26,8 +25,8 @@ public class CompleteTaskBo implements Serializable { /** * 任务id */ - @NotBlank(message = "任务id不能为空", groups = {AddGroup.class}) - private String taskId; + @NotNull(message = "任务id不能为空", groups = {AddGroup.class}) + private Long taskId; /** * 附件id @@ -37,7 +36,7 @@ public class CompleteTaskBo implements Serializable { /** * 抄送人员 */ - private List wfCopyList; + private List flowCopyList; /** * 消息类型 @@ -49,11 +48,22 @@ public class CompleteTaskBo implements Serializable { */ private String message; + /** + * 消息通知 + */ + private String notice; + /** * 流程变量 */ private Map variables; + /** + * 扩展变量(此处为逗号分隔的ossId) + * @return + */ + private String ext; + public Map getVariables() { if (variables == null) { return new HashMap<>(16); diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/DelegateBo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/DelegateBo.java deleted file mode 100644 index a6846a6d6..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/DelegateBo.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.dromara.workflow.domain.bo; - -import jakarta.validation.constraints.NotBlank; -import lombok.Data; -import org.dromara.common.core.validate.AddGroup; - -import java.io.Serial; -import java.io.Serializable; - -/** - * 委派任务请求对象 - * - * @author may - */ -@Data -public class DelegateBo implements Serializable { - - @Serial - private static final long serialVersionUID = 1L; - - /** - * 委派人id - */ - @NotBlank(message = "委派人id不能为空", groups = {AddGroup.class}) - private String userId; - - /** - * 委派人名称 - */ - @NotBlank(message = "委派人名称不能为空", groups = {AddGroup.class}) - private String nickName; - - /** - * 任务id - */ - @NotBlank(message = "任务id不能为空", groups = {AddGroup.class}) - private String taskId; -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/DeleteMultiBo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/DeleteMultiBo.java deleted file mode 100644 index e533167d9..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/DeleteMultiBo.java +++ /dev/null @@ -1,52 +0,0 @@ -package org.dromara.workflow.domain.bo; - -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotEmpty; -import lombok.Data; -import org.dromara.common.core.validate.AddGroup; - -import java.io.Serial; -import java.io.Serializable; -import java.util.List; - -/** - * 减签参数请求 - * - * @author may - */ -@Data -public class DeleteMultiBo implements Serializable { - - @Serial - private static final long serialVersionUID = 1L; - - /** - * 任务ID - */ - @NotBlank(message = "任务ID不能为空", groups = AddGroup.class) - private String taskId; - - /** - * 减签人员 - */ - @NotEmpty(message = "减签人员不能为空", groups = AddGroup.class) - private List taskIds; - - /** - * 执行id - */ - @NotEmpty(message = "执行id不能为空", groups = AddGroup.class) - private List executionIds; - - /** - * 人员id - */ - @NotEmpty(message = "减签人员id不能为空", groups = AddGroup.class) - private List assigneeIds; - - /** - * 人员名称 - */ - @NotEmpty(message = "减签人员不能为空", groups = AddGroup.class) - private List assigneeNames; -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/ProcessInvalidBo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowCancelBo.java similarity index 56% rename from ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/ProcessInvalidBo.java rename to ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowCancelBo.java index 41e51c2a6..31742ea79 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/ProcessInvalidBo.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowCancelBo.java @@ -8,24 +8,24 @@ import java.io.Serial; import java.io.Serializable; /** - * 流程实例作废请求对象 + * 撤销任务请求对象 * * @author may */ @Data -public class ProcessInvalidBo implements Serializable { +public class FlowCancelBo implements Serializable { @Serial private static final long serialVersionUID = 1L; /** - * 业务id + * 任务ID */ - @NotBlank(message = "业务id不能为空", groups = {AddGroup.class}) - private String businessKey; + @NotBlank(message = "业务ID不能为空", groups = AddGroup.class) + private String businessId; /** - * 作废原因 + * 办理意见 */ - private String deleteReason; + private String message; } diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowCategoryBo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowCategoryBo.java new file mode 100644 index 000000000..fd626eb0d --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowCategoryBo.java @@ -0,0 +1,47 @@ +package org.dromara.workflow.domain.bo; + +import io.github.linpeilie.annotations.AutoMapper; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.dromara.common.core.validate.AddGroup; +import org.dromara.common.core.validate.EditGroup; +import org.dromara.common.mybatis.core.domain.BaseEntity; +import org.dromara.workflow.domain.FlowCategory; + +/** + * 流程分类业务对象 wf_category + * + * @author may + * @date 2023-06-27 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@AutoMapper(target = FlowCategory.class, reverseConvertGenerate = false) +public class FlowCategoryBo extends BaseEntity { + + /** + * 流程分类ID + */ + @NotNull(message = "流程分类ID不能为空", groups = { EditGroup.class }) + private Long categoryId; + + /** + * 父流程分类id + */ + @NotNull(message = "父流程分类id不能为空", groups = {AddGroup.class, EditGroup.class}) + private Long parentId; + + /** + * 流程分类名称 + */ + @NotBlank(message = "流程分类名称不能为空", groups = {AddGroup.class, EditGroup.class}) + private String categoryName; + + /** + * 显示顺序 + */ + private Long orderNum; + +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/WfCopy.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowCopyBo.java similarity index 77% rename from ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/WfCopy.java rename to ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowCopyBo.java index 88a5a2184..a45e52109 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/WfCopy.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowCopyBo.java @@ -1,17 +1,18 @@ -package org.dromara.workflow.domain.vo; +package org.dromara.workflow.domain.bo; import lombok.Data; import java.io.Serial; import java.io.Serializable; + /** * 抄送 * * @author may */ @Data -public class WfCopy implements Serializable { +public class FlowCopyBo implements Serializable { @Serial private static final long serialVersionUID = 1L; diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowInstanceBo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowInstanceBo.java new file mode 100644 index 000000000..fb1fe611b --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowInstanceBo.java @@ -0,0 +1,55 @@ +package org.dromara.workflow.domain.bo; + +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; +import java.util.List; + +/** + * 流程实例请求对象 + * + * @author may + */ +@Data +public class FlowInstanceBo implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 流程定义名称 + */ + private String flowName; + + /** + * 流程定义编码 + */ + private String flowCode; + + /** + * 任务发起人 + */ + private String startUserId; + + /** + * 业务id + */ + private String businessId; + + /** + * 流程分类id + */ + private String category; + + /** + * 任务名称 + */ + private String nodeName; + + /** + * 申请人Ids + */ + private List createByIds; + +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowInvalidBo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowInvalidBo.java new file mode 100644 index 000000000..297bd00d9 --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowInvalidBo.java @@ -0,0 +1,31 @@ +package org.dromara.workflow.domain.bo; + +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import org.dromara.common.core.validate.AddGroup; + +import java.io.Serial; +import java.io.Serializable; + +/** + * 作废请求对象 + * + * @author may + */ +@Data +public class FlowInvalidBo implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 流程实例id + */ + @NotNull(message = "流程实例id为空", groups = AddGroup.class) + private Long id; + + /** + * 审批意见 + */ + private String comment; +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowTaskBo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowTaskBo.java new file mode 100644 index 000000000..64dd08255 --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowTaskBo.java @@ -0,0 +1,55 @@ +package org.dromara.workflow.domain.bo; + +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; +import java.util.List; + +/** + * 任务请求对象 + * + * @author may + */ +@Data +public class FlowTaskBo implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 任务名称 + */ + private String nodeName; + + /** + * 流程定义名称 + */ + private String flowName; + + /** + * 流程定义编码 + */ + private String flowCode; + + /** + * 流程分类id + */ + private String category; + + /** + * 流程实例id + */ + private Long instanceId; + + /** + * 权限列表 + */ + private List permissionList; + + /** + * 申请人Ids + */ + private List createByIds; + +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/TerminationBo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowTerminationBo.java similarity index 66% rename from ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/TerminationBo.java rename to ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowTerminationBo.java index 8f2206e82..897fc21ee 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/TerminationBo.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowTerminationBo.java @@ -1,6 +1,6 @@ package org.dromara.workflow.domain.bo; -import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; import lombok.Data; import org.dromara.common.core.validate.AddGroup; @@ -13,7 +13,7 @@ import java.io.Serializable; * @author may */ @Data -public class TerminationBo implements Serializable { +public class FlowTerminationBo implements Serializable { @Serial private static final long serialVersionUID = 1L; @@ -21,8 +21,8 @@ public class TerminationBo implements Serializable { /** * 任务id */ - @NotBlank(message = "任务id为空", groups = AddGroup.class) - private String taskId; + @NotNull(message = "任务id为空", groups = AddGroup.class) + private Long taskId; /** * 审批意见 diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/ModelBo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/ModelBo.java deleted file mode 100644 index efe9acddb..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/ModelBo.java +++ /dev/null @@ -1,66 +0,0 @@ -package org.dromara.workflow.domain.bo; - -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.Pattern; -import lombok.Data; -import org.dromara.common.core.validate.AddGroup; -import org.dromara.common.core.validate.EditGroup; -import org.dromara.workflow.common.constant.FlowConstant; - -import java.io.Serial; -import java.io.Serializable; - -/** - * 模型请求对象 - * - * @author may - */ -@Data -public class ModelBo implements Serializable { - - @Serial - private static final long serialVersionUID = 1L; - - /** - * 模型id - */ - @NotBlank(message = "模型ID不能为空", groups = {EditGroup.class}) - private String id; - - /** - * 模型名称 - */ - @NotBlank(message = "模型名称不能为空", groups = {AddGroup.class}) - private String name; - - /** - * 模型标识key - */ - @NotBlank(message = "模型标识key不能为空", groups = {AddGroup.class}) - @Pattern(regexp = FlowConstant.MODEL_KEY_PATTERN, message = "模型标识key只能字符或者下划线开头", groups = {AddGroup.class}) - private String key; - - /** - * 模型分类 - */ - @NotBlank(message = "模型分类不能为空", groups = {AddGroup.class}) - private String categoryCode; - - /** - * 模型XML - */ - @NotBlank(message = "模型XML不能为空", groups = {AddGroup.class}) - private String xml; - - /** - * 模型SVG图片 - */ - @NotBlank(message = "模型SVG不能为空", groups = {EditGroup.class}) - private String svg; - - /** - * 备注 - */ - private String description; - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/ProcessDefinitionBo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/ProcessDefinitionBo.java deleted file mode 100644 index 2025932ba..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/ProcessDefinitionBo.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.dromara.workflow.domain.bo; - -import lombok.Data; - -import java.io.Serial; -import java.io.Serializable; - -/** - * 流程定义请求对象 - * - * @author may - */ -@Data -public class ProcessDefinitionBo implements Serializable { - - @Serial - private static final long serialVersionUID = 1L; - - /** - * 流程定义名称key - */ - private String key; - - /** - * 流程定义名称 - */ - private String name; - - /** - * 模型分类 - */ - private String categoryCode; - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/ProcessInstanceBo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/ProcessInstanceBo.java deleted file mode 100644 index 2833b3ecb..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/ProcessInstanceBo.java +++ /dev/null @@ -1,43 +0,0 @@ -package org.dromara.workflow.domain.bo; - -import lombok.Data; - -import java.io.Serial; -import java.io.Serializable; - -/** - * 流程实例请求对象 - * - * @author may - */ -@Data -public class ProcessInstanceBo implements Serializable { - - @Serial - private static final long serialVersionUID = 1L; - - /** - * 流程名称 - */ - private String name; - - /** - * 流程key - */ - private String key; - - /** - * 任务发起人 - */ - private String startUserId; - - /** - * 业务id - */ - private String businessKey; - - /** - * 模型分类 - */ - private String categoryCode; -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/StartProcessBo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/StartProcessBo.java index 7af7935e6..ea21a81e7 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/StartProcessBo.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/StartProcessBo.java @@ -26,13 +26,13 @@ public class StartProcessBo implements Serializable { * 业务唯一值id */ @NotBlank(message = "业务ID不能为空", groups = {AddGroup.class}) - private String businessKey; + private String businessId; /** - * 表名 + * 流程定义编码 */ - @NotBlank(message = "表名不能为空", groups = {AddGroup.class}) - private String tableName; + @NotBlank(message = "流程定义编码不能为空", groups = {AddGroup.class}) + private String flowCode; /** * 流程变量,前端会提交一个元素{'entity': {业务详情数据对象}} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/SysUserMultiBo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/SysUserMultiBo.java deleted file mode 100644 index e4d99e47a..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/SysUserMultiBo.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.dromara.workflow.domain.bo; - -import lombok.Data; - -import java.io.Serial; -import java.io.Serializable; - - -/** - * 用户加签查询 - * - * @author may - */ -@Data -public class SysUserMultiBo implements Serializable { - - @Serial - private static final long serialVersionUID = 1L; - - /** - * 人员名称 - */ - private String userName; - - /** - * 人员名称 - */ - private String nickName; - - /** - * 部门id - */ - private String deptId; - - /** - * 任务id - */ - private String taskId; -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/TaskBo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/TaskBo.java deleted file mode 100644 index 303747939..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/TaskBo.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.dromara.workflow.domain.bo; - -import lombok.Data; - -import java.io.Serial; -import java.io.Serializable; - -/** - * 任务请求对象 - * - * @author may - */ -@Data -public class TaskBo implements Serializable { - - @Serial - private static final long serialVersionUID = 1L; - - /** - * 任务名称 - */ - private String name; - - /** - * 流程定义名称 - */ - private String processDefinitionName; - - /** - * 流程定义key - */ - private String processDefinitionKey; -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/TaskOperationBo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/TaskOperationBo.java new file mode 100644 index 000000000..4348e310c --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/TaskOperationBo.java @@ -0,0 +1,48 @@ +package org.dromara.workflow.domain.bo; + +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import org.dromara.common.core.validate.AddGroup; +import org.dromara.common.core.validate.EditGroup; + +import java.io.Serial; +import java.io.Serializable; +import java.util.List; + + +/** + * 任务操作业务对象,用于描述任务委派、转办、加签等操作的必要参数 + * 包含了用户ID、任务ID、任务相关的消息、以及加签/减签的用户ID + * + * @author AprilWind + */ +@Data +public class TaskOperationBo implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 委派/转办人的用户ID(必填,准对委派/转办人操作) + */ + @NotNull(message = "委派/转办人id不能为空", groups = {AddGroup.class}) + private String userId; + + /** + * 加签/减签人的用户ID列表(必填,针对加签/减签操作) + */ + @NotNull(message = "加签/减签id不能为空", groups = {EditGroup.class}) + private List userIds; + + /** + * 任务ID(必填) + */ + @NotNull(message = "任务id不能为空") + private Long taskId; + + /** + * 意见或备注信息(可选) + */ + private String message; + +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/TaskUrgingBo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/TaskUrgingBo.java deleted file mode 100644 index 20856efa9..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/TaskUrgingBo.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.dromara.workflow.domain.bo; - -import lombok.Data; - -import java.io.Serial; -import java.io.Serializable; -import java.util.List; - -/** - * 任务催办 - * - * @author may - */ -@Data -public class TaskUrgingBo implements Serializable { - - @Serial - private static final long serialVersionUID = 1L; - - /** - * 流程实例id - */ - private String processInstanceId; - - /** - * 消息类型 - */ - private List messageType; - - /** - * 催办内容(为空默认系统内置信息) - */ - private String message; -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/TestLeaveBo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/TestLeaveBo.java index 877e98160..a1a4b5968 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/TestLeaveBo.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/TestLeaveBo.java @@ -53,7 +53,6 @@ public class TestLeaveBo extends BaseEntity { /** * 请假天数 */ - @NotNull(message = "请假天数不能为空", groups = {AddGroup.class, EditGroup.class}) private Integer leaveDays; /** diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/TransmitBo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/TransmitBo.java deleted file mode 100644 index 3eb6609fd..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/TransmitBo.java +++ /dev/null @@ -1,37 +0,0 @@ -package org.dromara.workflow.domain.bo; - -import jakarta.validation.constraints.NotBlank; -import lombok.Data; -import org.dromara.common.core.validate.AddGroup; - -import java.io.Serial; -import java.io.Serializable; - -/** - * 终转办务请求对象 - * - * @author may - */ -@Data -public class TransmitBo implements Serializable { - - @Serial - private static final long serialVersionUID = 1L; - - /** - * 任务id - */ - @NotBlank(message = "任务id为空", groups = AddGroup.class) - private String taskId; - - /** - * 转办人id - */ - @NotBlank(message = "转办人不能为空", groups = AddGroup.class) - private String userId; - - /** - * 审批意见 - */ - private String comment; -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/WfCategoryBo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/WfCategoryBo.java deleted file mode 100644 index 69608fda3..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/WfCategoryBo.java +++ /dev/null @@ -1,54 +0,0 @@ -package org.dromara.workflow.domain.bo; - -import io.github.linpeilie.annotations.AutoMapper; -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import lombok.Data; -import lombok.EqualsAndHashCode; -import org.dromara.common.core.validate.AddGroup; -import org.dromara.common.core.validate.EditGroup; -import org.dromara.common.mybatis.core.domain.BaseEntity; -import org.dromara.workflow.domain.WfCategory; - -/** - * 流程分类业务对象 wf_category - * - * @author may - * @date 2023-06-27 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@AutoMapper(target = WfCategory.class, reverseConvertGenerate = false) -public class WfCategoryBo extends BaseEntity { - - /** - * 主键 - */ - @NotNull(message = "主键不能为空", groups = {EditGroup.class}) - private Long id; - - /** - * 分类名称 - */ - @NotBlank(message = "分类名称不能为空", groups = {AddGroup.class, EditGroup.class}) - private String categoryName; - - /** - * 分类编码 - */ - @NotBlank(message = "分类编码不能为空", groups = {AddGroup.class, EditGroup.class}) - private String categoryCode; - - /** - * 父级id - */ - @NotNull(message = "父级id不能为空", groups = {AddGroup.class, EditGroup.class}) - private Long parentId; - - /** - * 排序 - */ - private Long sortNum; - - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/WfDefinitionConfigBo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/WfDefinitionConfigBo.java deleted file mode 100644 index fac17709a..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/WfDefinitionConfigBo.java +++ /dev/null @@ -1,59 +0,0 @@ -package org.dromara.workflow.domain.bo; - -import org.dromara.workflow.domain.WfDefinitionConfig; -import org.dromara.common.mybatis.core.domain.BaseEntity; -import org.dromara.common.core.validate.AddGroup; -import org.dromara.common.core.validate.EditGroup; -import io.github.linpeilie.annotations.AutoMapper; -import lombok.Data; -import lombok.EqualsAndHashCode; -import jakarta.validation.constraints.*; - -/** - * 流程定义配置业务对象 wf_form_definition - * - * @author may - * @date 2024-03-18 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@AutoMapper(target = WfDefinitionConfig.class, reverseConvertGenerate = false) -public class WfDefinitionConfigBo extends BaseEntity { - - /** - * 主键 - */ - @NotNull(message = "主键不能为空", groups = {EditGroup.class}) - private Long id; - - /** - * 表名 - */ - @NotBlank(message = "表名不能为空", groups = {AddGroup.class}) - private String tableName; - - /** - * 流程定义ID - */ - @NotBlank(message = "流程定义ID不能为空", groups = {AddGroup.class}) - private String definitionId; - - /** - * 流程KEY - */ - @NotBlank(message = "流程KEY不能为空", groups = {AddGroup.class}) - private String processKey; - - /** - * 流程版本 - */ - @NotNull(message = "流程版本不能为空", groups = {AddGroup.class}) - private Integer version; - - /** - * 备注 - */ - private String remark; - - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/WfFormManageBo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/WfFormManageBo.java deleted file mode 100644 index 8afc286db..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/WfFormManageBo.java +++ /dev/null @@ -1,53 +0,0 @@ -package org.dromara.workflow.domain.bo; - -import org.dromara.workflow.domain.WfFormManage; -import org.dromara.common.mybatis.core.domain.BaseEntity; -import org.dromara.common.core.validate.AddGroup; -import org.dromara.common.core.validate.EditGroup; -import io.github.linpeilie.annotations.AutoMapper; -import lombok.Data; -import lombok.EqualsAndHashCode; -import jakarta.validation.constraints.*; - -/** - * 表单管理业务对象 wf_form_manage - * - * @author may - * @date 2024-03-29 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@AutoMapper(target = WfFormManage.class, reverseConvertGenerate = false) -public class WfFormManageBo extends BaseEntity { - - /** - * 主键 - */ - @NotNull(message = "主键不能为空", groups = { EditGroup.class }) - private Long id; - - /** - * 表单名称 - */ - @NotBlank(message = "表单名称不能为空", groups = { AddGroup.class, EditGroup.class }) - private String formName; - - /** - * 表单类型 - */ - @NotBlank(message = "表单类型不能为空", groups = { AddGroup.class, EditGroup.class }) - private String formType; - /** - * 路由地址/表单ID - */ - @NotBlank(message = "路由地址/表单ID不能为空", groups = { AddGroup.class, EditGroup.class }) - private String router; - - - /** - * 备注 - */ - private String remark; - - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/WfNodeConfigBo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/WfNodeConfigBo.java deleted file mode 100644 index de518d3dd..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/WfNodeConfigBo.java +++ /dev/null @@ -1,63 +0,0 @@ -package org.dromara.workflow.domain.bo; - -import org.dromara.workflow.domain.WfNodeConfig; -import org.dromara.common.mybatis.core.domain.BaseEntity; -import org.dromara.common.core.validate.AddGroup; -import org.dromara.common.core.validate.EditGroup; -import io.github.linpeilie.annotations.AutoMapper; -import lombok.Data; -import lombok.EqualsAndHashCode; -import jakarta.validation.constraints.*; - -/** - * 节点配置业务对象 wf_node_config - * - * @author may - * @date 2024-03-30 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@AutoMapper(target = WfNodeConfig.class, reverseConvertGenerate = false) -public class WfNodeConfigBo extends BaseEntity { - - /** - * 主键 - */ - @NotNull(message = "主键不能为空", groups = {EditGroup.class}) - private Long id; - - /** - * 表单id - */ - private Long formId; - - /** - * 表单类型 - */ - private String formType; - - /** - * 节点名称 - */ - @NotBlank(message = "节点名称不能为空", groups = {AddGroup.class, EditGroup.class}) - private String nodeName; - - /** - * 节点id - */ - @NotBlank(message = "节点id不能为空", groups = {AddGroup.class, EditGroup.class}) - private String nodeId; - - /** - * 流程定义id - */ - @NotBlank(message = "流程定义id不能为空", groups = {AddGroup.class, EditGroup.class}) - private String definitionId; - - /** - * 是否为申请人节点 (0是 1否) - */ - @NotBlank(message = "是否为申请人节点不能为空", groups = {AddGroup.class, EditGroup.class}) - private String applyUserTask; - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/ActHistoryInfoVo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/ActHistoryInfoVo.java deleted file mode 100644 index e4c1142ac..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/ActHistoryInfoVo.java +++ /dev/null @@ -1,93 +0,0 @@ -package org.dromara.workflow.domain.vo; - -import lombok.Data; -import org.dromara.common.translation.annotation.Translation; -import org.dromara.common.translation.constant.TransConstant; -import org.flowable.engine.task.Attachment; - -import java.io.Serial; -import java.io.Serializable; -import java.util.Date; -import java.util.List; - -/** - * 流程审批记录视图 - * - * @author may - */ -@Data -public class ActHistoryInfoVo implements Serializable { - - @Serial - private static final long serialVersionUID = 1L; - /** - * 任务id - */ - private String id; - /** - * 节点id - */ - private String taskDefinitionKey; - /** - * 任务名称 - */ - private String name; - /** - * 流程实例id - */ - private String processInstanceId; - /** - * 版本 - */ - private Integer version; - /** - * 开始时间 - */ - private Date startTime; - /** - * 结束时间 - */ - private Date endTime; - /** - * 运行时长 - */ - private String runDuration; - /** - * 状态 - */ - private String status; - /** - * 状态 - */ - private String statusName; - /** - * 办理人id - */ - private String assignee; - - /** - * 办理人名称 - */ - @Translation(type = TransConstant.USER_ID_TO_NICKNAME, mapper = "assignee") - private String nickName; - - /** - * 办理人id - */ - private String owner; - - /** - * 审批信息id - */ - private String commentId; - - /** - * 审批信息 - */ - private String comment; - - /** - * 审批附件 - */ - private List attachmentList; -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowCategoryVo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowCategoryVo.java new file mode 100644 index 000000000..2c72143cb --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowCategoryVo.java @@ -0,0 +1,69 @@ +package org.dromara.workflow.domain.vo; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import io.github.linpeilie.annotations.AutoMapper; +import lombok.Data; +import org.dromara.common.excel.annotation.ExcelDictFormat; +import org.dromara.common.excel.convert.ExcelDictConvert; +import org.dromara.workflow.domain.FlowCategory; + +import java.io.Serial; +import java.io.Serializable; +import java.util.Date; + + +/** + * 流程分类视图对象 wf_category + * + * @author may + * @date 2023-06-27 + */ +@Data +@ExcelIgnoreUnannotated +@AutoMapper(target = FlowCategory.class) +public class FlowCategoryVo implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 流程分类ID + */ + @ExcelProperty(value = "流程分类ID") + private Long categoryId; + + /** + * 父级id + */ + private Long parentId; + + /** + * 父类别名称 + */ + private String parentName; + + /** + * 祖级列表 + */ + private String ancestors; + + /** + * 流程分类名称 + */ + @ExcelProperty(value = "流程分类名称") + private String categoryName; + + /** + * 显示顺序 + */ + @ExcelProperty(value = "显示顺序") + private Long orderNum; + + /** + * 创建时间 + */ + @ExcelProperty(value = "创建时间") + private Date createTime; + +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowDefinitionVo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowDefinitionVo.java new file mode 100644 index 000000000..aef75739a --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowDefinitionVo.java @@ -0,0 +1,104 @@ +package org.dromara.workflow.domain.vo; + +import lombok.Data; +import org.dromara.common.translation.annotation.Translation; +import org.dromara.workflow.common.constant.FlowConstant; + +import java.io.Serial; +import java.io.Serializable; +import java.util.Date; + +/** + * 流程定义视图 + * + * @author may + */ +@Data +public class FlowDefinitionVo implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + private Long id; + + /** + * 创建时间 + */ + private Date createTime; + + /** + * 更新时间 + */ + private Date updateTime; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 删除标记 + */ + private String delFlag; + + /** + * 流程定义编码 + */ + private String flowCode; + + /** + * 流程定义名称 + */ + private String flowName; + + /** + * 流程分类id + */ + private String category; + + /** + * 流程分类名称 + */ + @Translation(type = FlowConstant.CATEGORY_ID_TO_NAME, mapper = "category") + private String categoryName; + + /** + * 流程版本 + */ + private String version; + + /** + * 是否发布(0未发布 1已发布 9失效) + */ + private Integer isPublish; + + /** + * 审批表单是否自定义(Y是 N否) + */ + private String formCustom; + + /** + * 审批表单路径 + */ + private String formPath; + + /** + * 流程激活状态(0挂起 1激活) + */ + private Integer activityStatus; + + /** + * 监听器类型 + */ + private String listenerType; + + /** + * 监听器路径 + */ + private String listenerPath; + + /** + * 扩展字段,预留给业务系统使用 + */ + private String ext; +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowHisTaskVo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowHisTaskVo.java new file mode 100644 index 000000000..8776a76b8 --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowHisTaskVo.java @@ -0,0 +1,244 @@ +package org.dromara.workflow.domain.vo; + +import lombok.Data; +import org.dromara.common.core.utils.DateUtils; +import org.dromara.common.translation.annotation.Translation; +import org.dromara.common.translation.constant.TransConstant; +import org.dromara.warm.flow.core.enums.CooperateType; +import org.dromara.workflow.common.constant.FlowConstant; + +import java.io.Serial; +import java.io.Serializable; +import java.util.Date; +import java.util.List; + +/** + * 历史任务视图 + * + * @author may + */ +@Data +public class FlowHisTaskVo implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + private Long id; + + /** + * 创建时间 + */ + private Date createTime; + + /** + * 更新时间 + */ + private Date updateTime; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 删除标记 + */ + private String delFlag; + + /** + * 对应flow_definition表的id + */ + private Long definitionId; + + /** + * 流程定义名称 + */ + private String flowName; + + /** + * 流程实例表id + */ + private Long instanceId; + + /** + * 任务表id + */ + private Long taskId; + + /** + * 协作方式(1审批 2转办 3委派 4会签 5票签 6加签 7减签) + */ + private Integer cooperateType; + + /** + * 协作方式(1审批 2转办 3委派 4会签 5票签 6加签 7减签) + */ + private String cooperateTypeName; + + /** + * 业务id + */ + private String businessId; + + /** + * 开始节点编码 + */ + private String nodeCode; + + /** + * 开始节点名称 + */ + private String nodeName; + + /** + * 开始节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关) + */ + private Integer nodeType; + + /** + * 目标节点编码 + */ + private String targetNodeCode; + + /** + * 结束节点名称 + */ + private String targetNodeName; + + /** + * 审批者 + */ + private String approver; + + /** + * 审批者 + */ + @Translation(type = TransConstant.USER_ID_TO_NICKNAME, mapper = "approver") + private String approveName; + + /** + * 协作人(只有转办、会签、票签、委派) + */ + private String collaborator; + + /** + * 权限标识 permissionFlag的list形式 + */ + private List permissionList; + + /** + * 跳转类型(PASS通过 REJECT退回 NONE无动作) + */ + private String skipType; + + /** + * 流程状态 + */ + private String flowStatus; + + /** + * 任务状态 + */ + private String flowTaskStatus; + + /** + * 流程状态 + */ + private String flowStatusName; + + /** + * 审批意见 + */ + private String message; + + /** + * 业务详情 存业务类的json + */ + private String ext; + + /** + * 创建者 + */ + private String createBy; + + /** + * 申请人 + */ + @Translation(type = TransConstant.USER_ID_TO_NICKNAME, mapper = "createBy") + private String createByName; + + /** + * 流程分类id + */ + private String category; + + /** + * 流程分类名称 + */ + @Translation(type = FlowConstant.CATEGORY_ID_TO_NAME, mapper = "category") + private String categoryName; + + /** + * 审批表单是否自定义(Y是 N否) + */ + private String formCustom; + + /** + * 审批表单路径 + */ + private String formPath; + + /** + * 流程定义编码 + */ + private String flowCode; + + /** + * 流程版本号 + */ + private String version; + + /** + * 运行时长 + */ + private String runDuration; + + /** + * 设置创建时间并计算任务运行时长 + * + * @param createTime 创建时间 + */ + public void setCreateTime(Date createTime) { + this.createTime = createTime; + updateRunDuration(); + } + + /** + * 设置更新时间并计算任务运行时长 + * + * @param updateTime 更新时间 + */ + public void setUpdateTime(Date updateTime) { + this.updateTime = updateTime; + updateRunDuration(); + } + + /** + * 更新运行时长 + */ + private void updateRunDuration() { + // 如果创建时间和更新时间均不为空,计算它们之间的时长 + if (this.updateTime != null && this.createTime != null) { + this.runDuration = DateUtils.getTimeDifference(this.updateTime, this.createTime); + } + } + + /** + * 设置协作方式,并通过协作方式获取名称 + */ + public void setCooperateType(Integer cooperateType) { + this.cooperateType = cooperateType; + this.cooperateTypeName = CooperateType.getValueByKey(cooperateType); + } + +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowInstanceVo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowInstanceVo.java new file mode 100644 index 000000000..75543f419 --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowInstanceVo.java @@ -0,0 +1,137 @@ +package org.dromara.workflow.domain.vo; + +import lombok.Data; +import org.dromara.common.translation.annotation.Translation; +import org.dromara.common.translation.constant.TransConstant; +import org.dromara.workflow.common.constant.FlowConstant; + +import java.util.Date; + +/** + * 流程实例视图 + * + * @author may + */ +@Data +public class FlowInstanceVo { + + private Long id; + + /** + * 创建时间 + */ + private Date createTime; + + /** + * 更新时间 + */ + private Date updateTime; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 删除标记 + */ + private String delFlag; + + /** + * 对应flow_definition表的id + */ + private Long definitionId; + + /** + * 流程定义名称 + */ + private String flowName; + + /** + * 流程定义编码 + */ + private String flowCode; + + /** + * 业务id + */ + private String businessId; + + /** + * 节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关) + */ + private Integer nodeType; + + /** + * 流程节点编码 每个流程的nodeCode是唯一的,即definitionId+nodeCode唯一,在数据库层面做了控制 + */ + private String nodeCode; + + /** + * 流程节点名称 + */ + private String nodeName; + + /** + * 流程变量 + */ + private String variable; + + /** + * 流程状态(0待提交 1审批中 2 审批通过 3自动通过 8已完成 9已退回 10失效) + */ + private String flowStatus; + + /** + * 流程状态 + */ + private String flowStatusName; + + /** + * 流程激活状态(0挂起 1激活) + */ + private Integer activityStatus; + + /** + * 审批表单是否自定义(Y是 N否) + */ + private String formCustom; + + /** + * 审批表单路径 + */ + private String formPath; + + /** + * 扩展字段,预留给业务系统使用 + */ + private String ext; + + /** + * 流程定义版本 + */ + private String version; + + /** + * 创建者 + */ + private String createBy; + + /** + * 申请人 + */ + @Translation(type = TransConstant.USER_ID_TO_NICKNAME, mapper = "createBy") + private String createByName; + + /** + * 流程分类id + */ + private String category; + + /** + * 流程分类名称 + */ + @Translation(type = FlowConstant.CATEGORY_ID_TO_NAME, mapper = "category") + private String categoryName; + +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowTaskVo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowTaskVo.java new file mode 100644 index 000000000..3fb08d954 --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowTaskVo.java @@ -0,0 +1,176 @@ +package org.dromara.workflow.domain.vo; + +import lombok.Data; +import org.dromara.common.translation.annotation.Translation; +import org.dromara.common.translation.constant.TransConstant; +import org.dromara.warm.flow.core.entity.User; +import org.dromara.workflow.common.constant.FlowConstant; + +import java.io.Serial; +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; + +/** + * 任务视图 + * + * @author may + */ +@Data +public class FlowTaskVo implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + private Long id; + + /** + * 创建时间 + */ + private Date createTime; + + /** + * 更新时间 + */ + private Date updateTime; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 删除标记 + */ + private String delFlag; + + /** + * 对应flow_definition表的id + */ + private Long definitionId; + + /** + * 流程实例表id + */ + private Long instanceId; + + /** + * 流程定义名称 + */ + private String flowName; + + /** + * 业务id + */ + private String businessId; + + /** + * 节点编码 + */ + private String nodeCode; + + /** + * 节点名称 + */ + private String nodeName; + + /** + * 节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关) + */ + private Integer nodeType; + + /** + * 权限标识 permissionFlag的list形式 + */ + private List permissionList; + + /** + * 流程用户列表 + */ + private List userList; + + /** + * 审批表单是否自定义(Y是 N否) + */ + private String formCustom; + + /** + * 审批表单 + */ + private String formPath; + + /** + * 流程定义编码 + */ + private String flowCode; + + /** + * 流程版本号 + */ + private String version; + + /** + * 流程状态 + */ + private String flowStatus; + + /** + * 流程分类id + */ + private String category; + + /** + * 流程分类名称 + */ + @Translation(type = FlowConstant.CATEGORY_ID_TO_NAME, mapper = "category") + private String categoryName; + + /** + * 流程状态 + */ + @Translation(type = TransConstant.DICT_TYPE_TO_LABEL, mapper = "flowStatus", other = "wf_business_status") + private String flowStatusName; + + /** + * 办理人类型 + */ + private String type; + + /** + * 办理人ids + */ + private String assigneeIds; + + /** + * 办理人名称 + */ + private String assigneeNames; + + /** + * 抄送人id + */ + private String processedBy; + + /** + * 抄送人名称 + */ + @Translation(type = TransConstant.USER_ID_TO_NICKNAME, mapper = "processedBy") + private String processedByName; + + /** + * 流程签署比例值 大于0为票签,会签 + */ + private BigDecimal nodeRatio; + + /** + * 申请人id + */ + private String createBy; + + /** + * 申请人名称 + */ + @Translation(type = TransConstant.USER_ID_TO_NICKNAME, mapper = "createBy") + private String createByName; +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/VariableVo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowVariableVo.java similarity index 86% rename from ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/VariableVo.java rename to ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowVariableVo.java index 6a26c8287..b4de76e93 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/VariableVo.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowVariableVo.java @@ -11,7 +11,7 @@ import java.io.Serializable; * @author may */ @Data -public class VariableVo implements Serializable { +public class FlowVariableVo implements Serializable { @Serial private static final long serialVersionUID = 1L; diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/GraphicInfoVo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/GraphicInfoVo.java deleted file mode 100644 index 763613165..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/GraphicInfoVo.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.dromara.workflow.domain.vo; - -import lombok.Data; - -import java.io.Serial; -import java.io.Serializable; - -/** - * 节点图形信息 - * - * @author may - */ -@Data -public class GraphicInfoVo implements Serializable { - - @Serial - private static final long serialVersionUID = 1L; - /** - * x坐标 - */ - private double x; - - /** - * y坐标 - */ - private double y; - - /** - * 节点高度 - */ - private double height; - - /** - * 节点宽度 - */ - private double width; - - /** - * 节点id - */ - private String nodeId; - - /** - * 节点名称 - */ - private String nodeName; -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/ModelVo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/ModelVo.java deleted file mode 100644 index b2ce81108..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/ModelVo.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.dromara.workflow.domain.vo; - -import lombok.Data; - -import java.io.Serial; -import java.io.Serializable; - -/** - * 模型视图对象 - * - * @author may - */ -@Data -public class ModelVo implements Serializable { - - @Serial - private static final long serialVersionUID = 1L; - - /** - * 模型id - */ - private String id; - - /** - * 模型名称 - */ - private String name; - - /** - * 模型标识key - */ - private String key; - - /** - * 模型分类 - */ - private String categoryCode; - - /** - * 模型XML - */ - private String xml; - - /** - * 备注 - */ - private String description; -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/MultiInstanceVo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/MultiInstanceVo.java deleted file mode 100644 index b99839603..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/MultiInstanceVo.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.dromara.workflow.domain.vo; - -import lombok.Data; - -import java.io.Serial; -import java.io.Serializable; - -/** - * 多实例信息 - * - * @author may - */ -@Data -public class MultiInstanceVo implements Serializable { - - @Serial - private static final long serialVersionUID = 1L; - - /** - * 会签类型(串行,并行) - */ - private Object type; - - /** - * 会签人员KEY - */ - private String assignee; - - /** - * 会签人员集合KEY - */ - private String assigneeList; -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/ParticipantVo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/ParticipantVo.java deleted file mode 100644 index c5876f689..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/ParticipantVo.java +++ /dev/null @@ -1,43 +0,0 @@ -package org.dromara.workflow.domain.vo; - -import lombok.Data; - -import java.io.Serial; -import java.io.Serializable; -import java.util.List; - -/** - * 参与者 - * - * @author may - */ -@Data -public class ParticipantVo implements Serializable { - - @Serial - private static final long serialVersionUID = 1L; - - /** - * 组id(角色id) - */ - private List groupIds; - - /** - * 候选人id(用户id) 当组id不为空时,将组内人员查出放入candidate - */ - private List candidate; - - /** - * 候选人名称(用户名称) 当组id不为空时,将组内人员查出放入candidateName - */ - private List candidateName; - - /** - * 是否认领标识 - * 当为空时默认当前任务不需要认领 - * 当为true时当前任务说明为候选模式并且有人已经认领了任务可以归还, - * 当为false时当前任务说明为候选模式该任务未认领, - */ - private Boolean claim; - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/ProcessDefinitionVo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/ProcessDefinitionVo.java deleted file mode 100644 index 034adbb26..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/ProcessDefinitionVo.java +++ /dev/null @@ -1,70 +0,0 @@ -package org.dromara.workflow.domain.vo; - -import lombok.Data; - -import java.io.Serial; -import java.io.Serializable; -import java.util.Date; - -/** - * 流程定义视图 - * - * @author may - */ -@Data -public class ProcessDefinitionVo implements Serializable { - - @Serial - private static final long serialVersionUID = 1L; - - /** - * 流程定义id - */ - private String id; - - /** - * 流程定义名称 - */ - private String name; - - /** - * 流程定义标识key - */ - private String key; - - /** - * 流程定义版本 - */ - private int version; - - /** - * 流程定义挂起或激活 1激活 2挂起 - */ - private int suspensionState; - - /** - * 流程xml名称 - */ - private String resourceName; - - /** - * 流程图片名称 - */ - private String diagramResourceName; - - /** - * 流程部署id - */ - private String deploymentId; - - /** - * 流程部署时间 - */ - private Date deploymentTime; - - /** - * 流程定义配置 - */ - private WfDefinitionConfigVo wfDefinitionConfigVo; - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/ProcessInstanceVo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/ProcessInstanceVo.java deleted file mode 100644 index ab3e7a130..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/ProcessInstanceVo.java +++ /dev/null @@ -1,100 +0,0 @@ -package org.dromara.workflow.domain.vo; - -import lombok.Data; - -import java.io.Serial; -import java.io.Serializable; -import java.util.Date; -import java.util.List; - -/** - * 流程实例视图 - * - * @author may - */ -@Data -public class ProcessInstanceVo implements Serializable { - - @Serial - private static final long serialVersionUID = 1L; - - /** - * 流程实例id - */ - private String id; - - /** - * 流程定义id - */ - private String processDefinitionId; - - /** - * 流程定义名称 - */ - private String processDefinitionName; - - /** - * 流程定义key - */ - private String processDefinitionKey; - - /** - * 流程定义版本 - */ - private Integer processDefinitionVersion; - - /** - * 部署id - */ - private String deploymentId; - - /** - * 业务id - */ - private String businessKey; - - /** - * 是否挂起 - */ - private Boolean isSuspended; - - /** - * 租户id - */ - private String tenantId; - - /** - * 启动时间 - */ - private Date startTime; - - /** - * 结束时间 - */ - private Date endTime; - - /** - * 启动人id - */ - private String startUserId; - - /** - * 流程状态 - */ - private String businessStatus; - - /** - * 流程状态 - */ - private String businessStatusName; - - /** - * 待办任务集合 - */ - private List taskVoList; - - /** - * 节点配置 - */ - private WfNodeConfigVo wfNodeConfigVo; -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/TaskVo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/TaskVo.java deleted file mode 100644 index 466e77690..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/TaskVo.java +++ /dev/null @@ -1,173 +0,0 @@ -package org.dromara.workflow.domain.vo; - -import lombok.Data; -import org.dromara.common.translation.annotation.Translation; -import org.dromara.common.translation.constant.TransConstant; - -import java.io.Serial; -import java.io.Serializable; -import java.util.Date; - -/** - * 任务视图 - * - * @author may - */ -@Data -public class TaskVo implements Serializable { - - @Serial - private static final long serialVersionUID = 1L; - - /** - * 任务id - */ - private String id; - - /** - * 任务名称 - */ - private String name; - - /** - * 描述 - */ - private String description; - - /** - * 优先级 - */ - private Integer priority; - - /** - * 负责此任务的人员的用户id - */ - private String owner; - - /** - * 办理人id - */ - private Long assignee; - - /** - * 办理人 - */ - @Translation(type = TransConstant.USER_ID_TO_NICKNAME, mapper = "assignee") - private String assigneeName; - - - /** - * 流程实例id - */ - private String processInstanceId; - - /** - * 执行id - */ - private String executionId; - - /** - * 无用 - */ - private String taskDefinitionId; - - /** - * 流程定义id - */ - private String processDefinitionId; - - /** - * 创建时间 - */ - private Date createTime; - - /** - * 已办任务-创建时间 - */ - private Date startTime; - - /** - * 结束时间 - */ - private Date endTime; - - /** - * 节点id - */ - private String taskDefinitionKey; - - /** - * 任务截止日期 - */ - private Date dueDate; - - /** - * 流程类别 - */ - private String category; - - /** - * 父级任务id - */ - private String parentTaskId; - - /** - * 租户id - */ - private String tenantId; - - /** - * 认领时间 - */ - private Date claimTime; - - /** - * 流程状态 - */ - private String businessStatus; - - /** - * 流程状态 - */ - private String businessStatusName; - - /** - * 流程定义名称 - */ - private String processDefinitionName; - - /** - * 流程定义key - */ - private String processDefinitionKey; - - /** - * 流程定义版本 - */ - private Integer processDefinitionVersion; - - /** - * 参与者 - */ - private ParticipantVo participantVo; - - /** - * 是否会签 - */ - private Boolean multiInstance; - - /** - * 业务id - */ - private String businessKey; - - /** - * 流程定义配置 - */ - private WfDefinitionConfigVo wfDefinitionConfigVo; - - /** - * 节点配置 - */ - private WfNodeConfigVo wfNodeConfigVo; -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/WfCategoryVo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/WfCategoryVo.java deleted file mode 100644 index 362f64625..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/WfCategoryVo.java +++ /dev/null @@ -1,58 +0,0 @@ -package org.dromara.workflow.domain.vo; - -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; -import io.github.linpeilie.annotations.AutoMapper; -import lombok.Data; -import org.dromara.workflow.domain.WfCategory; - -import java.io.Serial; -import java.io.Serializable; - - -/** - * 流程分类视图对象 wf_category - * - * @author may - * @date 2023-06-27 - */ -@Data -@ExcelIgnoreUnannotated -@AutoMapper(target = WfCategory.class) -public class WfCategoryVo implements Serializable { - - @Serial - private static final long serialVersionUID = 1L; - - /** - * 主键 - */ - @ExcelProperty(value = "主键") - private Long id; - - /** - * 分类名称 - */ - @ExcelProperty(value = "分类名称") - private String categoryName; - - /** - * 分类编码 - */ - @ExcelProperty(value = "分类编码") - private String categoryCode; - - /** - * 父级id - */ - @ExcelProperty(value = "父级id") - private Long parentId; - - /** - * 排序 - */ - @ExcelProperty(value = "排序") - private Long sortNum; - - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/WfDefinitionConfigVo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/WfDefinitionConfigVo.java deleted file mode 100644 index 9c7b0d7db..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/WfDefinitionConfigVo.java +++ /dev/null @@ -1,70 +0,0 @@ -package org.dromara.workflow.domain.vo; - -import org.dromara.workflow.domain.WfDefinitionConfig; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; -import io.github.linpeilie.annotations.AutoMapper; -import lombok.Data; - -import java.io.Serial; -import java.io.Serializable; - - -/** - * 流程定义配置视图对象 wf_definition_config - * - * @author may - * @date 2024-03-18 - */ -@Data -@ExcelIgnoreUnannotated -@AutoMapper(target = WfDefinitionConfig.class) -public class WfDefinitionConfigVo implements Serializable { - - @Serial - private static final long serialVersionUID = 1L; - - /** - * 主键 - */ - @ExcelProperty(value = "主键") - private Long id; - - /** - * 表名 - */ - @ExcelProperty(value = "表名") - private String tableName; - - /** - * 流程定义ID - */ - @ExcelProperty(value = "流程定义ID") - private String definitionId; - - /** - * 流程KEY - */ - @ExcelProperty(value = "流程KEY") - private String processKey; - - - /** - * 流程版本 - */ - @ExcelProperty(value = "流程版本") - private Integer version; - - /** - * 备注 - */ - @ExcelProperty(value = "备注") - private String remark; - - /** - * 表单管理 - */ - private WfFormManageVo wfFormManageVo; - - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/WfFormManageVo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/WfFormManageVo.java deleted file mode 100644 index 302df2396..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/WfFormManageVo.java +++ /dev/null @@ -1,63 +0,0 @@ -package org.dromara.workflow.domain.vo; - -import org.dromara.workflow.domain.WfFormManage; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; -import io.github.linpeilie.annotations.AutoMapper; -import lombok.Data; - -import java.io.Serial; -import java.io.Serializable; - - -/** - * 表单管理视图对象 wf_form_manage - * - * @author may - * @date 2024-03-29 - */ -@Data -@ExcelIgnoreUnannotated -@AutoMapper(target = WfFormManage.class) -public class WfFormManageVo implements Serializable { - - @Serial - private static final long serialVersionUID = 1L; - - /** - * 主键 - */ - @ExcelProperty(value = "主键") - private Long id; - - /** - * 表单名称 - */ - @ExcelProperty(value = "表单名称") - private String formName; - - /** - * 表单类型 - */ - @ExcelProperty(value = "表单类型") - private String formType; - - /** - * 表单类型名称 - */ - private String formTypeName; - - /** - * 路由地址/表单ID - */ - @ExcelProperty(value = "路由地址/表单ID") - private String router; - - /** - * 备注 - */ - @ExcelProperty(value = "备注") - private String remark; - - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/WfNodeConfigVo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/WfNodeConfigVo.java deleted file mode 100644 index 89e9d9b3f..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/WfNodeConfigVo.java +++ /dev/null @@ -1,75 +0,0 @@ -package org.dromara.workflow.domain.vo; - -import org.dromara.workflow.domain.WfNodeConfig; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; -import io.github.linpeilie.annotations.AutoMapper; -import lombok.Data; - -import java.io.Serial; -import java.io.Serializable; - - -/** - * 节点配置视图对象 wf_node_config - * - * @author may - * @date 2024-03-30 - */ -@Data -@ExcelIgnoreUnannotated -@AutoMapper(target = WfNodeConfig.class) -public class WfNodeConfigVo implements Serializable { - - @Serial - private static final long serialVersionUID = 1L; - - /** - * 主键 - */ - @ExcelProperty(value = "主键") - private Long id; - - /** - * 表单id - */ - @ExcelProperty(value = "表单id") - private Long formId; - - /** - * 表单类型 - */ - @ExcelProperty(value = "表单类型") - private String formType; - - /** - * 节点名称 - */ - @ExcelProperty(value = "节点名称") - private String nodeName; - - /** - * 节点id - */ - @ExcelProperty(value = "节点id") - private String nodeId; - - /** - * 流程定义id - */ - @ExcelProperty(value = "流程定义id") - private String definitionId; - - /** - * 是否为申请人节点 (0是 1否) - */ - @ExcelProperty(value = "是否为申请人节点 (0是 1否)") - private String applyUserTask; - - /** - * 表单管理 - */ - private WfFormManageVo wfFormManageVo; - - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/CustomDefaultProcessDiagramCanvas.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/CustomDefaultProcessDiagramCanvas.java deleted file mode 100644 index 39fd9d363..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/CustomDefaultProcessDiagramCanvas.java +++ /dev/null @@ -1,108 +0,0 @@ -package org.dromara.workflow.flowable; - -import org.flowable.bpmn.model.AssociationDirection; -import org.flowable.image.impl.DefaultProcessDiagramCanvas; - -import java.awt.*; -import java.awt.geom.Line2D; -import java.awt.geom.RoundRectangle2D; - -public class CustomDefaultProcessDiagramCanvas extends DefaultProcessDiagramCanvas { - //设置高亮线的颜色 这里我设置成绿色 - protected static Color HIGHLIGHT_SEQUENCEFLOW_COLOR = Color.GREEN; - - public CustomDefaultProcessDiagramCanvas(int width, int height, int minX, int minY, String imageType, String activityFontName, String labelFontName, String annotationFontName, ClassLoader customClassLoader) { - super(width, height, minX, minY, imageType, activityFontName, labelFontName, annotationFontName, customClassLoader); - } - - /** - * 画线颜色设置 - */ - public void drawConnection(int[] xPoints, int[] yPoints, boolean conditional, boolean isDefault, String connectionType, - AssociationDirection associationDirection, boolean highLighted, double scaleFactor) { - - Paint originalPaint = g.getPaint(); - Stroke originalStroke = g.getStroke(); - - g.setPaint(CONNECTION_COLOR); - if (connectionType.equals("association")) { - g.setStroke(ASSOCIATION_STROKE); - } else if (highLighted) { - //设置线的颜色 - g.setPaint(HIGHLIGHT_SEQUENCEFLOW_COLOR); - g.setStroke(HIGHLIGHT_FLOW_STROKE); - } - - for (int i = 1; i < xPoints.length; i++) { - Integer sourceX = xPoints[i - 1]; - Integer sourceY = yPoints[i - 1]; - Integer targetX = xPoints[i]; - Integer targetY = yPoints[i]; - Line2D.Double line = new Line2D.Double(sourceX, sourceY, targetX, targetY); - g.draw(line); - } - - if (isDefault) { - Line2D.Double line = new Line2D.Double(xPoints[0], yPoints[0], xPoints[1], yPoints[1]); - drawDefaultSequenceFlowIndicator(line, scaleFactor); - } - - if (conditional) { - Line2D.Double line = new Line2D.Double(xPoints[0], yPoints[0], xPoints[1], yPoints[1]); - drawConditionalSequenceFlowIndicator(line, scaleFactor); - } - - if (associationDirection == AssociationDirection.ONE || associationDirection == AssociationDirection.BOTH) { - Line2D.Double line = new Line2D.Double(xPoints[xPoints.length - 2], yPoints[xPoints.length - 2], xPoints[xPoints.length - 1], yPoints[xPoints.length - 1]); - drawArrowHead(line, scaleFactor); - } - if (associationDirection == AssociationDirection.BOTH) { - Line2D.Double line = new Line2D.Double(xPoints[1], yPoints[1], xPoints[0], yPoints[0]); - drawArrowHead(line, scaleFactor); - } - g.setPaint(originalPaint); - g.setStroke(originalStroke); - } - - /** - * 高亮节点设置 - */ - public void drawHighLight(int x, int y, int width, int height) { - Paint originalPaint = g.getPaint(); - Stroke originalStroke = g.getStroke(); - //设置高亮节点的颜色 - g.setPaint(HIGHLIGHT_COLOR); - g.setStroke(THICK_TASK_BORDER_STROKE); - - RoundRectangle2D rect = new RoundRectangle2D.Double(x, y, width, height, 20, 20); - g.draw(rect); - - g.setPaint(originalPaint); - g.setStroke(originalStroke); - } - - /** - * @description: 高亮节点红色 - * @param: x - * @param: y - * @param: width - * @param: height - * @return: void - * @author: gssong - * @date: 2022/4/12 - */ - public void drawHighLightRed(int x, int y, int width, int height) { - Paint originalPaint = g.getPaint(); - Stroke originalStroke = g.getStroke(); - //设置高亮节点的颜色 - g.setPaint(Color.green); - g.setStroke(THICK_TASK_BORDER_STROKE); - - RoundRectangle2D rect = new RoundRectangle2D.Double(x, y, width, height, 20, 20); - g.draw(rect); - - g.setPaint(originalPaint); - g.setStroke(originalStroke); - } - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/CustomDefaultProcessDiagramGenerator.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/CustomDefaultProcessDiagramGenerator.java deleted file mode 100644 index e4793a26f..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/CustomDefaultProcessDiagramGenerator.java +++ /dev/null @@ -1,1120 +0,0 @@ -/* Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.dromara.workflow.flowable; - -import org.flowable.bpmn.model.Event; -import org.flowable.bpmn.model.Process; -import org.flowable.bpmn.model.*; -import org.flowable.image.ProcessDiagramGenerator; - -import java.awt.*; -import java.awt.image.BufferedImage; -import java.io.InputStream; -import java.util.List; -import java.util.*; - -/** - * Class to generate an image based the diagram interchange information in a BPMN 2.0 process. - * - * @author Joram Barrez - * @author Tijs Rademakers - * @author Zheng Ji - */ -public class CustomDefaultProcessDiagramGenerator implements ProcessDiagramGenerator { - - protected Map, ActivityDrawInstruction> activityDrawInstructions = new HashMap<>(); - protected Map, ArtifactDrawInstruction> artifactDrawInstructions = new HashMap<>(); - - public CustomDefaultProcessDiagramGenerator() { - this(1.0); - } - - // The instructions on how to draw a certain construct is - // created statically and stored in a map for performance. - public CustomDefaultProcessDiagramGenerator(final double scaleFactor) { - // start event - activityDrawInstructions.put(StartEvent.class, new ActivityDrawInstruction() { - - @Override - public void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId()); - StartEvent startEvent = (StartEvent) flowNode; - if (startEvent.getEventDefinitions() != null && !startEvent.getEventDefinitions().isEmpty()) { - EventDefinition eventDefinition = startEvent.getEventDefinitions().get(0); - if (eventDefinition instanceof TimerEventDefinition) { - processDiagramCanvas.drawTimerStartEvent(graphicInfo, scaleFactor); - } else if (eventDefinition instanceof ErrorEventDefinition) { - processDiagramCanvas.drawErrorStartEvent(graphicInfo, scaleFactor); - } else if (eventDefinition instanceof EscalationEventDefinition) { - processDiagramCanvas.drawEscalationStartEvent(graphicInfo, scaleFactor); - } else if (eventDefinition instanceof ConditionalEventDefinition) { - processDiagramCanvas.drawConditionalStartEvent(graphicInfo, scaleFactor); - } else if (eventDefinition instanceof SignalEventDefinition) { - processDiagramCanvas.drawSignalStartEvent(graphicInfo, scaleFactor); - } else if (eventDefinition instanceof MessageEventDefinition) { - processDiagramCanvas.drawMessageStartEvent(graphicInfo, scaleFactor); - } else { - processDiagramCanvas.drawNoneStartEvent(graphicInfo); - } - } else { - List eventTypeElements = startEvent.getExtensionElements().get("eventType"); - if (eventTypeElements != null && eventTypeElements.size() > 0) { - processDiagramCanvas.drawEventRegistryStartEvent(graphicInfo, scaleFactor); - - } else { - processDiagramCanvas.drawNoneStartEvent(graphicInfo); - } - } - } - }); - - // signal catch - activityDrawInstructions.put(IntermediateCatchEvent.class, new ActivityDrawInstruction() { - - @Override - public void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId()); - IntermediateCatchEvent intermediateCatchEvent = (IntermediateCatchEvent) flowNode; - if (intermediateCatchEvent.getEventDefinitions() != null && !intermediateCatchEvent.getEventDefinitions().isEmpty()) { - - if (intermediateCatchEvent.getEventDefinitions().get(0) instanceof SignalEventDefinition) { - processDiagramCanvas.drawCatchingSignalEvent(flowNode.getName(), graphicInfo, true, scaleFactor); - } else if (intermediateCatchEvent.getEventDefinitions().get(0) instanceof TimerEventDefinition) { - processDiagramCanvas.drawCatchingTimerEvent(flowNode.getName(), graphicInfo, true, scaleFactor); - } else if (intermediateCatchEvent.getEventDefinitions().get(0) instanceof MessageEventDefinition) { - processDiagramCanvas.drawCatchingMessageEvent(flowNode.getName(), graphicInfo, true, scaleFactor); - } else if (intermediateCatchEvent.getEventDefinitions().get(0) instanceof ConditionalEventDefinition) { - processDiagramCanvas.drawCatchingConditionalEvent(flowNode.getName(), graphicInfo, true, scaleFactor); - } - } - } - }); - - // signal throw - activityDrawInstructions.put(ThrowEvent.class, new ActivityDrawInstruction() { - - @Override - public void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId()); - ThrowEvent throwEvent = (ThrowEvent) flowNode; - if (throwEvent.getEventDefinitions() != null && !throwEvent.getEventDefinitions().isEmpty()) { - if (throwEvent.getEventDefinitions().get(0) instanceof SignalEventDefinition) { - processDiagramCanvas.drawThrowingSignalEvent(graphicInfo, scaleFactor); - } else if (throwEvent.getEventDefinitions().get(0) instanceof EscalationEventDefinition) { - processDiagramCanvas.drawThrowingEscalationEvent(graphicInfo, scaleFactor); - } else if (throwEvent.getEventDefinitions().get(0) instanceof CompensateEventDefinition) { - processDiagramCanvas.drawThrowingCompensateEvent(graphicInfo, scaleFactor); - } else { - processDiagramCanvas.drawThrowingNoneEvent(graphicInfo, scaleFactor); - } - } else { - processDiagramCanvas.drawThrowingNoneEvent(graphicInfo, scaleFactor); - } - } - }); - - // end event - activityDrawInstructions.put(EndEvent.class, new ActivityDrawInstruction() { - - @Override - public void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId()); - EndEvent endEvent = (EndEvent) flowNode; - if (endEvent.getEventDefinitions() != null && !endEvent.getEventDefinitions().isEmpty()) { - if (endEvent.getEventDefinitions().get(0) instanceof ErrorEventDefinition) { - processDiagramCanvas.drawErrorEndEvent(flowNode.getName(), graphicInfo, scaleFactor); - } else if (endEvent.getEventDefinitions().get(0) instanceof EscalationEventDefinition) { - processDiagramCanvas.drawEscalationEndEvent(flowNode.getName(), graphicInfo, scaleFactor); - } else { - processDiagramCanvas.drawNoneEndEvent(graphicInfo, scaleFactor); - } - } else { - processDiagramCanvas.drawNoneEndEvent(graphicInfo, scaleFactor); - } - } - }); - - // task - activityDrawInstructions.put(Task.class, new ActivityDrawInstruction() { - - @Override - public void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId()); - processDiagramCanvas.drawTask(flowNode.getName(), graphicInfo, scaleFactor); - } - }); - - // user task - activityDrawInstructions.put(UserTask.class, new ActivityDrawInstruction() { - - @Override - public void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId()); - processDiagramCanvas.drawUserTask(flowNode.getName(), graphicInfo, scaleFactor); - } - }); - - // script task - activityDrawInstructions.put(ScriptTask.class, new ActivityDrawInstruction() { - - @Override - public void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId()); - processDiagramCanvas.drawScriptTask(flowNode.getName(), graphicInfo, scaleFactor); - } - }); - - // service task - activityDrawInstructions.put(ServiceTask.class, new ActivityDrawInstruction() { - - @Override - public void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId()); - ServiceTask serviceTask = (ServiceTask) flowNode; - if ("camel".equalsIgnoreCase(serviceTask.getType())) { - processDiagramCanvas.drawCamelTask(serviceTask.getName(), graphicInfo, scaleFactor); - }else if (ServiceTask.HTTP_TASK.equalsIgnoreCase(serviceTask.getType())) { - processDiagramCanvas.drawHttpTask(serviceTask.getName(), graphicInfo, scaleFactor); - } else if (ServiceTask.DMN_TASK.equalsIgnoreCase(serviceTask.getType())) { - processDiagramCanvas.drawDMNTask(serviceTask.getName(), graphicInfo, scaleFactor); - } else if (ServiceTask.SHELL_TASK.equalsIgnoreCase(serviceTask.getType())) { - processDiagramCanvas.drawShellTask(serviceTask.getName(), graphicInfo, scaleFactor); - } else { - processDiagramCanvas.drawServiceTask(serviceTask.getName(), graphicInfo, scaleFactor); - } - } - }); - - // http service task - activityDrawInstructions.put(HttpServiceTask.class, new ActivityDrawInstruction() { - - @Override - public void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId()); - processDiagramCanvas.drawHttpTask(flowNode.getName(), graphicInfo, scaleFactor); - } - }); - - // receive task - activityDrawInstructions.put(ReceiveTask.class, new ActivityDrawInstruction() { - - @Override - public void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId()); - processDiagramCanvas.drawReceiveTask(flowNode.getName(), graphicInfo, scaleFactor); - } - }); - - // send task - activityDrawInstructions.put(SendTask.class, new ActivityDrawInstruction() { - - @Override - public void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId()); - processDiagramCanvas.drawSendTask(flowNode.getName(), graphicInfo, scaleFactor); - } - }); - - // manual task - activityDrawInstructions.put(ManualTask.class, new ActivityDrawInstruction() { - - @Override - public void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId()); - processDiagramCanvas.drawManualTask(flowNode.getName(), graphicInfo, scaleFactor); - } - }); - - // send event service task - activityDrawInstructions.put(SendEventServiceTask.class, new ActivityDrawInstruction() { - - @Override - public void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId()); - processDiagramCanvas.drawSendEventServiceTask(flowNode.getName(), graphicInfo, scaleFactor); - } - }); - - // external worker service task - activityDrawInstructions.put(ExternalWorkerServiceTask.class, new ActivityDrawInstruction() { - - @Override - public void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId()); - ServiceTask serviceTask = (ServiceTask) flowNode; - processDiagramCanvas.drawServiceTask(serviceTask.getName(), graphicInfo, scaleFactor); - } - }); - - // case service task - activityDrawInstructions.put(CaseServiceTask.class, new ActivityDrawInstruction() { - - @Override - public void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId()); - processDiagramCanvas.drawCaseServiceTask(flowNode.getName(), graphicInfo, scaleFactor); - } - }); - - // businessRuleTask task - activityDrawInstructions.put(BusinessRuleTask.class, new ActivityDrawInstruction() { - - @Override - public void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId()); - processDiagramCanvas.drawBusinessRuleTask(flowNode.getName(), graphicInfo, scaleFactor); - } - }); - - // exclusive gateway - activityDrawInstructions.put(ExclusiveGateway.class, new ActivityDrawInstruction() { - - @Override - public void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId()); - processDiagramCanvas.drawExclusiveGateway(graphicInfo, scaleFactor); - } - }); - - // inclusive gateway - activityDrawInstructions.put(InclusiveGateway.class, new ActivityDrawInstruction() { - - @Override - public void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId()); - processDiagramCanvas.drawInclusiveGateway(graphicInfo, scaleFactor); - } - }); - - // parallel gateway - activityDrawInstructions.put(ParallelGateway.class, new ActivityDrawInstruction() { - - @Override - public void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId()); - processDiagramCanvas.drawParallelGateway(graphicInfo, scaleFactor); - } - }); - - // event based gateway - activityDrawInstructions.put(EventGateway.class, new ActivityDrawInstruction() { - - @Override - public void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId()); - processDiagramCanvas.drawEventBasedGateway(graphicInfo, scaleFactor); - } - }); - - // Boundary timer - activityDrawInstructions.put(BoundaryEvent.class, new ActivityDrawInstruction() { - - @Override - public void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId()); - BoundaryEvent boundaryEvent = (BoundaryEvent) flowNode; - if (boundaryEvent.getEventDefinitions() != null && !boundaryEvent.getEventDefinitions().isEmpty()) { - EventDefinition eventDefinition = boundaryEvent.getEventDefinitions().get(0); - if (eventDefinition instanceof TimerEventDefinition) { - processDiagramCanvas.drawCatchingTimerEvent(flowNode.getName(), graphicInfo, boundaryEvent.isCancelActivity(), scaleFactor); - - } else if (eventDefinition instanceof ConditionalEventDefinition) { - processDiagramCanvas.drawCatchingConditionalEvent(graphicInfo, boundaryEvent.isCancelActivity(), scaleFactor); - - } else if (eventDefinition instanceof ErrorEventDefinition) { - processDiagramCanvas.drawCatchingErrorEvent(graphicInfo, boundaryEvent.isCancelActivity(), scaleFactor); - - } else if (eventDefinition instanceof EscalationEventDefinition) { - processDiagramCanvas.drawCatchingEscalationEvent(graphicInfo, boundaryEvent.isCancelActivity(), scaleFactor); - - } else if (eventDefinition instanceof SignalEventDefinition) { - processDiagramCanvas.drawCatchingSignalEvent(flowNode.getName(), graphicInfo, boundaryEvent.isCancelActivity(), scaleFactor); - - } else if (eventDefinition instanceof MessageEventDefinition) { - processDiagramCanvas.drawCatchingMessageEvent(flowNode.getName(), graphicInfo, boundaryEvent.isCancelActivity(), scaleFactor); - - } else if (eventDefinition instanceof CompensateEventDefinition) { - processDiagramCanvas.drawCatchingCompensateEvent(graphicInfo, boundaryEvent.isCancelActivity(), scaleFactor); - } - - } else { - List eventTypeElements = boundaryEvent.getExtensionElements().get("eventType"); - if (eventTypeElements != null && eventTypeElements.size() > 0) { - processDiagramCanvas.drawCatchingEventRegistryEvent(flowNode.getName(), graphicInfo, boundaryEvent.isCancelActivity(), scaleFactor); - } - } - } - }); - - // subprocess - activityDrawInstructions.put(SubProcess.class, new ActivityDrawInstruction() { - - @Override - public void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId()); - if (graphicInfo.getExpanded() != null && !graphicInfo.getExpanded()) { - processDiagramCanvas.drawCollapsedSubProcess(flowNode.getName(), graphicInfo, false, scaleFactor); - } else { - processDiagramCanvas.drawExpandedSubProcess(flowNode.getName(), graphicInfo, false, scaleFactor); - } - } - }); - - // transaction - activityDrawInstructions.put(Transaction.class, new ActivityDrawInstruction() { - - @Override - public void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId()); - if (graphicInfo.getExpanded() != null && !graphicInfo.getExpanded()) { - processDiagramCanvas.drawCollapsedSubProcess(flowNode.getName(), graphicInfo, false, scaleFactor); - } else { - processDiagramCanvas.drawExpandedTransaction(flowNode.getName(), graphicInfo, scaleFactor); - } - } - }); - - // Event subprocess - activityDrawInstructions.put(EventSubProcess.class, new ActivityDrawInstruction() { - - @Override - public void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId()); - if (graphicInfo.getExpanded() != null && !graphicInfo.getExpanded()) { - processDiagramCanvas.drawCollapsedSubProcess(flowNode.getName(), graphicInfo, true, scaleFactor); - } else { - processDiagramCanvas.drawExpandedSubProcess(flowNode.getName(), graphicInfo, true, scaleFactor); - } - } - }); - - // Adhoc subprocess - activityDrawInstructions.put(AdhocSubProcess.class, new ActivityDrawInstruction() { - - @Override - public void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId()); - if (graphicInfo.getExpanded() != null && !graphicInfo.getExpanded()) { - processDiagramCanvas.drawCollapsedSubProcess(flowNode.getName(), graphicInfo, false, scaleFactor); - } else { - processDiagramCanvas.drawExpandedSubProcess(flowNode.getName(), graphicInfo, false, scaleFactor); - } - } - }); - - // call activity - activityDrawInstructions.put(CallActivity.class, new ActivityDrawInstruction() { - - @Override - public void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId()); - processDiagramCanvas.drawCollapsedCallActivity(flowNode.getName(), graphicInfo, scaleFactor); - } - }); - - // text annotation - artifactDrawInstructions.put(TextAnnotation.class, new ArtifactDrawInstruction() { - - @Override - public void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, Artifact artifact) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(artifact.getId()); - TextAnnotation textAnnotation = (TextAnnotation) artifact; - processDiagramCanvas.drawTextAnnotation(textAnnotation.getText(), graphicInfo, scaleFactor); - } - }); - - // association - artifactDrawInstructions.put(Association.class, new ArtifactDrawInstruction() { - - @Override - public void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, Artifact artifact) { - Association association = (Association) artifact; - String sourceRef = association.getSourceRef(); - String targetRef = association.getTargetRef(); - - // source and target can be instance of FlowElement or Artifact - BaseElement sourceElement = bpmnModel.getFlowElement(sourceRef); - BaseElement targetElement = bpmnModel.getFlowElement(targetRef); - if (sourceElement == null) { - sourceElement = bpmnModel.getArtifact(sourceRef); - } - if (targetElement == null) { - targetElement = bpmnModel.getArtifact(targetRef); - } - List graphicInfoList = bpmnModel.getFlowLocationGraphicInfo(artifact.getId()); - graphicInfoList = connectionPerfectionizer(processDiagramCanvas, bpmnModel, sourceElement, targetElement, graphicInfoList); - int[] xPoints = new int[graphicInfoList.size()]; - int[] yPoints = new int[graphicInfoList.size()]; - for (int i = 1; i < graphicInfoList.size(); i++) { - GraphicInfo graphicInfo = graphicInfoList.get(i); - GraphicInfo previousGraphicInfo = graphicInfoList.get(i - 1); - - if (i == 1) { - xPoints[0] = (int) previousGraphicInfo.getX(); - yPoints[0] = (int) previousGraphicInfo.getY(); - } - xPoints[i] = (int) graphicInfo.getX(); - yPoints[i] = (int) graphicInfo.getY(); - } - - AssociationDirection associationDirection = association.getAssociationDirection(); - processDiagramCanvas.drawAssociation(xPoints, yPoints, associationDirection, false, scaleFactor); - } - }); - } - - @Override - public InputStream generateDiagram(BpmnModel bpmnModel, String imageType, List highLightedActivities, List highLightedFlows, - String activityFontName, String labelFontName, String annotationFontName, ClassLoader customClassLoader, double scaleFactor, boolean drawSequenceFlowNameWithNoLabelDI) { - - return generateProcessDiagram(bpmnModel, imageType, highLightedActivities, highLightedFlows, - activityFontName, labelFontName, annotationFontName, customClassLoader, scaleFactor, drawSequenceFlowNameWithNoLabelDI).generateImage(imageType); - } - - @Override - public InputStream generateDiagram(BpmnModel bpmnModel, String imageType, List highLightedActivities, List highLightedFlows, boolean drawSequenceFlowNameWithNoLabelDI) { - return generateDiagram(bpmnModel, imageType, highLightedActivities, highLightedFlows, null, null, null, null, 1.0, drawSequenceFlowNameWithNoLabelDI); - } - - @Override - public InputStream generateDiagram(BpmnModel bpmnModel, String imageType, - List highLightedActivities, List highLightedFlows, double scaleFactor, boolean drawSequenceFlowNameWithNoLabelDI) { - return generateDiagram(bpmnModel, imageType, highLightedActivities, highLightedFlows, null, null, null, null, scaleFactor, drawSequenceFlowNameWithNoLabelDI); - } - - @Override - public InputStream generateDiagram(BpmnModel bpmnModel, String imageType, List highLightedActivities, boolean drawSequenceFlowNameWithNoLabelDI) { - return generateDiagram(bpmnModel, imageType, highLightedActivities, Collections.emptyList(), drawSequenceFlowNameWithNoLabelDI); - } - - @Override - public InputStream generateDiagram(BpmnModel bpmnModel, String imageType, List highLightedActivities, double scaleFactor, boolean drawSequenceFlowNameWithNoLabelDI) { - return generateDiagram(bpmnModel, imageType, highLightedActivities, Collections.emptyList(), scaleFactor, drawSequenceFlowNameWithNoLabelDI); - } - - @Override - public InputStream generateDiagram(BpmnModel bpmnModel, String imageType, String activityFontName, - String labelFontName, String annotationFontName, ClassLoader customClassLoader, boolean drawSequenceFlowNameWithNoLabelDI) { - - return generateDiagram(bpmnModel, imageType, Collections.emptyList(), Collections.emptyList(), - activityFontName, labelFontName, annotationFontName, customClassLoader, 1.0, drawSequenceFlowNameWithNoLabelDI); - } - - @Override - public InputStream generateDiagram(BpmnModel bpmnModel, String imageType, String activityFontName, - String labelFontName, String annotationFontName, ClassLoader customClassLoader, double scaleFactor, boolean drawSequenceFlowNameWithNoLabelDI) { - - return generateDiagram(bpmnModel, imageType, Collections.emptyList(), Collections.emptyList(), - activityFontName, labelFontName, annotationFontName, customClassLoader, scaleFactor, drawSequenceFlowNameWithNoLabelDI); - } - - @Override - public InputStream generatePngDiagram(BpmnModel bpmnModel, boolean drawSequenceFlowNameWithNoLabelDI) { - return generatePngDiagram(bpmnModel, 1.0, drawSequenceFlowNameWithNoLabelDI); - } - - @Override - public InputStream generatePngDiagram(BpmnModel bpmnModel, double scaleFactor, boolean drawSequenceFlowNameWithNoLabelDI) { - return generateDiagram(bpmnModel, "png", Collections.emptyList(), Collections.emptyList(), scaleFactor, drawSequenceFlowNameWithNoLabelDI); - } - - @Override - public InputStream generateJpgDiagram(BpmnModel bpmnModel) { - return generateJpgDiagram(bpmnModel, 1.0, false); - } - - @Override - public InputStream generateJpgDiagram(BpmnModel bpmnModel, double scaleFactor, boolean drawSequenceFlowNameWithNoLabelDI) { - return generateDiagram(bpmnModel, "jpg", Collections.emptyList(), Collections.emptyList(), drawSequenceFlowNameWithNoLabelDI); - } - - public BufferedImage generateImage(BpmnModel bpmnModel, String imageType, List highLightedActivities, List highLightedFlows, - String activityFontName, String labelFontName, String annotationFontName, ClassLoader customClassLoader, double scaleFactor, boolean drawSequenceFlowNameWithNoLabelDI) { - - return generateProcessDiagram(bpmnModel, imageType, highLightedActivities, highLightedFlows, - activityFontName, labelFontName, annotationFontName, customClassLoader, scaleFactor, drawSequenceFlowNameWithNoLabelDI).generateBufferedImage(imageType); - } - - public BufferedImage generateImage(BpmnModel bpmnModel, String imageType, - List highLightedActivities, List highLightedFlows, double scaleFactor, boolean drawSequenceFlowNameWithNoLabelDI) { - - return generateImage(bpmnModel, imageType, highLightedActivities, highLightedFlows, null, null, null, null, scaleFactor, drawSequenceFlowNameWithNoLabelDI); - } - - @Override - public BufferedImage generatePngImage(BpmnModel bpmnModel, double scaleFactor) { - return generateImage(bpmnModel, "png", Collections.emptyList(), Collections.emptyList(), scaleFactor, false); - } - - protected CustomDefaultProcessDiagramCanvas generateProcessDiagram(BpmnModel bpmnModel, String imageType, - List highLightedActivities, List highLightedFlows, - String activityFontName, String labelFontName, String annotationFontName, ClassLoader customClassLoader, double scaleFactor, boolean drawSequenceFlowNameWithNoLabelDI) { - - prepareBpmnModel(bpmnModel); - - CustomDefaultProcessDiagramCanvas processDiagramCanvas = initProcessDiagramCanvas(bpmnModel, imageType, activityFontName, labelFontName, annotationFontName, customClassLoader); - - // Draw pool shape, if process is participant in collaboration - for (Pool pool : bpmnModel.getPools()) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(pool.getId()); - processDiagramCanvas.drawPoolOrLane(pool.getName(), graphicInfo, scaleFactor); - } - - // Draw lanes - for (Process process : bpmnModel.getProcesses()) { - for (Lane lane : process.getLanes()) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(lane.getId()); - processDiagramCanvas.drawPoolOrLane(lane.getName(), graphicInfo, scaleFactor); - } - } - - // Draw activities and their sequence-flows - for (Process process : bpmnModel.getProcesses()) { - for (FlowNode flowNode : process.findFlowElementsOfType(FlowNode.class)) { - if (!isPartOfCollapsedSubProcess(flowNode, bpmnModel)) { - drawActivity(processDiagramCanvas, bpmnModel, flowNode, highLightedActivities, highLightedFlows, scaleFactor, drawSequenceFlowNameWithNoLabelDI); - } - } - } - - // Draw artifacts - for (Process process : bpmnModel.getProcesses()) { - - for (Artifact artifact : process.getArtifacts()) { - drawArtifact(processDiagramCanvas, bpmnModel, artifact); - } - - List subProcesses = process.findFlowElementsOfType(SubProcess.class, true); - if (subProcesses != null) { - for (SubProcess subProcess : subProcesses) { - - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(subProcess.getId()); - if (graphicInfo != null && graphicInfo.getExpanded() != null && !graphicInfo.getExpanded()) { - continue; - } - - if (!isPartOfCollapsedSubProcess(subProcess, bpmnModel)) { - for (Artifact subProcessArtifact : subProcess.getArtifacts()) { - drawArtifact(processDiagramCanvas, bpmnModel, subProcessArtifact); - } - } - } - } - } - - return processDiagramCanvas; - } - - protected void prepareBpmnModel(BpmnModel bpmnModel) { - - // Need to make sure all elements have positive x and y. - // Check all graphicInfo and update the elements accordingly - - List allGraphicInfos = new ArrayList<>(); - if (bpmnModel.getLocationMap() != null) { - allGraphicInfos.addAll(bpmnModel.getLocationMap().values()); - } - if (bpmnModel.getLabelLocationMap() != null) { - allGraphicInfos.addAll(bpmnModel.getLabelLocationMap().values()); - } - if (bpmnModel.getFlowLocationMap() != null) { - for (List flowGraphicInfos : bpmnModel.getFlowLocationMap().values()) { - allGraphicInfos.addAll(flowGraphicInfos); - } - } - - if (allGraphicInfos.size() > 0) { - - boolean needsTranslationX = false; - boolean needsTranslationY = false; - - double lowestX = 0.0; - double lowestY = 0.0; - - // Collect lowest x and y - for (GraphicInfo graphicInfo : allGraphicInfos) { - - double x = graphicInfo.getX(); - double y = graphicInfo.getY(); - - if (x < lowestX) { - needsTranslationX = true; - lowestX = x; - } - if (y < lowestY) { - needsTranslationY = true; - lowestY = y; - } - - } - - // Update all graphicInfo objects - if (needsTranslationX || needsTranslationY) { - - double translationX = Math.abs(lowestX); - double translationY = Math.abs(lowestY); - - for (GraphicInfo graphicInfo : allGraphicInfos) { - if (needsTranslationX) { - graphicInfo.setX(graphicInfo.getX() + translationX); - } - if (needsTranslationY) { - graphicInfo.setY(graphicInfo.getY() + translationY); - } - } - } - - } - - } - - protected void drawActivity(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, - FlowNode flowNode, List highLightedActivities, List highLightedFlows, double scaleFactor, Boolean drawSequenceFlowNameWithNoLabelDI) { - - ActivityDrawInstruction drawInstruction = activityDrawInstructions.get(flowNode.getClass()); - if (drawInstruction != null) { - - drawInstruction.draw(processDiagramCanvas, bpmnModel, flowNode); - - // Gather info on the multi instance marker - boolean multiInstanceSequential = false; - boolean multiInstanceParallel = false; - boolean collapsed = false; - if (flowNode instanceof Activity) { - Activity activity = (Activity) flowNode; - MultiInstanceLoopCharacteristics multiInstanceLoopCharacteristics = activity.getLoopCharacteristics(); - if (multiInstanceLoopCharacteristics != null) { - multiInstanceSequential = multiInstanceLoopCharacteristics.isSequential(); - multiInstanceParallel = !multiInstanceSequential; - } - } - - // Gather info on the collapsed marker - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId()); - if (flowNode instanceof SubProcess) { - collapsed = graphicInfo.getExpanded() != null && !graphicInfo.getExpanded(); - } else if (flowNode instanceof CallActivity) { - collapsed = true; - } - - if (scaleFactor == 1.0) { - // Actually draw the markers - processDiagramCanvas.drawActivityMarkers((int) graphicInfo.getX(), (int) graphicInfo.getY(), (int) graphicInfo.getWidth(), (int) graphicInfo.getHeight(), - multiInstanceSequential, multiInstanceParallel, collapsed); - } - - // Draw highlighted activities - if (highLightedActivities.contains(flowNode.getId())) { - drawHighLightRed(processDiagramCanvas, bpmnModel.getGraphicInfo(flowNode.getId())); - } else if (highLightedActivities.contains(Color.RED.toString() + flowNode.getId())) { - drawHighLight(processDiagramCanvas, bpmnModel.getGraphicInfo(flowNode.getId())); - } - - } else if (flowNode instanceof Task) { - activityDrawInstructions.get(Task.class).draw(processDiagramCanvas, bpmnModel, flowNode); - - if (highLightedActivities.contains(flowNode.getId())) { - drawHighLightRed(processDiagramCanvas, bpmnModel.getGraphicInfo(flowNode.getId())); - } else if (highLightedActivities.contains(Color.RED.toString() + flowNode.getId())) { - drawHighLight(processDiagramCanvas, bpmnModel.getGraphicInfo(flowNode.getId())); - } - } - - // Outgoing transitions of activity - for (SequenceFlow sequenceFlow : flowNode.getOutgoingFlows()) { - boolean highLighted = (highLightedFlows.contains(sequenceFlow.getId())); - String defaultFlow = null; - if (flowNode instanceof Activity) { - defaultFlow = ((Activity) flowNode).getDefaultFlow(); - } else if (flowNode instanceof Gateway) { - defaultFlow = ((Gateway) flowNode).getDefaultFlow(); - } - - boolean isDefault = false; - if (defaultFlow != null && defaultFlow.equalsIgnoreCase(sequenceFlow.getId())) { - isDefault = true; - } - boolean drawConditionalIndicator = sequenceFlow.getConditionExpression() != null && sequenceFlow.getConditionExpression().trim().length() > 0 && !(flowNode instanceof Gateway); - - String sourceRef = sequenceFlow.getSourceRef(); - String targetRef = sequenceFlow.getTargetRef(); - FlowElement sourceElement = bpmnModel.getFlowElement(sourceRef); - FlowElement targetElement = bpmnModel.getFlowElement(targetRef); - List graphicInfoList = bpmnModel.getFlowLocationGraphicInfo(sequenceFlow.getId()); - if (graphicInfoList != null && graphicInfoList.size() > 0) { - graphicInfoList = connectionPerfectionizer(processDiagramCanvas, bpmnModel, sourceElement, targetElement, graphicInfoList); - int[] xPoints = new int[graphicInfoList.size()]; - int[] yPoints = new int[graphicInfoList.size()]; - - for (int i = 1; i < graphicInfoList.size(); i++) { - GraphicInfo graphicInfo = graphicInfoList.get(i); - GraphicInfo previousGraphicInfo = graphicInfoList.get(i - 1); - - if (i == 1) { - xPoints[0] = (int) previousGraphicInfo.getX(); - yPoints[0] = (int) previousGraphicInfo.getY(); - } - xPoints[i] = (int) graphicInfo.getX(); - yPoints[i] = (int) graphicInfo.getY(); - - } - - processDiagramCanvas.drawSequenceflow(xPoints, yPoints, drawConditionalIndicator, isDefault, highLighted, scaleFactor); - - // Draw sequenceflow label - GraphicInfo labelGraphicInfo = bpmnModel.getLabelGraphicInfo(sequenceFlow.getId()); - if (labelGraphicInfo != null) { - processDiagramCanvas.drawLabel(sequenceFlow.getName(), labelGraphicInfo, false); - } else { - if (drawSequenceFlowNameWithNoLabelDI) { - GraphicInfo lineCenter = getLineCenter(graphicInfoList); - processDiagramCanvas.drawLabel(sequenceFlow.getName(), lineCenter, false); - } - - } - } - } - - // Nested elements - if (flowNode instanceof FlowElementsContainer) { - for (FlowElement nestedFlowElement : ((FlowElementsContainer) flowNode).getFlowElements()) { - if (nestedFlowElement instanceof FlowNode && !isPartOfCollapsedSubProcess(nestedFlowElement, bpmnModel)) { - drawActivity(processDiagramCanvas, bpmnModel, (FlowNode) nestedFlowElement, - highLightedActivities, highLightedFlows, scaleFactor, drawSequenceFlowNameWithNoLabelDI); - } - } - } - } - - /** - * This method makes coordinates of connection flow better. - * - * @param processDiagramCanvas - * @param bpmnModel - * @param sourceElement - * @param targetElement - * @param graphicInfoList - * @return - */ - protected static List connectionPerfectionizer(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, BaseElement sourceElement, BaseElement targetElement, List graphicInfoList) { - GraphicInfo sourceGraphicInfo = bpmnModel.getGraphicInfo(sourceElement.getId()); - GraphicInfo targetGraphicInfo = bpmnModel.getGraphicInfo(targetElement.getId()); - - CustomDefaultProcessDiagramCanvas.SHAPE_TYPE sourceShapeType = getShapeType(sourceElement); - CustomDefaultProcessDiagramCanvas.SHAPE_TYPE targetShapeType = getShapeType(targetElement); - - return processDiagramCanvas.connectionPerfectionizer(sourceShapeType, targetShapeType, sourceGraphicInfo, targetGraphicInfo, graphicInfoList); - } - - /** - * This method returns shape type of base element.
- * Each element can be presented as rectangle, rhombus, or ellipse. - * - * @param baseElement - * @return CustomDefaultProcessDiagramCanvas.SHAPE_TYPE - */ - protected static CustomDefaultProcessDiagramCanvas.SHAPE_TYPE getShapeType(BaseElement baseElement) { - if (baseElement instanceof Task || baseElement instanceof Activity || baseElement instanceof TextAnnotation) { - return CustomDefaultProcessDiagramCanvas.SHAPE_TYPE.Rectangle; - } else if (baseElement instanceof Gateway) { - return CustomDefaultProcessDiagramCanvas.SHAPE_TYPE.Rhombus; - } else if (baseElement instanceof Event) { - return CustomDefaultProcessDiagramCanvas.SHAPE_TYPE.Ellipse; - } else { - // unknown source element, just do not correct coordinates - } - return null; - } - - protected static GraphicInfo getLineCenter(List graphicInfoList) { - GraphicInfo gi = new GraphicInfo(); - - int[] xPoints = new int[graphicInfoList.size()]; - int[] yPoints = new int[graphicInfoList.size()]; - - double length = 0; - double[] lengths = new double[graphicInfoList.size()]; - lengths[0] = 0; - double m; - for (int i = 1; i < graphicInfoList.size(); i++) { - GraphicInfo graphicInfo = graphicInfoList.get(i); - GraphicInfo previousGraphicInfo = graphicInfoList.get(i - 1); - - if (i == 1) { - xPoints[0] = (int) previousGraphicInfo.getX(); - yPoints[0] = (int) previousGraphicInfo.getY(); - } - xPoints[i] = (int) graphicInfo.getX(); - yPoints[i] = (int) graphicInfo.getY(); - - length += Math.sqrt( - Math.pow((int) graphicInfo.getX() - (int) previousGraphicInfo.getX(), 2) + - Math.pow((int) graphicInfo.getY() - (int) previousGraphicInfo.getY(), 2)); - lengths[i] = length; - } - m = length / 2; - int p1 = 0; - int p2 = 1; - for (int i = 1; i < lengths.length; i++) { - double len = lengths[i]; - p1 = i - 1; - p2 = i; - if (len > m) { - break; - } - } - - GraphicInfo graphicInfo1 = graphicInfoList.get(p1); - GraphicInfo graphicInfo2 = graphicInfoList.get(p2); - - double AB = (int) graphicInfo2.getX() - (int) graphicInfo1.getX(); - double OA = (int) graphicInfo2.getY() - (int) graphicInfo1.getY(); - double OB = lengths[p2] - lengths[p1]; - double ob = m - lengths[p1]; - double ab = AB * ob / OB; - double oa = OA * ob / OB; - - double mx = graphicInfo1.getX() + ab; - double my = graphicInfo1.getY() + oa; - - gi.setX(mx); - gi.setY(my); - return gi; - } - - protected void drawArtifact(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, Artifact artifact) { - - ArtifactDrawInstruction drawInstruction = artifactDrawInstructions.get(artifact.getClass()); - if (drawInstruction != null) { - drawInstruction.draw(processDiagramCanvas, bpmnModel, artifact); - } - } - - private static void drawHighLight(CustomDefaultProcessDiagramCanvas processDiagramCanvas, GraphicInfo graphicInfo) { - processDiagramCanvas.drawHighLight((int) graphicInfo.getX(), (int) graphicInfo.getY(), (int) graphicInfo.getWidth(), (int) graphicInfo.getHeight()); - - } - - private static void drawHighLightRed(CustomDefaultProcessDiagramCanvas processDiagramCanvas, GraphicInfo graphicInfo) { - processDiagramCanvas.drawHighLightRed((int) graphicInfo.getX(), (int) graphicInfo.getY(), (int) graphicInfo.getWidth(), (int) graphicInfo.getHeight()); - - } - - protected static CustomDefaultProcessDiagramCanvas initProcessDiagramCanvas(BpmnModel bpmnModel, String imageType, - String activityFontName, String labelFontName, String annotationFontName, ClassLoader customClassLoader) { - - // We need to calculate maximum values to know how big the image will be in its entirety - double minX = Double.MAX_VALUE; - double maxX = 0; - double minY = Double.MAX_VALUE; - double maxY = 0; - - for (Pool pool : bpmnModel.getPools()) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(pool.getId()); - minX = graphicInfo.getX(); - maxX = graphicInfo.getX() + graphicInfo.getWidth(); - minY = graphicInfo.getY(); - maxY = graphicInfo.getY() + graphicInfo.getHeight(); - } - - List flowNodes = gatherAllFlowNodes(bpmnModel); - for (FlowNode flowNode : flowNodes) { - - GraphicInfo flowNodeGraphicInfo = bpmnModel.getGraphicInfo(flowNode.getId()); - - // width - if (flowNodeGraphicInfo.getX() + flowNodeGraphicInfo.getWidth() > maxX) { - maxX = flowNodeGraphicInfo.getX() + flowNodeGraphicInfo.getWidth(); - } - if (flowNodeGraphicInfo.getX() < minX) { - minX = flowNodeGraphicInfo.getX(); - } - // height - if (flowNodeGraphicInfo.getY() + flowNodeGraphicInfo.getHeight() > maxY) { - maxY = flowNodeGraphicInfo.getY() + flowNodeGraphicInfo.getHeight(); - } - if (flowNodeGraphicInfo.getY() < minY) { - minY = flowNodeGraphicInfo.getY(); - } - - for (SequenceFlow sequenceFlow : flowNode.getOutgoingFlows()) { - List graphicInfoList = bpmnModel.getFlowLocationGraphicInfo(sequenceFlow.getId()); - if (graphicInfoList != null) { - for (GraphicInfo graphicInfo : graphicInfoList) { - // width - if (graphicInfo.getX() > maxX) { - maxX = graphicInfo.getX(); - } - if (graphicInfo.getX() < minX) { - minX = graphicInfo.getX(); - } - // height - if (graphicInfo.getY() > maxY) { - maxY = graphicInfo.getY(); - } - if (graphicInfo.getY() < minY) { - minY = graphicInfo.getY(); - } - } - } - } - } - - List artifacts = gatherAllArtifacts(bpmnModel); - for (Artifact artifact : artifacts) { - - GraphicInfo artifactGraphicInfo = bpmnModel.getGraphicInfo(artifact.getId()); - - if (artifactGraphicInfo != null) { - // width - if (artifactGraphicInfo.getX() + artifactGraphicInfo.getWidth() > maxX) { - maxX = artifactGraphicInfo.getX() + artifactGraphicInfo.getWidth(); - } - if (artifactGraphicInfo.getX() < minX) { - minX = artifactGraphicInfo.getX(); - } - // height - if (artifactGraphicInfo.getY() + artifactGraphicInfo.getHeight() > maxY) { - maxY = artifactGraphicInfo.getY() + artifactGraphicInfo.getHeight(); - } - if (artifactGraphicInfo.getY() < minY) { - minY = artifactGraphicInfo.getY(); - } - } - - List graphicInfoList = bpmnModel.getFlowLocationGraphicInfo(artifact.getId()); - if (graphicInfoList != null) { - for (GraphicInfo graphicInfo : graphicInfoList) { - // width - if (graphicInfo.getX() > maxX) { - maxX = graphicInfo.getX(); - } - if (graphicInfo.getX() < minX) { - minX = graphicInfo.getX(); - } - // height - if (graphicInfo.getY() > maxY) { - maxY = graphicInfo.getY(); - } - if (graphicInfo.getY() < minY) { - minY = graphicInfo.getY(); - } - } - } - } - - int nrOfLanes = 0; - for (Process process : bpmnModel.getProcesses()) { - for (Lane l : process.getLanes()) { - - nrOfLanes++; - - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(l.getId()); - // // width - if (graphicInfo.getX() + graphicInfo.getWidth() > maxX) { - maxX = graphicInfo.getX() + graphicInfo.getWidth(); - } - if (graphicInfo.getX() < minX) { - minX = graphicInfo.getX(); - } - // height - if (graphicInfo.getY() + graphicInfo.getHeight() > maxY) { - maxY = graphicInfo.getY() + graphicInfo.getHeight(); - } - if (graphicInfo.getY() < minY) { - minY = graphicInfo.getY(); - } - } - } - - // Special case, see https://activiti.atlassian.net/browse/ACT-1431 - if (flowNodes.isEmpty() && bpmnModel.getPools().isEmpty() && nrOfLanes == 0) { - // Nothing to show - minX = 0; - minY = 0; - } - - return new CustomDefaultProcessDiagramCanvas((int) maxX + 10, (int) maxY + 10, (int) minX, (int) minY, - imageType, activityFontName, labelFontName, annotationFontName, customClassLoader); - } - - protected static List gatherAllArtifacts(BpmnModel bpmnModel) { - List artifacts = new ArrayList<>(); - for (Process process : bpmnModel.getProcesses()) { - artifacts.addAll(process.getArtifacts()); - } - return artifacts; - } - - protected static List gatherAllFlowNodes(BpmnModel bpmnModel) { - List flowNodes = new ArrayList<>(); - for (Process process : bpmnModel.getProcesses()) { - flowNodes.addAll(gatherAllFlowNodes(process)); - } - return flowNodes; - } - - protected static List gatherAllFlowNodes(FlowElementsContainer flowElementsContainer) { - List flowNodes = new ArrayList<>(); - for (FlowElement flowElement : flowElementsContainer.getFlowElements()) { - if (flowElement instanceof FlowNode) { - flowNodes.add((FlowNode) flowElement); - } - if (flowElement instanceof FlowElementsContainer) { - flowNodes.addAll(gatherAllFlowNodes((FlowElementsContainer) flowElement)); - } - } - return flowNodes; - } - - protected boolean isPartOfCollapsedSubProcess(FlowElement flowElement, BpmnModel model) { - SubProcess subProcess = flowElement.getSubProcess(); - if (subProcess != null) { - GraphicInfo graphicInfo = model.getGraphicInfo(subProcess.getId()); - if (graphicInfo != null && graphicInfo.getExpanded() != null && !graphicInfo.getExpanded()) { - return true; - } - - return isPartOfCollapsedSubProcess(subProcess, model); - } - - return false; - } - - public Map, ActivityDrawInstruction> getActivityDrawInstructions() { - return activityDrawInstructions; - } - - public void setActivityDrawInstructions( - Map, ActivityDrawInstruction> activityDrawInstructions) { - this.activityDrawInstructions = activityDrawInstructions; - } - - public Map, ArtifactDrawInstruction> getArtifactDrawInstructions() { - return artifactDrawInstructions; - } - - public void setArtifactDrawInstructions( - Map, ArtifactDrawInstruction> artifactDrawInstructions) { - this.artifactDrawInstructions = artifactDrawInstructions; - } - - protected interface ActivityDrawInstruction { - void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode); - } - - protected interface ArtifactDrawInstruction { - void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, Artifact artifact); - } -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/AddSequenceMultiInstanceCmd.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/AddSequenceMultiInstanceCmd.java deleted file mode 100644 index 3cdfcf415..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/AddSequenceMultiInstanceCmd.java +++ /dev/null @@ -1,61 +0,0 @@ -package org.dromara.workflow.flowable.cmd; - -import cn.hutool.core.collection.CollUtil; -import org.flowable.common.engine.impl.interceptor.Command; -import org.flowable.common.engine.impl.interceptor.CommandContext; -import org.flowable.engine.impl.persistence.entity.ExecutionEntity; -import org.flowable.engine.impl.persistence.entity.ExecutionEntityManager; -import org.flowable.engine.impl.util.CommandContextUtil; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static org.dromara.workflow.common.constant.FlowConstant.NUMBER_OF_INSTANCES; - -/** - * 串行加签 - * - * @author may - */ -public class AddSequenceMultiInstanceCmd implements Command { - - /** - * 执行id - */ - private final String executionId; - - /** - * 会签人员集合KEY - */ - private final String assigneeList; - - /** - * 加签人员 - */ - private final List assignees; - - public AddSequenceMultiInstanceCmd(String executionId, String assigneeList, List assignees) { - this.executionId = executionId; - this.assigneeList = assigneeList; - this.assignees = assignees; - } - - @Override - public Void execute(CommandContext commandContext) { - ExecutionEntityManager executionEntityManager = CommandContextUtil.getExecutionEntityManager(); - ExecutionEntity entity = executionEntityManager.findById(executionId); - // 多实例任务总数加 assignees.size() - if (entity.getVariable(NUMBER_OF_INSTANCES) instanceof Integer nrOfInstances) { - entity.setVariable(NUMBER_OF_INSTANCES, nrOfInstances + assignees.size()); - } - // 设置流程变量 - if (entity.getVariable(assigneeList) instanceof List userIds) { - CollUtil.addAll(userIds, assignees); - Map variables = new HashMap<>(16); - variables.put(assigneeList, userIds); - entity.setVariables(variables); - } - return null; - } -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/AttachmentCmd.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/AttachmentCmd.java deleted file mode 100644 index 20a0a5f3a..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/AttachmentCmd.java +++ /dev/null @@ -1,66 +0,0 @@ -package org.dromara.workflow.flowable.cmd; - -import cn.hutool.core.collection.CollUtil; -import org.dromara.common.core.domain.dto.OssDTO; -import org.dromara.common.core.service.OssService; -import org.dromara.common.core.utils.StringUtils; -import org.dromara.common.satoken.utils.LoginHelper; -import org.flowable.common.engine.impl.interceptor.Command; -import org.flowable.common.engine.impl.interceptor.CommandContext; -import org.flowable.engine.impl.persistence.entity.AttachmentEntity; -import org.flowable.engine.impl.persistence.entity.AttachmentEntityManager; -import org.flowable.engine.impl.util.CommandContextUtil; - -import java.util.Date; -import java.util.List; - -/** - * 附件上传 - * - * @author may - */ -public class AttachmentCmd implements Command { - - private final String fileId; - - private final String taskId; - - private final String processInstanceId; - - private final OssService ossService; - - public AttachmentCmd(String fileId, String taskId, String processInstanceId, OssService ossService) { - this.fileId = fileId; - this.taskId = taskId; - this.processInstanceId = processInstanceId; - this.ossService = ossService; - } - - @Override - public Boolean execute(CommandContext commandContext) { - try { - if (StringUtils.isNotBlank(fileId)) { - List ossList = ossService.selectByIds(fileId); - if (CollUtil.isNotEmpty(ossList)) { - for (OssDTO oss : ossList) { - AttachmentEntityManager attachmentEntityManager = CommandContextUtil.getAttachmentEntityManager(); - AttachmentEntity attachmentEntity = attachmentEntityManager.create(); - attachmentEntity.setRevision(1); - attachmentEntity.setUserId(LoginHelper.getUserId().toString()); - attachmentEntity.setName(oss.getOriginalName()); - attachmentEntity.setDescription(oss.getOriginalName()); - attachmentEntity.setType(oss.getFileSuffix()); - attachmentEntity.setTaskId(taskId); - attachmentEntity.setProcessInstanceId(processInstanceId); - attachmentEntity.setContentId(oss.getOssId().toString()); - attachmentEntity.setTime(new Date()); - attachmentEntityManager.insert(attachmentEntity); - } - } - } - } catch (Exception e) { - throw new RuntimeException(e); - } - return true; - } -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/DeleteExecutionCmd.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/DeleteExecutionCmd.java deleted file mode 100644 index 215d31023..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/DeleteExecutionCmd.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.dromara.workflow.flowable.cmd; - -import org.flowable.common.engine.impl.interceptor.Command; -import org.flowable.common.engine.impl.interceptor.CommandContext; -import org.flowable.engine.impl.persistence.entity.ExecutionEntity; -import org.flowable.engine.impl.persistence.entity.ExecutionEntityManager; -import org.flowable.engine.impl.util.CommandContextUtil; - -import java.io.Serializable; - -/** - * 删除执行数据 - * - * @author may - */ -public class DeleteExecutionCmd implements Command, Serializable { - - /** - * 执行id - */ - private final String executionId; - - public DeleteExecutionCmd(String executionId) { - this.executionId = executionId; - } - - @Override - public Void execute(CommandContext commandContext) { - ExecutionEntityManager executionEntityManager = CommandContextUtil.getExecutionEntityManager(); - ExecutionEntity entity = executionEntityManager.findById(executionId); - if (entity != null) { - executionEntityManager.deleteExecutionAndRelatedData(entity, "", false, false); - } - return null; - } -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/DeleteSequenceMultiInstanceCmd.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/DeleteSequenceMultiInstanceCmd.java deleted file mode 100644 index a61daebc5..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/DeleteSequenceMultiInstanceCmd.java +++ /dev/null @@ -1,83 +0,0 @@ -package org.dromara.workflow.flowable.cmd; - -import cn.hutool.core.util.ObjectUtil; -import lombok.AllArgsConstructor; -import org.dromara.common.core.utils.StreamUtils; -import org.flowable.common.engine.impl.interceptor.Command; -import org.flowable.common.engine.impl.interceptor.CommandContext; -import org.flowable.engine.impl.persistence.entity.ExecutionEntity; -import org.flowable.engine.impl.persistence.entity.ExecutionEntityManager; -import org.flowable.engine.impl.util.CommandContextUtil; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static org.dromara.workflow.common.constant.FlowConstant.LOOP_COUNTER; -import static org.dromara.workflow.common.constant.FlowConstant.NUMBER_OF_INSTANCES; - - -/** - * 串行减签 - * - * @author may - */ -@AllArgsConstructor -public class DeleteSequenceMultiInstanceCmd implements Command { - - /** - * 当前节点审批人员id - */ - private final String currentUserId; - - /** - * 执行id - */ - private final String executionId; - - /** - * 会签人员集合KEY - */ - private final String assigneeList; - - /** - * 减签人员 - */ - private final List assignees; - - - @Override - @SuppressWarnings("unchecked") - public Void execute(CommandContext commandContext) { - ExecutionEntityManager executionEntityManager = CommandContextUtil.getExecutionEntityManager(); - ExecutionEntity entity = executionEntityManager.findById(executionId); - // 设置流程变量 - List userIds = new ArrayList<>(); - List variable = (List) entity.getVariable(assigneeList); - for (Object o : variable) { - userIds.add(Long.valueOf(o.toString())); - } - List userIdList = new ArrayList<>(); - userIds.forEach(e -> { - Long userId = StreamUtils.findFirst(assignees, id -> ObjectUtil.equals(id, e)); - if (userId == null) { - userIdList.add(e); - } - }); - // 当前任务执行位置 - int loopCounterIndex = -1; - for (int i = 0; i < userIdList.size(); i++) { - Long userId = userIdList.get(i); - if (currentUserId.equals(userId.toString())) { - loopCounterIndex = i; - } - } - Map variables = new HashMap<>(16); - variables.put(NUMBER_OF_INSTANCES, userIdList.size()); - variables.put(assigneeList, userIdList); - variables.put(LOOP_COUNTER, loopCounterIndex); - entity.setVariables(variables); - return null; - } -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/ExecutionChildByExecutionIdCmd.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/ExecutionChildByExecutionIdCmd.java deleted file mode 100644 index 1f3088bfc..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/ExecutionChildByExecutionIdCmd.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.dromara.workflow.flowable.cmd; - -import org.dromara.common.core.utils.StreamUtils; -import org.flowable.common.engine.impl.interceptor.Command; -import org.flowable.common.engine.impl.interceptor.CommandContext; -import org.flowable.engine.impl.persistence.entity.ExecutionEntity; -import org.flowable.engine.impl.persistence.entity.ExecutionEntityManager; -import org.flowable.engine.impl.util.CommandContextUtil; - -import java.io.Serializable; -import java.util.List; - -/** - * 获取并行网关执行后保留的执行实例数据 - * - * @author may - */ -public class ExecutionChildByExecutionIdCmd implements Command>, Serializable { - - /** - * 当前任务执行实例id - */ - private final String executionId; - - public ExecutionChildByExecutionIdCmd(String executionId) { - this.executionId = executionId; - } - - @Override - public List execute(CommandContext commandContext) { - ExecutionEntityManager executionEntityManager = CommandContextUtil.getExecutionEntityManager(); - // 获取当前执行数据 - ExecutionEntity executionEntity = executionEntityManager.findById(executionId); - // 通过当前执行数据的父执行,查询所有子执行数据 - List allChildrenExecution = - executionEntityManager.collectChildren(executionEntity.getParent()); - return StreamUtils.filter(allChildrenExecution, e -> !e.isActive()); - } -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/UpdateBusinessStatusCmd.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/UpdateBusinessStatusCmd.java deleted file mode 100644 index 3ba120aef..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/UpdateBusinessStatusCmd.java +++ /dev/null @@ -1,37 +0,0 @@ -package org.dromara.workflow.flowable.cmd; - -import org.dromara.common.core.exception.ServiceException; -import org.flowable.common.engine.impl.interceptor.Command; -import org.flowable.common.engine.impl.interceptor.CommandContext; -import org.flowable.engine.impl.persistence.entity.HistoricProcessInstanceEntity; -import org.flowable.engine.impl.persistence.entity.HistoricProcessInstanceEntityManager; -import org.flowable.engine.impl.util.CommandContextUtil; - -/** - * 修改流程状态 - * - * @author may - */ -public class UpdateBusinessStatusCmd implements Command { - - private final String processInstanceId; - private final String status; - - public UpdateBusinessStatusCmd(String processInstanceId, String status) { - this.processInstanceId = processInstanceId; - this.status = status; - } - - @Override - public Boolean execute(CommandContext commandContext) { - try { - HistoricProcessInstanceEntityManager manager = CommandContextUtil.getHistoricProcessInstanceEntityManager(); - HistoricProcessInstanceEntity processInstance = manager.findById(processInstanceId); - processInstance.setBusinessStatus(status); - manager.update(processInstance); - return true; - } catch (Exception e) { - throw new ServiceException(e.getMessage()); - } - } -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/UpdateHiTaskInstCmd.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/UpdateHiTaskInstCmd.java deleted file mode 100644 index 42f6d1c78..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/UpdateHiTaskInstCmd.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.dromara.workflow.flowable.cmd; - -import org.dromara.common.core.exception.ServiceException; -import org.flowable.common.engine.impl.interceptor.Command; -import org.flowable.common.engine.impl.interceptor.CommandContext; -import org.flowable.engine.impl.util.CommandContextUtil; -import org.flowable.task.service.HistoricTaskService; -import org.flowable.task.service.impl.persistence.entity.HistoricTaskInstanceEntity; - -import java.util.Date; -import java.util.List; - - -/** - * 修改流程历史 - * - * @author may - */ -public class UpdateHiTaskInstCmd implements Command { - - private final List taskIds; - - private final String processDefinitionId; - - private final String processInstanceId; - - public UpdateHiTaskInstCmd(List taskIds, String processDefinitionId, String processInstanceId) { - this.taskIds = taskIds; - this.processDefinitionId = processDefinitionId; - this.processInstanceId = processInstanceId; - } - - @Override - public Boolean execute(CommandContext commandContext) { - try { - HistoricTaskService historicTaskService = CommandContextUtil.getHistoricTaskService(); - for (String taskId : taskIds) { - HistoricTaskInstanceEntity historicTask = historicTaskService.getHistoricTask(taskId); - if (historicTask != null) { - historicTask.setProcessDefinitionId(processDefinitionId); - historicTask.setProcessInstanceId(processInstanceId); - historicTask.setCreateTime(new Date()); - CommandContextUtil.getHistoricTaskService().updateHistoricTask(historicTask, true); - } - } - return true; - } catch (Exception e) { - throw new ServiceException(e.getMessage()); - } - } -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/config/FlowableConfig.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/config/FlowableConfig.java deleted file mode 100644 index 1494bf37f..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/config/FlowableConfig.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.dromara.workflow.flowable.config; - -import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator; -import org.dromara.workflow.flowable.handler.TaskTimeoutJobHandler; -import org.flowable.spring.SpringProcessEngineConfiguration; -import org.flowable.spring.boot.EngineConfigurationConfigurer; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Configuration; - -import java.util.Collections; - - -/** - * flowable配置 - * - * @author may - */ -@Configuration -public class FlowableConfig implements EngineConfigurationConfigurer { - - @Autowired - private GlobalFlowableListener globalFlowableListener; - @Autowired - private IdentifierGenerator identifierGenerator; - - @Override - public void configure(SpringProcessEngineConfiguration processEngineConfiguration) { - processEngineConfiguration.setIdGenerator(() -> identifierGenerator.nextId(null).toString()); - processEngineConfiguration.setEventListeners(Collections.singletonList(globalFlowableListener)); - processEngineConfiguration.addCustomJobHandler(new TaskTimeoutJobHandler()); - } -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/config/GlobalFlowableListener.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/config/GlobalFlowableListener.java deleted file mode 100644 index 9bb971a8c..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/config/GlobalFlowableListener.java +++ /dev/null @@ -1,139 +0,0 @@ -package org.dromara.workflow.flowable.config; - -import cn.hutool.core.collection.CollUtil; -import org.dromara.common.core.utils.StringUtils; -import org.dromara.common.tenant.helper.TenantHelper; -import org.dromara.workflow.common.enums.TaskStatusEnum; -import org.dromara.workflow.flowable.handler.TaskTimeoutJobHandler; -import org.dromara.workflow.utils.QueryUtils; -import org.flowable.bpmn.model.BoundaryEvent; -import org.flowable.bpmn.model.BpmnModel; -import org.flowable.bpmn.model.FlowElement; -import org.flowable.common.engine.api.delegate.event.*; -import org.flowable.common.engine.impl.cfg.TransactionState; -import org.flowable.engine.RepositoryService; -import org.flowable.engine.RuntimeService; -import org.flowable.engine.TaskService; -import org.flowable.engine.impl.util.CommandContextUtil; -import org.flowable.engine.runtime.Execution; -import org.flowable.engine.task.Comment; -import org.flowable.job.service.TimerJobService; -import org.flowable.job.service.impl.persistence.entity.JobEntity; -import org.flowable.job.service.impl.persistence.entity.TimerJobEntity; -import org.flowable.task.api.Task; -import org.flowable.task.service.impl.persistence.entity.TaskEntity; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Lazy; -import org.springframework.stereotype.Component; - -import java.util.Date; -import java.util.List; - - -/** - * 引擎调度监听 - * - * @author may - */ -@Component -public class GlobalFlowableListener implements FlowableEventListener { - - @Autowired - @Lazy - private TaskService taskService; - - @Autowired - @Lazy - private RuntimeService runtimeService; - - @Autowired - @Lazy - private RepositoryService repositoryService; - - @Value("${flowable.async-executor-activate}") - private boolean asyncExecutorActivate; - - @Override - public void onEvent(FlowableEvent flowableEvent) { - if (flowableEvent instanceof FlowableEngineEvent flowableEngineEvent) { - FlowableEngineEventType engineEventType = (FlowableEngineEventType) flowableEvent.getType(); - switch (engineEventType) { - case JOB_EXECUTION_SUCCESS -> jobExecutionSuccess((FlowableEngineEntityEvent) flowableEngineEvent); - case TASK_DUEDATE_CHANGED, TASK_CREATED -> { - FlowableEntityEvent flowableEntityEvent = (FlowableEntityEvent) flowableEngineEvent; - Object entityObject = flowableEntityEvent.getEntity(); - TaskEntity task = (TaskEntity) entityObject; - if (asyncExecutorActivate && task.getDueDate() != null && task.getDueDate().after(new Date())) { - //删除之前已经存在的定时任务 - TimerJobService timerJobService = CommandContextUtil.getTimerJobService(); - List timerJobEntityList = timerJobService.findTimerJobsByProcessInstanceId(task.getProcessInstanceId()); - if (!CollUtil.isEmpty(timerJobEntityList)) { - for (TimerJobEntity timerJobEntity : timerJobEntityList) { - String taskId = timerJobEntity.getJobHandlerConfiguration(); - if (task.getId().equals(taskId)) { - timerJobService.deleteTimerJob(timerJobEntity); - } - } - } - //创建job对象 - TimerJobEntity timer = timerJobService.createTimerJob(); - timer.setTenantId(TenantHelper.getTenantId()); - //设置job类型 - timer.setJobType(JobEntity.JOB_TYPE_TIMER); - timer.setJobHandlerType(TaskTimeoutJobHandler.TYPE); - timer.setDuedate(task.getDueDate()); - timer.setProcessInstanceId(task.getProcessInstanceId()); - //设置任务id - timer.setJobHandlerConfiguration(task.getId()); - //保存并触发事件 - timerJobService.scheduleTimerJob(timer); - } - } - } - } - } - - @Override - public boolean isFailOnException() { - return true; - } - - @Override - public boolean isFireOnTransactionLifecycleEvent() { - return false; - } - - @Override - public String getOnTransaction() { - return TransactionState.COMMITTED.name(); - } - - /** - * 处理边界定时事件自动审批记录 - * - * @param event 事件 - */ - protected void jobExecutionSuccess(FlowableEngineEntityEvent event) { - if (event != null && StringUtils.isNotBlank(event.getExecutionId())) { - Execution execution = runtimeService.createExecutionQuery().executionId(event.getExecutionId()).singleResult(); - if (execution != null) { - BpmnModel bpmnModel = repositoryService.getBpmnModel(event.getProcessDefinitionId()); - FlowElement flowElement = bpmnModel.getFlowElement(execution.getActivityId()); - if (flowElement instanceof BoundaryEvent) { - String attachedToRefId = ((BoundaryEvent) flowElement).getAttachedToRefId(); - List list = runtimeService.createExecutionQuery().activityId(attachedToRefId).list(); - for (Execution ex : list) { - Task task = QueryUtils.taskQuery().executionId(ex.getId()).singleResult(); - if (task != null) { - List taskComments = taskService.getTaskComments(task.getId()); - if (CollUtil.isEmpty(taskComments)) { - taskService.addComment(task.getId(), task.getProcessInstanceId(), TaskStatusEnum.PASS.getStatus(), "超时自动审批!"); - } - } - } - } - } - } - } -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/handler/FlowProcessEventHandler.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/handler/FlowProcessEventHandler.java deleted file mode 100644 index 69ae70a07..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/handler/FlowProcessEventHandler.java +++ /dev/null @@ -1,50 +0,0 @@ -package org.dromara.workflow.flowable.handler; - -import org.dromara.common.core.domain.event.ProcessEvent; -import org.dromara.common.core.domain.event.ProcessTaskEvent; -import org.dromara.common.core.utils.SpringUtils; -import org.springframework.stereotype.Component; - -/** - * 流程监听服务 - * - * @author may - * @date 2024-06-02 - */ -@Component -public class FlowProcessEventHandler { - - /** - * 总体流程监听(例如: 提交 退回 撤销 终止 作废等) - * - * @param key 流程key - * @param businessKey 业务id - * @param status 状态 - * @param submit 当为true时为申请人节点办理 - */ - public void processHandler(String key, String businessKey, String status, boolean submit) { - ProcessEvent processEvent = new ProcessEvent(); - processEvent.setKey(key); - processEvent.setBusinessKey(businessKey); - processEvent.setStatus(status); - processEvent.setSubmit(submit); - SpringUtils.context().publishEvent(processEvent); - } - - /** - * 执行办理任务监听 - * - * @param key 流程key - * @param taskDefinitionKey 审批节点key - * @param taskId 任务id - * @param businessKey 业务id - */ - public void processTaskHandler(String key, String taskDefinitionKey, String taskId, String businessKey) { - ProcessTaskEvent processTaskEvent = new ProcessTaskEvent(); - processTaskEvent.setKey(key); - processTaskEvent.setTaskDefinitionKey(taskDefinitionKey); - processTaskEvent.setTaskId(taskId); - processTaskEvent.setBusinessKey(businessKey); - SpringUtils.context().publishEvent(processTaskEvent); - } -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/handler/TaskTimeoutJobHandler.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/handler/TaskTimeoutJobHandler.java deleted file mode 100644 index 61c938864..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/handler/TaskTimeoutJobHandler.java +++ /dev/null @@ -1,37 +0,0 @@ -package org.dromara.workflow.flowable.handler; - -import org.dromara.workflow.common.enums.TaskStatusEnum; -import org.flowable.common.engine.impl.interceptor.CommandContext; -import org.flowable.engine.TaskService; -import org.flowable.engine.impl.jobexecutor.TimerEventHandler; -import org.flowable.engine.impl.util.CommandContextUtil; -import org.flowable.job.service.JobHandler; -import org.flowable.job.service.impl.persistence.entity.JobEntity; -import org.flowable.task.api.Task; -import org.flowable.variable.api.delegate.VariableScope; - -/** - * 办理超时(过期)任务 - * - * @author may - */ -public class TaskTimeoutJobHandler extends TimerEventHandler implements JobHandler { - - public static final String TYPE = "taskTimeout"; - - @Override - public String getType() { - return TYPE; - } - - @Override - public void execute(JobEntity job, String configuration, VariableScope variableScope, CommandContext commandContext) { - TaskService taskService = CommandContextUtil.getProcessEngineConfiguration(commandContext) - .getTaskService(); - Task task = taskService.createTaskQuery().taskId(configuration).singleResult(); - if (task != null) { - taskService.addComment(task.getId(), task.getProcessInstanceId(), TaskStatusEnum.TIMEOUT.getStatus(), "超时自动审批!"); - taskService.complete(configuration); - } - } -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/handler/FlowProcessEventHandler.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/handler/FlowProcessEventHandler.java new file mode 100644 index 000000000..656e013e4 --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/handler/FlowProcessEventHandler.java @@ -0,0 +1,79 @@ +package org.dromara.workflow.handler; + +import lombok.extern.slf4j.Slf4j; +import org.dromara.common.core.domain.event.ProcessDeleteEvent; +import org.dromara.common.core.domain.event.ProcessEvent; +import org.dromara.common.core.domain.event.ProcessTaskEvent; +import org.dromara.common.core.utils.SpringUtils; +import org.dromara.common.tenant.helper.TenantHelper; +import org.dromara.workflow.common.ConditionalOnEnable; +import org.springframework.stereotype.Component; + +/** + * 流程监听服务 + * + * @author may + * @date 2024-06-02 + */ +@ConditionalOnEnable +@Slf4j +@Component +public class FlowProcessEventHandler { + + /** + * 总体流程监听(例如: 草稿,撤销,退回,作废,终止,已完成等) + * + * @param flowCode 流程定义编码 + * @param businessId 业务id + * @param status 状态 + * @param submit 当为true时为申请人节点办理 + */ + public void processHandler(String flowCode, String businessId, String status, boolean submit) { + String tenantId = TenantHelper.getTenantId(); + log.info("发布流程事件,租户ID: {}, 流程状态: {}, 流程编码: {}, 业务ID: {}, 是否申请人节点办理: {}", tenantId, status, flowCode, businessId, submit); + ProcessEvent processEvent = new ProcessEvent(); + processEvent.setTenantId(tenantId); + processEvent.setFlowCode(flowCode); + processEvent.setBusinessId(businessId); + processEvent.setStatus(status); + processEvent.setSubmit(submit); + SpringUtils.context().publishEvent(processEvent); + } + + /** + * 执行办理任务监听 + * + * @param flowCode 流程定义编码 + * @param nodeCode 审批节点编码 + * @param taskId 任务id + * @param businessId 业务id + */ + public void processTaskHandler(String flowCode, String nodeCode, Long taskId, String businessId) { + String tenantId = TenantHelper.getTenantId(); + log.info("发布流程任务事件, 租户ID: {}, 流程编码: {}, 节点编码: {}, 任务ID: {}, 业务ID: {}", tenantId, flowCode, nodeCode, taskId, businessId); + ProcessTaskEvent processTaskEvent = new ProcessTaskEvent(); + processTaskEvent.setTenantId(tenantId); + processTaskEvent.setFlowCode(flowCode); + processTaskEvent.setNodeCode(nodeCode); + processTaskEvent.setTaskId(taskId); + processTaskEvent.setBusinessId(businessId); + SpringUtils.context().publishEvent(processTaskEvent); + } + + /** + * 删除流程监听 + * + * @param flowCode 流程定义编码 + * @param businessId 业务ID + */ + public void processDeleteHandler(String flowCode, String businessId) { + String tenantId = TenantHelper.getTenantId(); + log.info("发布删除流程事件, 租户ID: {}, 流程编码: {}, 业务ID: {}", tenantId, flowCode, businessId); + ProcessDeleteEvent processDeleteEvent = new ProcessDeleteEvent(); + processDeleteEvent.setTenantId(tenantId); + processDeleteEvent.setFlowCode(flowCode); + processDeleteEvent.setBusinessId(businessId); + SpringUtils.context().publishEvent(processDeleteEvent); + } + +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/handler/WorkflowPermissionHandler.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/handler/WorkflowPermissionHandler.java new file mode 100644 index 000000000..c18e4ed52 --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/handler/WorkflowPermissionHandler.java @@ -0,0 +1,73 @@ +package org.dromara.workflow.handler; + +import cn.hutool.core.util.ObjectUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.dromara.common.core.domain.model.LoginUser; +import org.dromara.workflow.common.ConditionalOnEnable; +import org.dromara.workflow.common.enums.TaskAssigneeEnum; +import org.dromara.common.satoken.utils.LoginHelper; +import org.dromara.warm.flow.core.dto.FlowParams; +import org.dromara.warm.flow.core.handler.PermissionHandler; +import org.dromara.warm.flow.core.service.impl.TaskServiceImpl; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * 办理人权限处理器 + * + * @author AprilWind + */ +@ConditionalOnEnable +@RequiredArgsConstructor +@Component +@Slf4j +public class WorkflowPermissionHandler implements PermissionHandler { + + /** + * 审批前获取当前办理人,办理时会校验的该权限集合 + * 后续在{@link TaskServiceImpl#checkAuth(Task, FlowParams)} 中调用 + * 返回当前用户权限集合 + */ + @Override + public List permissions() { + LoginUser loginUser = LoginHelper.getLoginUser(); + if (ObjectUtil.isNull(loginUser)) { + return new ArrayList<>(); + } + // 使用一个流来构建权限列表 + return Stream.of( + // 角色权限前缀 + loginUser.getRoles().stream() + .map(role -> TaskAssigneeEnum.ROLE.getCode() + role.getRoleId()), + + // 岗位权限前缀 + Stream.ofNullable(loginUser.getPosts()) + .flatMap(Collection::stream) + .map(post -> TaskAssigneeEnum.POST.getCode() + post.getPostId()), + + // 用户和部门权限 + Stream.of(String.valueOf(loginUser.getUserId()), + TaskAssigneeEnum.DEPT.getCode() + loginUser.getDeptId() + ) + ) + .flatMap(stream -> stream) + .collect(Collectors.toList()); + } + + /** + * 获取当前办理人 + * + * @return 当前办理人 + */ + @Override + public String getHandler() { + return LoginHelper.getUserIdStr(); + } + +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/listener/WorkflowGlobalListener.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/listener/WorkflowGlobalListener.java new file mode 100644 index 000000000..097d74ce7 --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/listener/WorkflowGlobalListener.java @@ -0,0 +1,116 @@ +package org.dromara.workflow.listener; + +import cn.hutool.core.collection.CollUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.dromara.common.core.enums.BusinessStatusEnum; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.warm.flow.core.entity.Definition; +import org.dromara.warm.flow.core.entity.Instance; +import org.dromara.warm.flow.core.entity.Task; +import org.dromara.warm.flow.core.listener.GlobalListener; +import org.dromara.warm.flow.core.listener.ListenerVariable; +import org.dromara.warm.flow.orm.entity.FlowTask; +import org.dromara.workflow.common.ConditionalOnEnable; +import org.dromara.workflow.handler.FlowProcessEventHandler; +import org.dromara.workflow.service.IFlwInstanceService; +import org.dromara.workflow.service.IFlwTaskService; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * 全局任务办理监听 + * + * @author may + */ +@ConditionalOnEnable +@Component +@Slf4j +@RequiredArgsConstructor +public class WorkflowGlobalListener implements GlobalListener { + + private final IFlwTaskService taskService; + private final IFlwInstanceService instanceService; + private final FlowProcessEventHandler flowProcessEventHandler; + + /** + * 创建监听器,任务创建时执行 + * + * @param listenerVariable 监听器变量 + */ + @Override + public void create(ListenerVariable listenerVariable) { + Instance instance = listenerVariable.getInstance(); + Definition definition = listenerVariable.getDefinition(); + String businessId = instance.getBusinessId(); + String flowStatus = instance.getFlowStatus(); + Task task = listenerVariable.getTask(); + if (task != null && BusinessStatusEnum.WAITING.getStatus().equals(flowStatus)) { + // 判断流程状态(发布审批中事件) + flowProcessEventHandler.processTaskHandler(definition.getFlowCode(), task.getNodeCode(), task.getId(), businessId); + } + } + + /** + * 开始监听器,任务开始办理时执行 + * + * @param listenerVariable 监听器变量 + */ + @Override + public void start(ListenerVariable listenerVariable) { + } + + /** + * 分派监听器,动态修改代办任务信息 + * + * @param listenerVariable 监听器变量 + */ + @Override + public void assignment(ListenerVariable listenerVariable) { + } + + /** + * 完成监听器,当前任务完成后执行 + * + * @param listenerVariable 监听器变量 + */ + @Override + public void finish(ListenerVariable listenerVariable) { + Instance instance = listenerVariable.getInstance(); + Definition definition = listenerVariable.getDefinition(); + String businessId = instance.getBusinessId(); + String flowStatus = instance.getFlowStatus(); + // 判断流程状态(发布:撤销,退回,作废,终止,已完成事件) + String status = determineFlowStatus(instance, flowStatus); + if (StringUtils.isNotBlank(status)) { + flowProcessEventHandler.processHandler(definition.getFlowCode(), businessId, status, false); + } + } + + /** + * 根据流程实例和当前流程状态确定最终状态 + * + * @param instance 流程实例 + * @param flowStatus 流程实例当前状态 + * @return 流程最终状态 + */ + private String determineFlowStatus(Instance instance, String flowStatus) { + if (StringUtils.isNotBlank(flowStatus) && BusinessStatusEnum.initialState(flowStatus)) { + log.info("流程实例当前状态: {}", flowStatus); + return flowStatus; + } else { + Long instanceId = instance.getId(); + List flowTasks = taskService.selectByInstId(instanceId); + if (CollUtil.isEmpty(flowTasks)) { + String status = BusinessStatusEnum.FINISH.getStatus(); + // 更新流程状态为已完成 + instanceService.updateStatus(instanceId, status); + log.info("流程已结束,状态更新为: {}", status); + return status; + } + return null; + } + } + +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/ActHiProcinstMapper.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/ActHiProcinstMapper.java deleted file mode 100644 index a3a41c924..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/ActHiProcinstMapper.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.dromara.workflow.mapper; - -import com.baomidou.mybatisplus.annotation.InterceptorIgnore; -import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; -import org.dromara.workflow.domain.ActHiProcinst; - -/** - * 流程实例Mapper接口 - * - * @author may - * @date 2023-07-22 - */ -@InterceptorIgnore(tenantLine = "true") -public interface ActHiProcinstMapper extends BaseMapperPlus { - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/ActHiTaskinstMapper.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/ActHiTaskinstMapper.java deleted file mode 100644 index 63b394b6f..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/ActHiTaskinstMapper.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.dromara.workflow.mapper; - -import com.baomidou.mybatisplus.annotation.InterceptorIgnore; -import org.dromara.workflow.domain.ActHiTaskinst; -import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; - -/** - * 流程历史任务Mapper接口 - * - * @author may - * @date 2024-03-02 - */ -@InterceptorIgnore(tenantLine = "true") -public interface ActHiTaskinstMapper extends BaseMapperPlus { - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/ActTaskMapper.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/ActTaskMapper.java deleted file mode 100644 index 63c5ecb7b..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/ActTaskMapper.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.dromara.workflow.mapper; - -import com.baomidou.mybatisplus.annotation.InterceptorIgnore; -import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.baomidou.mybatisplus.core.toolkit.Constants; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import org.apache.ibatis.annotations.Param; -import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; -import org.dromara.workflow.domain.vo.TaskVo; - - -/** - * 任务信息Mapper接口 - * - * @author may - * @date 2024-03-02 - */ -@InterceptorIgnore(tenantLine = "true") -public interface ActTaskMapper extends BaseMapperPlus { - /** - * 获取待办信息 - * - * @param page 分页 - * @param queryWrapper 条件 - * @return 结果 - */ - Page getTaskWaitByPage(@Param("page") Page page, @Param(Constants.WRAPPER) Wrapper queryWrapper); - - /** - * 获取已办 - * - * @param page 分页 - * @param queryWrapper 条件 - * @return 结果 - */ - Page getTaskFinishByPage(@Param("page") Page page, @Param(Constants.WRAPPER) Wrapper queryWrapper); - - /** - * 查询当前用户的抄送 - * - * @param page 分页 - * @param queryWrapper 条件 - * @return 结果 - */ - Page getTaskCopyByPage(@Param("page") Page page, @Param(Constants.WRAPPER) QueryWrapper queryWrapper); -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/FlwCategoryMapper.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/FlwCategoryMapper.java new file mode 100644 index 000000000..d2c0b3a4d --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/FlwCategoryMapper.java @@ -0,0 +1,60 @@ +package org.dromara.workflow.mapper; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import org.dromara.common.mybatis.annotation.DataColumn; +import org.dromara.common.mybatis.annotation.DataPermission; +import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; +import org.dromara.common.mybatis.helper.DataBaseHelper; +import org.dromara.workflow.domain.FlowCategory; +import org.dromara.workflow.domain.vo.FlowCategoryVo; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * 流程分类Mapper接口 + * + * @author may + * @date 2023-06-27 + */ +public interface FlwCategoryMapper extends BaseMapperPlus { + + /** + * 统计指定流程分类ID的分类数量 + * + * @param categoryId 流程分类ID + * @return 该流程分类ID的分类数量 + */ + @DataPermission({ + @DataColumn(key = "deptName", value = "createDept") + }) + long countCategoryById(Long categoryId); + + /** + * 根据父流程分类ID查询其所有子流程分类的列表 + * + * @param parentId 父流程分类ID + * @return 包含子流程分类的列表 + */ + default List selectListByParentId(Long parentId) { + return this.selectList(new LambdaQueryWrapper() + .select(FlowCategory::getCategoryId) + .apply(DataBaseHelper.findInSet(parentId, "ancestors"))); + } + + /** + * 根据父流程分类ID查询包括父ID及其所有子流程分类ID的列表 + * + * @param parentId 父流程分类ID + * @return 包含父ID和子流程分类ID的列表 + */ + default List selectCategoryIdsByParentId(Long parentId) { + return Stream.concat( + this.selectListByParentId(parentId).stream() + .map(FlowCategory::getCategoryId), + Stream.of(parentId) + ).collect(Collectors.toList()); + } + +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/FlwInstanceMapper.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/FlwInstanceMapper.java new file mode 100644 index 000000000..92809c80f --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/FlwInstanceMapper.java @@ -0,0 +1,27 @@ +package org.dromara.workflow.mapper; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Constants; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.apache.ibatis.annotations.Param; +import org.dromara.workflow.domain.bo.FlowInstanceBo; +import org.dromara.workflow.domain.vo.FlowInstanceVo; + +/** + * 实例信息Mapper接口 + * + * @author may + * @date 2024-03-02 + */ +public interface FlwInstanceMapper { + + /** + * 流程实例信息 + * + * @param page 分页 + * @param queryWrapper 条件 + * @return 结果 + */ + Page selectInstanceList(@Param("page") Page page, @Param(Constants.WRAPPER) Wrapper queryWrapper); + +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/FlwTaskMapper.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/FlwTaskMapper.java new file mode 100644 index 000000000..fd86c82de --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/FlwTaskMapper.java @@ -0,0 +1,57 @@ +package org.dromara.workflow.mapper; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Constants; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.apache.ibatis.annotations.Param; +import org.dromara.workflow.domain.bo.FlowTaskBo; +import org.dromara.workflow.domain.vo.FlowHisTaskVo; +import org.dromara.workflow.domain.vo.FlowTaskVo; + +import java.util.List; + + +/** + * 任务信息Mapper接口 + * + * @author may + * @date 2024-03-02 + */ +public interface FlwTaskMapper { + + /** + * 获取待办信息 + * + * @param page 分页 + * @param queryWrapper 条件 + * @return 结果 + */ + Page getListRunTask(@Param("page") Page page, @Param(Constants.WRAPPER) Wrapper queryWrapper); + + /** + * 获取待办信息 + * + * @param queryWrapper 条件 + * @return 结果 + */ + List getListRunTask(@Param(Constants.WRAPPER) Wrapper queryWrapper); + + /** + * 获取已办 + * + * @param page 分页 + * @param queryWrapper 条件 + * @return 结果 + */ + Page getListFinishTask(@Param("page") Page page, @Param(Constants.WRAPPER) Wrapper queryWrapper); + + /** + * 查询当前用户的抄送 + * + * @param page 分页 + * @param queryWrapper 条件 + * @return 结果 + */ + Page getTaskCopyByPage(@Param("page") Page page, @Param(Constants.WRAPPER) QueryWrapper queryWrapper); +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/WfCategoryMapper.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/WfCategoryMapper.java deleted file mode 100644 index 98aea024e..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/WfCategoryMapper.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.dromara.workflow.mapper; - -import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; -import org.dromara.workflow.domain.WfCategory; -import org.dromara.workflow.domain.vo.WfCategoryVo; - -/** - * 流程分类Mapper接口 - * - * @author may - * @date 2023-06-27 - */ -public interface WfCategoryMapper extends BaseMapperPlus { - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/WfDefinitionConfigMapper.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/WfDefinitionConfigMapper.java deleted file mode 100644 index ee2088255..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/WfDefinitionConfigMapper.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.dromara.workflow.mapper; - -import org.dromara.workflow.domain.WfDefinitionConfig; -import org.dromara.workflow.domain.vo.WfDefinitionConfigVo; -import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; - -/** - * 流程定义配置Mapper接口 - * - * @author may - * @date 2024-03-18 - */ -public interface WfDefinitionConfigMapper extends BaseMapperPlus { - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/WfFormManageMapper.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/WfFormManageMapper.java deleted file mode 100644 index acf8111ad..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/WfFormManageMapper.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.dromara.workflow.mapper; - -import org.dromara.workflow.domain.WfFormManage; -import org.dromara.workflow.domain.vo.WfFormManageVo; -import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; - -/** - * 表单管理Mapper接口 - * - * @author may - * @date 2024-03-29 - */ -public interface WfFormManageMapper extends BaseMapperPlus { - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/WfNodeConfigMapper.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/WfNodeConfigMapper.java deleted file mode 100644 index d2aecacb9..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/WfNodeConfigMapper.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.dromara.workflow.mapper; - -import org.dromara.workflow.domain.WfNodeConfig; -import org.dromara.workflow.domain.vo.WfNodeConfigVo; -import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; - -/** - * 节点配置Mapper接口 - * - * @author may - * @date 2024-03-30 - */ -public interface WfNodeConfigMapper extends BaseMapperPlus { - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/WfTaskBackNodeMapper.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/WfTaskBackNodeMapper.java deleted file mode 100644 index 9b291feb4..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/WfTaskBackNodeMapper.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.dromara.workflow.mapper; - -import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; -import org.dromara.workflow.domain.WfTaskBackNode; - -/** - * 节点驳回记录Mapper接口 - * - * @author may - * @date 2024-03-13 - */ -public interface WfTaskBackNodeMapper extends BaseMapperPlus { -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActHiProcinstService.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActHiProcinstService.java deleted file mode 100644 index e802c6972..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActHiProcinstService.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.dromara.workflow.service; - - -import org.dromara.workflow.domain.ActHiProcinst; - -import java.util.List; - -/** - * 流程实例Service接口 - * - * @author may - * @date 2023-07-22 - */ -public interface IActHiProcinstService { - - /** - * 按照业务id查询 - * - * @param businessKeys 业务id - * @return 结果 - */ - List selectByBusinessKeyIn(List businessKeys); - - /** - * 按照业务id查询 - * - * @param businessKey 业务id - * @return 结果 - */ - ActHiProcinst selectByBusinessKey(String businessKey); -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActHiTaskinstService.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActHiTaskinstService.java deleted file mode 100644 index ad286e242..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActHiTaskinstService.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.dromara.workflow.service; - - -/** - * 流程历史任务Service接口 - * - * @author may - * @date 2024-03-02 - */ -public interface IActHiTaskinstService { -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActModelService.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActModelService.java deleted file mode 100644 index 4a6d17062..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActModelService.java +++ /dev/null @@ -1,83 +0,0 @@ -package org.dromara.workflow.service; - -import jakarta.servlet.http.HttpServletResponse; -import org.dromara.common.mybatis.core.page.PageQuery; -import org.dromara.common.mybatis.core.page.TableDataInfo; -import org.dromara.workflow.domain.bo.ModelBo; -import org.dromara.workflow.domain.vo.ModelVo; -import org.flowable.engine.repository.Model; - -import java.util.List; - - -/** - * 模型管理 服务层 - * - * @author may - */ -public interface IActModelService { - /** - * 分页查询模型 - * - * @param modelBo 模型参数 - * @param pageQuery 参数 - * @return 返回分页列表 - */ - TableDataInfo page(ModelBo modelBo, PageQuery pageQuery); - - /** - * 新增模型 - * - * @param modelBo 模型请求对象 - * @return 结果 - */ - boolean saveNewModel(ModelBo modelBo); - - /** - * 查询模型 - * - * @param modelId 模型id - * @return 模型数据 - */ - ModelVo getInfo(String modelId); - - /** - * 修改模型信息 - * - * @param modelBo 模型数据 - * @return 结果 - */ - boolean update(ModelBo modelBo); - - /** - * 编辑模型XML - * - * @param modelBo 模型数据 - * @return 结果 - */ - boolean editModelXml(ModelBo modelBo); - - /** - * 模型部署 - * - * @param id 模型id - * @return 结果 - */ - boolean modelDeploy(String id); - - /** - * 导出模型zip压缩包 - * - * @param modelIds 模型id - * @param response 响应 - */ - void exportZip(List modelIds, HttpServletResponse response); - - /** - * 复制模型 - * - * @param modelBo 模型数据 - * @return 结果 - */ - boolean copyModel(ModelBo modelBo); -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActProcessDefinitionService.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActProcessDefinitionService.java deleted file mode 100644 index 5d00e4199..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActProcessDefinitionService.java +++ /dev/null @@ -1,91 +0,0 @@ -package org.dromara.workflow.service; - -import org.dromara.common.mybatis.core.page.PageQuery; -import org.dromara.common.mybatis.core.page.TableDataInfo; -import org.dromara.workflow.domain.bo.ProcessDefinitionBo; -import org.dromara.workflow.domain.vo.ProcessDefinitionVo; -import org.springframework.web.multipart.MultipartFile; - -import java.util.List; - -/** - * 流程定义 服务层 - * - * @author may - */ -public interface IActProcessDefinitionService { - /** - * 分页查询 - * - * @param processDefinitionBo 参数 - * @param pageQuery 分页 - * @return 返回分页列表 - */ - TableDataInfo page(ProcessDefinitionBo processDefinitionBo, PageQuery pageQuery); - - /** - * 查询历史流程定义列表 - * - * @param key 流程定义key - * @return 结果 - */ - List getListByKey(String key); - - /** - * 查看流程定义图片 - * - * @param processDefinitionId 流程定义id - * @return 结果 - */ - String definitionImage(String processDefinitionId); - - /** - * 查看流程定义xml文件 - * - * @param processDefinitionId 流程定义id - * @return 结果 - */ - String definitionXml(String processDefinitionId); - - /** - * 删除流程定义 - * - * @param deploymentIds 部署id - * @param processDefinitionIds 流程定义id - * @return 结果 - */ - boolean deleteDeployment(List deploymentIds, List processDefinitionIds); - - /** - * 激活或者挂起流程定义 - * - * @param processDefinitionId 流程定义id - * @return 结果 - */ - boolean updateDefinitionState(String processDefinitionId); - - /** - * 迁移流程定义 - * - * @param currentProcessDefinitionId 当前流程定义id - * @param fromProcessDefinitionId 需要迁移到的流程定义id - * @return 结果 - */ - boolean migrationDefinition(String currentProcessDefinitionId, String fromProcessDefinitionId); - - /** - * 流程定义转换为模型 - * - * @param processDefinitionId 流程定义id - * @return 结果 - */ - boolean convertToModel(String processDefinitionId); - - /** - * 通过zip或xml部署流程定义 - * - * @param file 文件 - * @param categoryCode 分类 - */ - void deployByFile(MultipartFile file, String categoryCode); -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActProcessInstanceService.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActProcessInstanceService.java deleted file mode 100644 index ca3b6fb8e..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActProcessInstanceService.java +++ /dev/null @@ -1,110 +0,0 @@ -package org.dromara.workflow.service; - -import org.dromara.common.mybatis.core.page.PageQuery; -import org.dromara.common.mybatis.core.page.TableDataInfo; -import org.dromara.workflow.domain.bo.ProcessInstanceBo; -import org.dromara.workflow.domain.bo.ProcessInvalidBo; -import org.dromara.workflow.domain.bo.TaskUrgingBo; -import org.dromara.workflow.domain.vo.ActHistoryInfoVo; -import org.dromara.workflow.domain.vo.ProcessInstanceVo; - -import java.util.List; -import java.util.Map; - -/** - * 流程实例 服务层 - * - * @author may - */ -public interface IActProcessInstanceService { - /** - * 通过流程实例id获取历史流程图 - * - * @param businessKey 流程实例id - * @return 结果 - */ - String getHistoryImage(String businessKey); - - /** - * 通过业务id获取历史流程图运行中,历史等节点 - * - * @param businessKey 业务id - * @return 结果 - */ - Map getHistoryList(String businessKey); - - /** - * 分页查询正在运行的流程实例 - * - * @param processInstanceBo 参数 - * @param pageQuery 分页 - * @return 结果 - */ - TableDataInfo getPageByRunning(ProcessInstanceBo processInstanceBo, PageQuery pageQuery); - - /** - * 分页查询已结束的流程实例 - * - * @param processInstanceBo 参数 - * @param pageQuery 分页 - * @return 结果 - */ - TableDataInfo getPageByFinish(ProcessInstanceBo processInstanceBo, PageQuery pageQuery); - - /** - * 获取审批记录 - * - * @param businessKey 业务id - * @return 结果 - */ - List getHistoryRecord(String businessKey); - - /** - * 作废流程实例,不会删除历史记录(删除运行中的实例) - * - * @param processInvalidBo 参数 - * @return 结果 - */ - boolean deleteRunInstance(ProcessInvalidBo processInvalidBo); - - /** - * 运行中的实例 删除程实例,删除历史记录,删除业务与流程关联信息 - * - * @param businessKeys 业务id - * @return 结果 - */ - boolean deleteRunAndHisInstance(List businessKeys); - - /** - * 已完成的实例 删除程实例,删除历史记录,删除业务与流程关联信息 - * - * @param businessKeys 业务id - * @return 结果 - */ - boolean deleteFinishAndHisInstance(List businessKeys); - - /** - * 撤销流程申请 - * - * @param businessKey 业务id - * @return 结果 - */ - boolean cancelProcessApply(String businessKey); - - /** - * 分页查询当前登录人单据 - * - * @param processInstanceBo 参数 - * @param pageQuery 分页 - * @return 结果 - */ - TableDataInfo getPageByCurrent(ProcessInstanceBo processInstanceBo, PageQuery pageQuery); - - /** - * 任务催办(给当前任务办理人发送站内信,邮件,短信等) - * - * @param taskUrgingBo 任务催办 - * @return 结果 - */ - boolean taskUrging(TaskUrgingBo taskUrgingBo); -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActTaskService.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActTaskService.java deleted file mode 100644 index 8e9f76367..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActTaskService.java +++ /dev/null @@ -1,161 +0,0 @@ -package org.dromara.workflow.service; - -import org.dromara.common.mybatis.core.page.PageQuery; -import org.dromara.common.mybatis.core.page.TableDataInfo; -import org.dromara.workflow.domain.bo.*; -import org.dromara.workflow.domain.vo.TaskVo; -import org.dromara.workflow.domain.vo.VariableVo; - -import java.util.List; -import java.util.Map; - -/** - * 任务 服务层 - * - * @author may - */ -public interface IActTaskService { - /** - * 启动任务 - * - * @param startProcessBo 启动流程参数 - * @return 结果 - */ - Map startWorkFlow(StartProcessBo startProcessBo); - - - /** - * 办理任务 - * - * @param completeTaskBo 办理任务参数 - * @return 结果 - */ - boolean completeTask(CompleteTaskBo completeTaskBo); - - /** - * 查询当前用户的待办任务 - * - * @param taskBo 参数 - * @param pageQuery 分页 - * @return 结果 - */ - TableDataInfo getPageByTaskWait(TaskBo taskBo, PageQuery pageQuery); - - /** - * 查询当前租户所有待办任务 - * - * @param taskBo 参数 - * @param pageQuery 分页 - * @return 结果 - */ - TableDataInfo getPageByAllTaskWait(TaskBo taskBo, PageQuery pageQuery); - - - /** - * 查询当前用户的已办任务 - * - * @param taskBo 参数 - * @param pageQuery 参数 - * @return 结果 - */ - TableDataInfo getPageByTaskFinish(TaskBo taskBo, PageQuery pageQuery); - - /** - * 查询当前用户的抄送 - * - * @param taskBo 参数 - * @param pageQuery 参数 - * @return 结果 - */ - TableDataInfo getPageByTaskCopy(TaskBo taskBo, PageQuery pageQuery); - - /** - * 查询当前租户所有已办任务 - * - * @param taskBo 参数 - * @param pageQuery 参数 - * @return 结果 - */ - TableDataInfo getPageByAllTaskFinish(TaskBo taskBo, PageQuery pageQuery); - - /** - * 委派任务 - * - * @param delegateBo 参数 - * @return 结果 - */ - boolean delegateTask(DelegateBo delegateBo); - - /** - * 终止任务 - * - * @param terminationBo 参数 - * @return 结果 - */ - boolean terminationTask(TerminationBo terminationBo); - - /** - * 转办任务 - * - * @param transmitBo 参数 - * @return 结果 - */ - boolean transferTask(TransmitBo transmitBo); - - /** - * 会签任务加签 - * - * @param addMultiBo 参数 - * @return 结果 - */ - boolean addMultiInstanceExecution(AddMultiBo addMultiBo); - - /** - * 会签任务减签 - * - * @param deleteMultiBo 参数 - * @return 结果 - */ - boolean deleteMultiInstanceExecution(DeleteMultiBo deleteMultiBo); - - /** - * 驳回审批 - * - * @param backProcessBo 参数 - * @return 流程实例id - */ - String backProcess(BackProcessBo backProcessBo); - - /** - * 修改任务办理人 - * - * @param taskIds 任务id - * @param userId 办理人id - * @return 结果 - */ - boolean updateAssignee(String[] taskIds, String userId); - - /** - * 查询流程变量 - * - * @param taskId 任务id - * @return 结果 - */ - List getInstanceVariable(String taskId); - - /** - * 查询工作流任务用户选择加签人员 - * - * @param taskId 任务id - * @return 结果 - */ - String getTaskUserIdsByAddMultiInstance(String taskId); - - /** - * 查询工作流选择减签人员 - * - * @param taskId 任务id - * @return 结果 - */ - List getListByDeleteMultiInstance(String taskId); -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwCategoryService.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwCategoryService.java new file mode 100644 index 000000000..43bc175fd --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwCategoryService.java @@ -0,0 +1,102 @@ +package org.dromara.workflow.service; + +import cn.hutool.core.lang.tree.Tree; +import org.dromara.workflow.domain.bo.FlowCategoryBo; +import org.dromara.workflow.domain.vo.FlowCategoryVo; + +import java.util.List; + +/** + * 流程分类Service接口 + * + * @author may + */ +public interface IFlwCategoryService { + + /** + * 查询流程分类 + * + * @param categoryId 主键 + * @return 流程分类 + */ + FlowCategoryVo queryById(Long categoryId); + + /** + * 根据流程分类ID查询流程分类名称 + * + * @param categoryId 流程分类ID + * @return 流程分类名称 + */ + String selectCategoryNameById(String categoryId); + + /** + * 查询符合条件的流程分类列表 + * + * @param bo 查询条件 + * @return 流程分类列表 + */ + List queryList(FlowCategoryBo bo); + + /** + * 查询流程分类树结构信息 + * + * @param category 流程分类信息 + * @return 流程分类树信息集合 + */ + List> selectCategoryTreeList(FlowCategoryBo category); + + /** + * 校验流程分类是否有数据权限 + * + * @param categoryId 流程分类ID + */ + void checkCategoryDataScope(Long categoryId); + + /** + * 校验流程分类名称是否唯一 + * + * @param category 流程分类信息 + * @return 结果 + */ + boolean checkCategoryNameUnique(FlowCategoryBo category); + + /** + * 查询流程分类是否存在流程定义 + * + * @param categoryId 流程分类ID + * @return 结果 true 存在 false 不存在 + */ + boolean checkCategoryExistDefinition(Long categoryId); + + /** + * 是否存在流程分类子节点 + * + * @param categoryId 流程分类ID + * @return 结果 + */ + boolean hasChildByCategoryId(Long categoryId); + + /** + * 新增流程分类 + * + * @param bo 流程分类 + * @return 是否新增成功 + */ + int insertByBo(FlowCategoryBo bo); + + /** + * 修改流程分类 + * + * @param bo 流程分类 + * @return 是否修改成功 + */ + int updateByBo(FlowCategoryBo bo); + + /** + * 删除流程分类信息 + * + * @param categoryId 主键 + * @return 是否删除成功 + */ + int deleteWithValidById(Long categoryId); +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwDefinitionService.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwDefinitionService.java new file mode 100644 index 000000000..1a2d29f77 --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwDefinitionService.java @@ -0,0 +1,79 @@ +package org.dromara.workflow.service; + +import jakarta.servlet.http.HttpServletResponse; +import org.dromara.common.mybatis.core.page.PageQuery; +import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.warm.flow.orm.entity.FlowDefinition; +import org.dromara.workflow.domain.vo.FlowDefinitionVo; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.util.List; + +/** + * 流程定义 服务层 + * + * @author may + */ +public interface IFlwDefinitionService { + + /** + * 查询流程定义列表 + * + * @param flowDefinition 参数 + * @param pageQuery 分页 + * @return 返回分页列表 + */ + TableDataInfo queryList(FlowDefinition flowDefinition, PageQuery pageQuery); + + /** + * 查询未发布的流程定义列表 + * + * @param flowDefinition 参数 + * @param pageQuery 分页 + * @return 返回分页列表 + */ + TableDataInfo unPublishList(FlowDefinition flowDefinition, PageQuery pageQuery); + + + /** + * 发布流程定义 + * + * @param id 流程定义id + * @return 结果 + */ + boolean publish(Long id); + + /** + * 导出流程定义 + * + * @param id 流程定义id + * @param response 响应 + * @throws IOException 异常 + */ + void exportDef(Long id, HttpServletResponse response) throws IOException; + + /** + * 导入流程定义 + * + * @param file 文件 + * @param category 分类 + * @return 结果 + */ + boolean importJson(MultipartFile file, String category); + + /** + * 删除流程定义 + * + * @param ids 流程定义id + * @return 结果 + */ + boolean removeDef(List ids); + + /** + * 新增租户流程定义 + * + * @param tenantId 租户id + */ + void syncDef(String tenantId); +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwInstanceService.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwInstanceService.java new file mode 100644 index 000000000..97d84a280 --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwInstanceService.java @@ -0,0 +1,159 @@ +package org.dromara.workflow.service; + +import org.dromara.common.mybatis.core.page.PageQuery; +import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.warm.flow.orm.entity.FlowInstance; +import org.dromara.workflow.domain.bo.FlowCancelBo; +import org.dromara.workflow.domain.bo.FlowInstanceBo; +import org.dromara.workflow.domain.bo.FlowInvalidBo; +import org.dromara.workflow.domain.vo.FlowInstanceVo; + +import java.util.List; +import java.util.Map; + +/** + * 流程实例 服务层 + * + * @author may + */ +public interface IFlwInstanceService { + + /** + * 分页查询正在运行的流程实例 + * + * @param flowInstanceBo 流程实例 + * @param pageQuery 分页 + * @return 结果 + */ + TableDataInfo selectRunningInstanceList(FlowInstanceBo flowInstanceBo, PageQuery pageQuery); + + /** + * 分页查询已结束的流程实例 + * + * @param flowInstanceBo 流程实例 + * @param pageQuery 分页 + * @return 结果 + */ + TableDataInfo selectFinishInstanceList(FlowInstanceBo flowInstanceBo, PageQuery pageQuery); + + /** + * 根据业务id查询流程实例详细信息 + * + * @param businessId 业务id + * @return 结果 + */ + FlowInstanceVo queryByBusinessId(Long businessId); + + /** + * 按照业务id查询流程实例 + * + * @param businessId 业务id + * @return 结果 + */ + FlowInstance selectInstByBusinessId(String businessId); + + /** + * 按照实例id查询流程实例 + * + * @param instanceId 实例id + * @return 结果 + */ + FlowInstance selectInstById(Long instanceId); + + /** + * 按照实例id查询流程实例 + * + * @param instanceIds 实例id + * @return 结果 + */ + List selectInstListByIdList(List instanceIds); + + /** + * 按照业务id删除流程实例 + * + * @param businessIds 业务id + * @return 结果 + */ + boolean deleteByBusinessIds(List businessIds); + + /** + * 按照实例id删除流程实例 + * + * @param instanceIds 实例id + * @return 结果 + */ + boolean deleteByInstanceIds(List instanceIds); + + /** + * 撤销流程 + * + * @param bo 参数 + * @return 结果 + */ + boolean cancelProcessApply(FlowCancelBo bo); + + /** + * 获取当前登陆人发起的流程实例 + * + * @param instanceBo 流程实例 + * @param pageQuery 分页 + * @return 结果 + */ + TableDataInfo selectCurrentInstanceList(FlowInstanceBo instanceBo, PageQuery pageQuery); + + /** + * 获取流程图,流程记录 + * + * @param businessId 业务id + * @return 结果 + */ + Map flowImage(String businessId); + + /** + * 按照实例id更新状态 + * + * @param instanceId 实例id + * @param status 状态 + */ + void updateStatus(Long instanceId, String status); + + /** + * 获取流程变量 + * + * @param instanceId 实例id + * @return 结果 + */ + Map instanceVariable(String instanceId); + + /** + * 设置流程变量 + * + * @param instanceId 实例id + * @param variable 流程变量 + */ + void setVariable(Long instanceId, Map variable); + + /** + * 按任务id查询实例 + * + * @param taskId 任务id + * @return 结果 + */ + FlowInstance selectByTaskId(Long taskId); + + /** + * 按任务id查询实例 + * + * @param taskIdList 任务id + * @return 结果 + */ + List selectByTaskIdList(List taskIdList); + + /** + * 作废流程 + * + * @param bo 流程实例 + * @return 结果 + */ + boolean processInvalid(FlowInvalidBo bo); +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwTaskAssigneeService.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwTaskAssigneeService.java new file mode 100644 index 000000000..116cb74f3 --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwTaskAssigneeService.java @@ -0,0 +1,22 @@ +package org.dromara.workflow.service; + +import org.dromara.common.core.domain.dto.UserDTO; + +import java.util.List; + +/** + * 流程设计器-获取办理人 + * + * @author AprilWind + */ +public interface IFlwTaskAssigneeService { + + /** + * 根据存储标识符(storageId)解析分配类型和ID,并获取对应的用户列表 + * + * @param storageId 包含分配类型和ID的字符串(例如 "user:123" 或 "role:456") + * @return 与分配类型和ID匹配的用户列表,如果格式无效则返回空列表 + */ + List fetchUsersByStorageId(String storageId); + +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwTaskService.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwTaskService.java new file mode 100644 index 000000000..80bfa948c --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwTaskService.java @@ -0,0 +1,190 @@ +package org.dromara.workflow.service; + +import org.dromara.common.core.domain.dto.UserDTO; +import org.dromara.common.mybatis.core.page.PageQuery; +import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.warm.flow.core.entity.Node; +import org.dromara.warm.flow.orm.entity.FlowHisTask; +import org.dromara.warm.flow.orm.entity.FlowTask; +import org.dromara.workflow.domain.bo.*; +import org.dromara.workflow.domain.vo.FlowHisTaskVo; +import org.dromara.workflow.domain.vo.FlowTaskVo; + +import java.util.List; +import java.util.Map; + +/** + * 任务 服务层 + * + * @author may + */ +public interface IFlwTaskService { + + /** + * 启动任务 + * + * @param startProcessBo 启动流程参数 + * @return 结果 + */ + Map startWorkFlow(StartProcessBo startProcessBo); + + /** + * 办理任务 + * + * @param completeTaskBo 办理任务参数 + * @return 结果 + */ + boolean completeTask(CompleteTaskBo completeTaskBo); + + /** + * 查询当前用户的待办任务 + * + * @param flowTaskBo 参数 + * @param pageQuery 分页 + * @return 结果 + */ + TableDataInfo pageByTaskWait(FlowTaskBo flowTaskBo, PageQuery pageQuery); + + /** + * 查询当前租户所有待办任务 + * + * @param flowTaskBo 参数 + * @param pageQuery 分页 + * @return 结果 + */ + TableDataInfo pageByTaskFinish(FlowTaskBo flowTaskBo, PageQuery pageQuery); + + /** + * 查询待办任务 + * + * @param flowTaskBo 参数 + * @param pageQuery 分页 + * @return 结果 + */ + TableDataInfo pageByAllTaskWait(FlowTaskBo flowTaskBo, PageQuery pageQuery); + + /** + * 查询已办任务 + * + * @param flowTaskBo 参数 + * @param pageQuery 分页 + * @return 结果 + */ + TableDataInfo pageByAllTaskFinish(FlowTaskBo flowTaskBo, PageQuery pageQuery); + + /** + * 查询当前用户的抄送 + * + * @param flowTaskBo 参数 + * @param pageQuery 分页 + * @return 结果 + */ + TableDataInfo pageByTaskCopy(FlowTaskBo flowTaskBo, PageQuery pageQuery); + + /** + * 修改任务办理人 + * + * @param taskIdList 任务id + * @param userId 用户id + * @return 结果 + */ + boolean updateAssignee(List taskIdList, String userId); + + /** + * 驳回审批 + * + * @param bo 参数 + * @return 结果 + */ + boolean backProcess(BackProcessBo bo); + + /** + * 获取可驳回的前置节点 + * + * @param definitionId 流程定义id + * @param nowNodeCode 当前节点 + * @return 结果 + */ + List getBackTaskNode(Long definitionId, String nowNodeCode); + + /** + * 终止任务 + * + * @param bo 参数 + * @return 结果 + */ + boolean terminationTask(FlowTerminationBo bo); + + /** + * 按照任务id查询任务 + * + * @param taskIdList 任务id + * @return 结果 + */ + List selectByIdList(List taskIdList); + + /** + * 按照任务id查询任务 + * + * @param taskId 任务id + * @return 结果 + */ + FlowTaskVo selectById(Long taskId); + + /** + * 按照任务id查询任务 + * + * @param taskIdList 任务id + * @return 结果 + */ + List selectHisTaskByIdList(List taskIdList); + + /** + * 按照任务id查询任务 + * + * @param taskId 任务id + * @return 结果 + */ + FlowHisTask selectHisTaskById(Long taskId); + + /** + * 按照实例id查询任务 + * + * @param instanceIdList 流程实例id + * @return 结果 + */ + List selectByInstIdList(List instanceIdList); + + /** + * 按照实例id查询任务 + * + * @param instanceId 流程实例id + * @return 结果 + */ + List selectByInstId(Long instanceId); + + /** + * 任务操作 + * + * @param bo 参数 + * @param taskOperation 操作类型,委派 delegateTask、转办 transferTask、加签 addSignature、减签 reductionSignature + * @return 结果 + */ + boolean taskOperation(TaskOperationBo bo, String taskOperation); + + /** + * 获取任务所有办理人 + * + * @param taskIdList 任务id + * @return 结果 + */ + Map> currentTaskAllUser(List taskIdList); + + /** + * 获取当前任务的所有办理人 + * + * @param taskId 任务id + * @return 结果 + */ + List currentTaskAllUser(Long taskId); +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/ITestLeaveService.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/ITestLeaveService.java index 943c919ae..67b50baf3 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/ITestLeaveService.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/ITestLeaveService.java @@ -5,7 +5,6 @@ import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.workflow.domain.bo.TestLeaveBo; import org.dromara.workflow.domain.vo.TestLeaveVo; -import java.util.Collection; import java.util.List; /** @@ -44,5 +43,5 @@ public interface ITestLeaveService { /** * 校验并批量删除请假信息 */ - Boolean deleteWithValidByIds(Collection ids); + Boolean deleteWithValidByIds(List ids); } diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IWfCategoryService.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IWfCategoryService.java deleted file mode 100644 index acf0aa2bc..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IWfCategoryService.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.dromara.workflow.service; - -import org.dromara.workflow.domain.WfCategory; -import org.dromara.workflow.domain.bo.WfCategoryBo; -import org.dromara.workflow.domain.vo.WfCategoryVo; - -import java.util.Collection; -import java.util.List; - -/** - * 流程分类Service接口 - * - * @author may - * @date 2023-06-28 - */ -public interface IWfCategoryService { - - /** - * 查询流程分类 - */ - WfCategoryVo queryById(Long id); - - - /** - * 查询流程分类列表 - */ - List queryList(WfCategoryBo bo); - - /** - * 新增流程分类 - */ - Boolean insertByBo(WfCategoryBo bo); - - /** - * 修改流程分类 - */ - Boolean updateByBo(WfCategoryBo bo); - - /** - * 校验并批量删除流程分类信息 - */ - Boolean deleteWithValidByIds(Collection ids, Boolean isValid); - - /** - * 按照类别编码查询 - * - * @param categoryCode 分类比吗 - * @return 结果 - */ - WfCategory queryByCategoryCode(String categoryCode); -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IWfDefinitionConfigService.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IWfDefinitionConfigService.java deleted file mode 100644 index fe5cf7ad3..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IWfDefinitionConfigService.java +++ /dev/null @@ -1,83 +0,0 @@ -package org.dromara.workflow.service; - -import org.dromara.workflow.domain.vo.WfDefinitionConfigVo; -import org.dromara.workflow.domain.bo.WfDefinitionConfigBo; - -import java.util.Collection; -import java.util.List; - -/** - * 流程定义配置Service接口 - * - * @author may - * @date 2024-03-18 - */ -public interface IWfDefinitionConfigService { - - /** - * 查询流程定义配置 - * - * @param definitionId 流程定义id - * @return 结果 - */ - WfDefinitionConfigVo getByDefId(String definitionId); - - /** - * 查询流程定义配置 - * - * @param tableName 表名 - * @return 结果 - */ - WfDefinitionConfigVo getByTableNameLastVersion(String tableName); - - /** - * 查询流程定义配置 - * - * @param definitionId 流程定义id - * @param tableName 表名 - * @return 结果 - */ - WfDefinitionConfigVo getByDefIdAndTableName(String definitionId, String tableName); - - /** - * 查询流程定义配置排除当前查询的流程定义 - * - * @param definitionId 流程定义id - * @param tableName 表名 - * @return 结果 - */ - List getByTableNameNotDefId(String tableName, String definitionId); - - /** - * 查询流程定义配置列表 - * - * @param definitionIds 流程定义id - * @return 结果 - */ - List queryList(List definitionIds); - - - /** - * 新增流程定义配置 - * - * @param bo 参数 - * @return 结果 - */ - Boolean saveOrUpdate(WfDefinitionConfigBo bo); - - /** - * 删除 - * - * @param ids id - * @return 结果 - */ - Boolean deleteByIds(Collection ids); - - /** - * 按照流程定义id删除 - * - * @param ids 流程定义id - * @return 结果 - */ - Boolean deleteByDefIds(Collection ids); -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IWfFormManageService.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IWfFormManageService.java deleted file mode 100644 index 2ca2264b0..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IWfFormManageService.java +++ /dev/null @@ -1,81 +0,0 @@ -package org.dromara.workflow.service; - -import org.dromara.workflow.domain.vo.WfFormManageVo; -import org.dromara.workflow.domain.bo.WfFormManageBo; -import org.dromara.common.mybatis.core.page.TableDataInfo; -import org.dromara.common.mybatis.core.page.PageQuery; - -import java.util.Collection; -import java.util.List; - -/** - * 表单管理Service接口 - * - * @author may - * @date 2024-03-29 - */ -public interface IWfFormManageService { - - /** - * 查询表单管理 - * - * @param id 主键 - * @return 结果 - */ - WfFormManageVo queryById(Long id); - - /** - * 查询表单管理 - * - * @param ids 主键 - * @return 结果 - */ - List queryByIds(List ids); - - /** - * 查询表单管理列表 - * - * @param bo 参数 - * @param pageQuery 分页 - * @return 结果 - */ - TableDataInfo queryPageList(WfFormManageBo bo, PageQuery pageQuery); - - /** - * 查询表单管理列表 - * - * @return 结果 - */ - List selectList(); - /** - * 查询表单管理列表 - * - * @param bo 参数 - * @return 结果 - */ - List queryList(WfFormManageBo bo); - - /** - * 新增表单管理 - * - * @param bo 参数 - * @return 结果 - */ - Boolean insertByBo(WfFormManageBo bo); - - /** - * 修改表单管理 - * - * @param bo 参数 - * @return 结果 - */ - Boolean updateByBo(WfFormManageBo bo); - - /** - * 批量删除表单管理信息 - * - * @param ids 主键 - * @return 结果 - */ - Boolean deleteByIds(Collection ids); -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IWfNodeConfigService.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IWfNodeConfigService.java deleted file mode 100644 index 5e64d64a5..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IWfNodeConfigService.java +++ /dev/null @@ -1,56 +0,0 @@ -package org.dromara.workflow.service; - -import org.dromara.workflow.domain.WfNodeConfig; -import org.dromara.workflow.domain.vo.WfNodeConfigVo; - -import java.util.Collection; -import java.util.List; - -/** - * 节点配置Service接口 - * - * @author may - * @date 2024-03-30 - */ -public interface IWfNodeConfigService { - - /** - * 查询节点配置 - * - * @param id 主键 - * @return 结果 - */ - WfNodeConfigVo queryById(Long id); - - /** - * 保存节点配置 - * - * @param list 参数 - * @return 结果 - */ - Boolean saveOrUpdate(List list); - - /** - * 批量删除节点配置信息 - * - * @param ids 主键 - * @return 结果 - */ - Boolean deleteByIds(Collection ids); - - /** - * 按照流程定义id删除 - * - * @param ids 流程定义id - * @return 结果 - */ - Boolean deleteByDefIds(Collection ids); - - /** - * 按照流程定义id查询 - * - * @param ids 流程定义id - * @return 结果 - */ - List selectByDefIds(Collection ids); -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IWfTaskBackNodeService.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IWfTaskBackNodeService.java deleted file mode 100644 index 97f940671..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IWfTaskBackNodeService.java +++ /dev/null @@ -1,65 +0,0 @@ -package org.dromara.workflow.service; - - -import org.dromara.workflow.domain.WfTaskBackNode; -import org.flowable.task.api.Task; - -import java.util.List; - -/** - * 节点驳回记录Service接口 - * - * @author may - * @date 2024-03-13 - */ -public interface IWfTaskBackNodeService { - - /** - * 记录审批节点 - * - * @param task 任务 - */ - void recordExecuteNode(Task task); - - /** - * 按流程实例id查询 - * - * @param processInstanceId 流程实例id - * @return 结果 - */ - List getListByInstanceId(String processInstanceId); - - /** - * 按照流程实例id,节点id查询 - * - * @param processInstanceId 流程实例id - * @param nodeId 节点id - * @return 结果 - */ - WfTaskBackNode getListByInstanceIdAndNodeId(String processInstanceId, String nodeId); - - /** - * 删除驳回后的节点 - * - * @param processInstanceId 流程实例id - * @param targetActivityId 节点id - * @return 结果 - */ - boolean deleteBackTaskNode(String processInstanceId, String targetActivityId); - - /** - * 按流程实例id删除 - * - * @param processInstanceId 流程实例id - * @return 结果 - */ - boolean deleteByInstanceId(String processInstanceId); - - /** - * 按流程实例id删除 - * - * @param processInstanceIds 流程实例id - * @return 结果 - */ - boolean deleteByInstanceIds(List processInstanceIds); -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActHiProcinstServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActHiProcinstServiceImpl.java deleted file mode 100644 index 06d607b4f..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActHiProcinstServiceImpl.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.dromara.workflow.service.impl; - - -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import lombok.RequiredArgsConstructor; -import org.dromara.common.tenant.helper.TenantHelper; -import org.dromara.workflow.domain.ActHiProcinst; -import org.dromara.workflow.mapper.ActHiProcinstMapper; -import org.dromara.workflow.service.IActHiProcinstService; -import org.springframework.stereotype.Service; - -import java.util.List; - - -/** - * 流程实例Service业务层处理 - * - * @author may - * @date 2023-07-22 - */ -@RequiredArgsConstructor -@Service -public class ActHiProcinstServiceImpl implements IActHiProcinstService { - - private final ActHiProcinstMapper baseMapper; - - /** - * 按照业务id查询 - * - * @param businessKeys 业务id - */ - @Override - public List selectByBusinessKeyIn(List businessKeys) { - return baseMapper.selectList(new LambdaQueryWrapper() - .in(ActHiProcinst::getBusinessKey, businessKeys) - .eq(TenantHelper.isEnable(), ActHiProcinst::getTenantId, TenantHelper.getTenantId())); - } - - /** - * 按照业务id查询 - * - * @param businessKey 业务id - */ - @Override - public ActHiProcinst selectByBusinessKey(String businessKey) { - return baseMapper.selectOne(new LambdaQueryWrapper() - .eq(ActHiProcinst::getBusinessKey, businessKey) - .eq(TenantHelper.isEnable(), ActHiProcinst::getTenantId, TenantHelper.getTenantId())); - - } -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActHiTaskinstServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActHiTaskinstServiceImpl.java deleted file mode 100644 index 5548f22f5..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActHiTaskinstServiceImpl.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.dromara.workflow.service.impl; - -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.dromara.workflow.service.IActHiTaskinstService; - - -/** - * 流程历史任务Service业务层处理 - * - * @author may - * @date 2024-03-02 - */ -@RequiredArgsConstructor -@Service -public class ActHiTaskinstServiceImpl implements IActHiTaskinstService { - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActModelServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActModelServiceImpl.java deleted file mode 100644 index 217538e44..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActModelServiceImpl.java +++ /dev/null @@ -1,431 +0,0 @@ -package org.dromara.workflow.service.impl; - -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.lang.Validator; -import cn.hutool.core.util.ArrayUtil; -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.core.util.StrUtil; -import cn.hutool.core.util.ZipUtil; -import cn.hutool.json.JSONUtil; -import com.alibaba.excel.util.StringUtils; -import jakarta.servlet.http.HttpServletResponse; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.apache.batik.transcoder.TranscoderInput; -import org.apache.batik.transcoder.TranscoderOutput; -import org.apache.batik.transcoder.image.PNGTranscoder; -import org.dromara.common.core.exception.ServiceException; -import org.dromara.common.mybatis.core.page.PageQuery; -import org.dromara.common.mybatis.core.page.TableDataInfo; -import org.dromara.common.tenant.helper.TenantHelper; -import org.dromara.workflow.common.constant.FlowConstant; -import org.dromara.workflow.domain.WfNodeConfig; -import org.dromara.workflow.domain.bo.ModelBo; -import org.dromara.workflow.domain.bo.WfDefinitionConfigBo; -import org.dromara.workflow.domain.vo.ModelVo; -import org.dromara.workflow.domain.vo.WfDefinitionConfigVo; -import org.dromara.workflow.service.IActModelService; -import org.dromara.workflow.service.IWfDefinitionConfigService; -import org.dromara.workflow.service.IWfNodeConfigService; -import org.dromara.workflow.utils.ModelUtils; -import org.dromara.workflow.utils.QueryUtils; -import org.flowable.bpmn.converter.BpmnXMLConverter; -import org.flowable.bpmn.model.BpmnModel; -import org.flowable.bpmn.model.Process; -import org.flowable.bpmn.model.UserTask; -import org.flowable.engine.RepositoryService; -import org.flowable.engine.repository.Deployment; -import org.flowable.engine.repository.Model; -import org.flowable.engine.repository.ModelQuery; -import org.flowable.engine.repository.ProcessDefinition; -import org.flowable.validation.ValidationError; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.URLEncoder; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.stream.Collectors; -import java.util.zip.ZipEntry; -import java.util.zip.ZipOutputStream; - -/** - * 模型管理 服务层实现 - * - * @author may - */ -@Slf4j -@RequiredArgsConstructor -@Service -public class ActModelServiceImpl implements IActModelService { - - @Autowired(required = false) - private RepositoryService repositoryService; - private final IWfNodeConfigService wfNodeConfigService; - private final IWfDefinitionConfigService wfDefinitionConfigService; - - /** - * 分页查询模型 - * - * @param modelBo 模型参数 - * @return 返回分页列表 - */ - @Override - public TableDataInfo page(ModelBo modelBo, PageQuery pageQuery) { - ModelQuery query = QueryUtils.modelQuery(); - if (StringUtils.isNotBlank(modelBo.getName())) { - query.modelNameLike("%" + modelBo.getName() + "%"); - } - if (StringUtils.isNotBlank(modelBo.getKey())) { - query.modelKey(modelBo.getKey()); - } - if (StringUtils.isNotBlank(modelBo.getCategoryCode())) { - query.modelCategory(modelBo.getCategoryCode()); - } - query.orderByLastUpdateTime().desc(); - // 创建时间降序排列 - query.orderByCreateTime().desc(); - // 分页查询 - List modelList = query.listPage(pageQuery.getFirstNum(), pageQuery.getPageSize()); - // 总记录数 - long total = query.count(); - TableDataInfo build = TableDataInfo.build(); - build.setRows(modelList); - build.setTotal(total); - return build; - } - - /** - * 新增模型 - * - * @param modelBo 模型请求对象 - * @return 结果 - */ - @Override - @Transactional(rollbackFor = Exception.class) - public boolean saveNewModel(ModelBo modelBo) { - try { - int version = 0; - String key = modelBo.getKey(); - String name = modelBo.getName(); - String description = modelBo.getDescription(); - String categoryCode = modelBo.getCategoryCode(); - String xml = modelBo.getXml(); - Model checkModel = QueryUtils.modelQuery().modelKey(key).singleResult(); - if (ObjectUtil.isNotNull(checkModel)) { - throw new ServiceException("模型key已存在!"); - } - //初始空的模型 - Model model = repositoryService.newModel(); - model.setKey(key); - model.setName(name); - model.setVersion(version); - model.setCategory(categoryCode); - model.setMetaInfo(description); - model.setTenantId(TenantHelper.getTenantId()); - //保存初始化的模型基本信息数据 - repositoryService.saveModel(model); - repositoryService.addModelEditorSource(model.getId(), StrUtil.utf8Bytes(xml)); - return true; - } catch (Exception e) { - log.error(e.getMessage(), e); - throw new ServiceException(e.getMessage()); - } - } - - /** - * 查询模型 - * - * @param id 模型id - * @return 模型数据 - */ - @Override - public ModelVo getInfo(String id) { - ModelVo modelVo = new ModelVo(); - Model model = repositoryService.getModel(id); - if (model != null) { - try { - byte[] modelEditorSource = repositoryService.getModelEditorSource(model.getId()); - modelVo.setXml(StrUtil.utf8Str(modelEditorSource)); - modelVo.setId(model.getId()); - modelVo.setKey(model.getKey()); - modelVo.setName(model.getName()); - modelVo.setCategoryCode(model.getCategory()); - modelVo.setDescription(model.getMetaInfo()); - return modelVo; - } catch (Exception e) { - log.error(e.getMessage(), e); - throw new ServiceException(e.getMessage()); - } - } - return modelVo; - } - - /** - * 修改模型信息 - * - * @param modelBo 模型数据 - * @return 结果 - */ - @Override - public boolean update(ModelBo modelBo) { - try { - Model model = repositoryService.getModel(modelBo.getId()); - List list = QueryUtils.modelQuery().modelKey(modelBo.getKey()).list(); - list.stream().filter(e -> !e.getId().equals(model.getId())).findFirst().ifPresent(e -> { - throw new ServiceException("模型KEY已存在!"); - }); - model.setCategory(modelBo.getCategoryCode()); - model.setMetaInfo(modelBo.getDescription()); - repositoryService.saveModel(model); - } catch (Exception e) { - log.error(e.getMessage(), e); - throw new ServiceException(e.getMessage()); - } - return true; - } - - /** - * 编辑模型XML - * - * @param modelBo 模型数据 - * @return 结果 - */ - @Override - @Transactional(rollbackFor = Exception.class) - public boolean editModelXml(ModelBo modelBo) { - try { - String xml = modelBo.getXml(); - String svg = modelBo.getSvg(); - String modelId = modelBo.getId(); - String key = modelBo.getKey(); - String name = modelBo.getName(); - BpmnModel bpmnModel = ModelUtils.xmlToBpmnModel(xml); - ModelUtils.checkBpmnModel(bpmnModel); - Model model = repositoryService.getModel(modelId); - List list = QueryUtils.modelQuery().modelKey(key).list(); - list.stream().filter(e -> !e.getId().equals(model.getId())).findFirst().ifPresent(e -> { - throw new ServiceException("模型KEY已存在!"); - }); - // 校验key命名规范 - if (!Validator.isMatchRegex(FlowConstant.MODEL_KEY_PATTERN, key)) { - throw new ServiceException("模型标识KEY只能字符或者下划线开头!"); - } - model.setKey(key); - model.setName(name); - model.setVersion(model.getVersion() + 1); - repositoryService.saveModel(model); - repositoryService.addModelEditorSource(model.getId(), StrUtil.utf8Bytes(xml)); - // 转换图片 - InputStream svgStream = new ByteArrayInputStream(StrUtil.utf8Bytes(svg)); - TranscoderInput input = new TranscoderInput(svgStream); - - PNGTranscoder transcoder = new PNGTranscoder(); - ByteArrayOutputStream outStream = new ByteArrayOutputStream(); - TranscoderOutput output = new TranscoderOutput(outStream); - - transcoder.transcode(input, output); - final byte[] result = outStream.toByteArray(); - repositoryService.addModelEditorSourceExtra(model.getId(), result); - return true; - } catch (Exception e) { - log.error(e.getMessage(), e); - throw new ServiceException(e.getMessage()); - } - } - - /** - * 模型部署 - * - * @param id 模型id - * @return 结果 - */ - @Override - @Transactional(rollbackFor = Exception.class) - public boolean modelDeploy(String id) { - try { - // 查询流程定义模型xml - byte[] xmlBytes = repositoryService.getModelEditorSource(id); - if (ArrayUtil.isEmpty(xmlBytes)) { - throw new ServiceException("模型数据为空,请先设计流程定义模型,再进行部署!"); - } - if (JSONUtil.isTypeJSON(new String(xmlBytes, StandardCharsets.UTF_8))) { - byte[] bytes = ModelUtils.bpmnJsonToXmlBytes(xmlBytes); - if (ArrayUtil.isEmpty(bytes)) { - throw new ServiceException("模型不能为空,请至少设计一条主线流程!"); - } - } - BpmnModel bpmnModel = ModelUtils.xmlToBpmnModel(xmlBytes); - // 校验模型 - ModelUtils.checkBpmnModel(bpmnModel); - List validationErrors = repositoryService.validateProcess(bpmnModel); - if (CollUtil.isNotEmpty(validationErrors)) { - String errorMsg = validationErrors.stream().map(ValidationError::getProblem).distinct().collect(Collectors.joining(",")); - throw new ServiceException(errorMsg); - } - // 查询模型的基本信息 - Model model = repositoryService.getModel(id); - ProcessDefinition processDefinition = QueryUtils.definitionQuery().processDefinitionKey(model.getKey()).latestVersion().singleResult(); - // xml资源的名称 ,对应act_ge_bytearray表中的name_字段 - String processName = model.getName() + ".bpmn20.xml"; - // 调用部署相关的api方法进行部署流程定义 - Deployment deployment = repositoryService.createDeployment() - // 部署名称 - .name(model.getName()) - // 部署标识key - .key(model.getKey()) - // 部署流程分类 - .category(model.getCategory()) - // bpmn20.xml资源 - .addBytes(processName, xmlBytes) - // 租户id - .tenantId(TenantHelper.getTenantId()) - .deploy(); - - // 更新 部署id 到流程定义模型数据表中 - model.setDeploymentId(deployment.getId()); - repositoryService.saveModel(model); - // 更新分类 - ProcessDefinition definition = QueryUtils.definitionQuery().deploymentId(deployment.getId()).singleResult(); - repositoryService.setProcessDefinitionCategory(definition.getId(), model.getCategory()); - //更新流程定义配置 - if (processDefinition != null) { - WfDefinitionConfigVo definitionVo = wfDefinitionConfigService.getByDefId(processDefinition.getId()); - if (definitionVo != null) { - wfDefinitionConfigService.deleteByDefIds(Collections.singletonList(processDefinition.getId())); - WfDefinitionConfigBo wfFormDefinition = new WfDefinitionConfigBo(); - wfFormDefinition.setDefinitionId(definition.getId()); - wfFormDefinition.setProcessKey(definition.getKey()); - wfFormDefinition.setTableName(definitionVo.getTableName()); - wfFormDefinition.setVersion(definition.getVersion()); - wfFormDefinition.setRemark(definitionVo.getRemark()); - wfDefinitionConfigService.saveOrUpdate(wfFormDefinition); - } - } - //更新流程节点配置表单 - List userTasks = ModelUtils.getUserTaskFlowElements(definition.getId()); - UserTask applyUserTask = ModelUtils.getApplyUserTask(definition.getId()); - List wfNodeConfigList = new ArrayList<>(); - for (UserTask userTask : userTasks) { - if (StringUtils.isNotBlank(userTask.getFormKey()) && userTask.getFormKey().contains(StrUtil.COLON)) { - WfNodeConfig wfNodeConfig = new WfNodeConfig(); - wfNodeConfig.setNodeId(userTask.getId()); - wfNodeConfig.setNodeName(userTask.getName()); - wfNodeConfig.setDefinitionId(definition.getId()); - String[] split = userTask.getFormKey().split(StrUtil.COLON); - wfNodeConfig.setFormType(split[0]); - wfNodeConfig.setFormId(Long.valueOf(split[1])); - wfNodeConfig.setApplyUserTask(applyUserTask.getId().equals(userTask.getId()) ? FlowConstant.TRUE : FlowConstant.FALSE); - wfNodeConfigList.add(wfNodeConfig); - } - } - if (CollUtil.isNotEmpty(wfNodeConfigList)) { - wfNodeConfigService.saveOrUpdate(wfNodeConfigList); - } - return true; - } catch (Exception e) { - log.error(e.getMessage(), e); - throw new ServiceException(e.getMessage()); - } - } - - /** - * 导出模型zip压缩包 - * - * @param modelIds 模型id - * @param response 相应 - */ - @Override - public void exportZip(List modelIds, HttpServletResponse response) { - try (ZipOutputStream zos = ZipUtil.getZipOutputStream(response.getOutputStream(), StandardCharsets.UTF_8)) { - // 压缩包文件名 - String zipName = "模型不存在"; - // 查询模型基本信息 - for (String modelId : modelIds) { - Model model = repositoryService.getModel(modelId); - byte[] xmlBytes = repositoryService.getModelEditorSource(modelId); - if (ObjectUtil.isNotNull(model)) { - if (JSONUtil.isTypeJSON(new String(xmlBytes, StandardCharsets.UTF_8)) && ArrayUtil.isEmpty(ModelUtils.bpmnJsonToXmlBytes(xmlBytes))) { - zipName = "模型不能为空,请至少设计一条主线流程!"; - zos.putNextEntry(new ZipEntry(zipName + ".txt")); - zos.write(zipName.getBytes(StandardCharsets.UTF_8)); - } else if (ArrayUtil.isEmpty(xmlBytes)) { - zipName = "模型数据为空,请先设计流程定义模型,再进行部署!"; - zos.putNextEntry(new ZipEntry(zipName + ".txt")); - zos.write(zipName.getBytes(StandardCharsets.UTF_8)); - } else { - String fileName = model.getName() + "-" + model.getKey(); - // 压缩包文件名 - zipName = fileName + ".zip"; - // 将xml添加到压缩包中(指定xml文件名:请假流程.bpmn20.xml - zos.putNextEntry(new ZipEntry(fileName + ".bpmn20.xml")); - zos.write(xmlBytes); - } - } - } - response.setHeader("Content-Disposition", - "attachment; filename=" + URLEncoder.encode(zipName, StandardCharsets.UTF_8) + ".zip"); - response.addHeader("Access-Control-Expose-Headers", "Content-Disposition"); - // 刷出响应流 - response.flushBuffer(); - } catch (IOException e) { - log.error(e.getMessage(), e); - } - } - - /** - * 复制模型 - * - * @param modelBo 模型数据 - * @return 结果 - */ - @Override - @Transactional(rollbackFor = Exception.class) - public boolean copyModel(ModelBo modelBo) { - try { - String key = modelBo.getKey(); - if (StringUtils.isNotBlank(key)) { - // 查询模型 - Model model = repositoryService.createModelQuery().modelId(modelBo.getId()).singleResult(); - if (ObjectUtil.isNotNull(model)) { - byte[] modelEditorSource = repositoryService.getModelEditorSource(model.getId()); - List list = QueryUtils.modelQuery().modelKey(key).list(); - if (CollUtil.isNotEmpty(list)) { - throw new ServiceException("模型KEY已存在!"); - } - // 校验key命名规范 - if (!Validator.isMatchRegex(FlowConstant.MODEL_KEY_PATTERN, key)) { - throw new ServiceException("模型标识KEY只能字符或者下划线开头!"); - } - // 复制模型数据 - Model newModel = repositoryService.newModel(); - newModel.setKey(modelBo.getKey()); - newModel.setName(modelBo.getName()); - newModel.setCategory(modelBo.getCategoryCode()); - newModel.setVersion(1); - newModel.setMetaInfo(modelBo.getDescription()); - newModel.setTenantId(TenantHelper.getTenantId()); - String xml = StrUtil.utf8Str(modelEditorSource); - BpmnModel bpmnModel = ModelUtils.xmlToBpmnModel(xml); - Process mainProcess = bpmnModel.getMainProcess(); - mainProcess.setId(modelBo.getKey()); - mainProcess.setName(modelBo.getName()); - byte[] xmlBytes = new BpmnXMLConverter().convertToXML(bpmnModel); - repositoryService.saveModel(newModel); - repositoryService.addModelEditorSource(newModel.getId(), xmlBytes); - } - } - } catch (Exception e) { - log.error(e.getMessage(), e); - throw new ServiceException(e.getMessage()); - } - return true; - } -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActProcessDefinitionServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActProcessDefinitionServiceImpl.java deleted file mode 100644 index 77fb257b5..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActProcessDefinitionServiceImpl.java +++ /dev/null @@ -1,444 +0,0 @@ -package org.dromara.workflow.service.impl; - -import cn.hutool.core.bean.BeanUtil; -import cn.hutool.core.codec.Base64; -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.io.FileUtil; -import cn.hutool.core.io.IoUtil; -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.core.util.StrUtil; -import lombok.RequiredArgsConstructor; -import lombok.SneakyThrows; -import lombok.extern.slf4j.Slf4j; -import org.dromara.common.core.exception.ServiceException; -import org.dromara.common.core.utils.StreamUtils; -import org.dromara.common.core.utils.StringUtils; -import org.dromara.common.mybatis.core.page.PageQuery; -import org.dromara.common.mybatis.core.page.TableDataInfo; -import org.dromara.common.tenant.helper.TenantHelper; -import org.dromara.workflow.common.constant.FlowConstant; -import org.dromara.workflow.domain.WfCategory; -import org.dromara.workflow.domain.WfDefinitionConfig; -import org.dromara.workflow.domain.WfNodeConfig; -import org.dromara.workflow.domain.bo.ProcessDefinitionBo; -import org.dromara.workflow.domain.bo.WfDefinitionConfigBo; -import org.dromara.workflow.domain.vo.ProcessDefinitionVo; -import org.dromara.workflow.domain.vo.WfDefinitionConfigVo; -import org.dromara.workflow.mapper.WfDefinitionConfigMapper; -import org.dromara.workflow.service.IActProcessDefinitionService; -import org.dromara.workflow.service.IWfCategoryService; -import org.dromara.workflow.service.IWfDefinitionConfigService; -import org.dromara.workflow.service.IWfNodeConfigService; -import org.dromara.workflow.utils.ModelUtils; -import org.dromara.workflow.utils.QueryUtils; -import org.flowable.bpmn.model.UserTask; -import org.flowable.engine.ProcessMigrationService; -import org.flowable.engine.RepositoryService; -import org.flowable.engine.history.HistoricProcessInstance; -import org.flowable.engine.impl.bpmn.deployer.ResourceNameUtil; -import org.flowable.engine.repository.*; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.web.multipart.MultipartFile; - -import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Set; -import java.util.zip.ZipEntry; -import java.util.zip.ZipInputStream; - -/** - * 流程定义 服务层实现 - * - * @author may - */ -@Slf4j -@RequiredArgsConstructor -@Service -public class ActProcessDefinitionServiceImpl implements IActProcessDefinitionService { - - @Autowired(required = false) - private RepositoryService repositoryService; - @Autowired(required = false) - private ProcessMigrationService processMigrationService; - private final IWfCategoryService wfCategoryService; - private final IWfDefinitionConfigService wfDefinitionConfigService; - private final WfDefinitionConfigMapper wfDefinitionConfigMapper; - private final IWfNodeConfigService wfNodeConfigService; - - /** - * 分页查询 - * - * @param bo 参数 - * @return 返回分页列表 - */ - @Override - public TableDataInfo page(ProcessDefinitionBo bo, PageQuery pageQuery) { - ProcessDefinitionQuery query = QueryUtils.definitionQuery(); - if (StringUtils.isNotEmpty(bo.getKey())) { - query.processDefinitionKey(bo.getKey()); - } - if (StringUtils.isNotEmpty(bo.getCategoryCode())) { - query.processDefinitionCategory(bo.getCategoryCode()); - } - if (StringUtils.isNotEmpty(bo.getName())) { - query.processDefinitionNameLike("%" + bo.getName() + "%"); - } - query.orderByDeploymentId().desc(); - // 分页查询 - List processDefinitionVoList = new ArrayList<>(); - List definitionList = query.latestVersion().listPage(pageQuery.getFirstNum(), pageQuery.getPageSize()); - List deploymentList = null; - if (CollUtil.isNotEmpty(definitionList)) { - List deploymentIds = StreamUtils.toList(definitionList, ProcessDefinition::getDeploymentId); - deploymentList = QueryUtils.deploymentQuery(deploymentIds).list(); - } - if (CollUtil.isNotEmpty(definitionList)) { - List ids = StreamUtils.toList(definitionList, ProcessDefinition::getId); - List wfDefinitionConfigVos = wfDefinitionConfigService.queryList(ids); - for (ProcessDefinition processDefinition : definitionList) { - ProcessDefinitionVo processDefinitionVo = BeanUtil.toBean(processDefinition, ProcessDefinitionVo.class); - if (CollUtil.isNotEmpty(deploymentList)) { - // 部署时间 - deploymentList.stream().filter(e -> e.getId().equals(processDefinition.getDeploymentId())).findFirst().ifPresent(e -> { - processDefinitionVo.setDeploymentTime(e.getDeploymentTime()); - }); - } - if (CollUtil.isNotEmpty(wfDefinitionConfigVos)) { - wfDefinitionConfigVos.stream().filter(e -> e.getDefinitionId().equals(processDefinition.getId())).findFirst().ifPresent(processDefinitionVo::setWfDefinitionConfigVo); - } - processDefinitionVoList.add(processDefinitionVo); - } - } - // 总记录数 - long total = query.count(); - TableDataInfo build = TableDataInfo.build(); - build.setRows(processDefinitionVoList); - build.setTotal(total); - return build; - } - - /** - * 查询历史流程定义列表 - * - * @param key 流程定义key - */ - @Override - public List getListByKey(String key) { - List processDefinitionVoList = new ArrayList<>(); - ProcessDefinitionQuery query = QueryUtils.definitionQuery(); - List definitionList = query.processDefinitionKey(key).list(); - List deploymentList = null; - if (CollUtil.isNotEmpty(definitionList)) { - List deploymentIds = StreamUtils.toList(definitionList, ProcessDefinition::getDeploymentId); - deploymentList = QueryUtils.deploymentQuery(deploymentIds).list(); - } - if (CollUtil.isNotEmpty(definitionList)) { - List ids = StreamUtils.toList(definitionList, ProcessDefinition::getId); - List wfDefinitionConfigVos = wfDefinitionConfigService.queryList(ids); - for (ProcessDefinition processDefinition : definitionList) { - ProcessDefinitionVo processDefinitionVo = BeanUtil.toBean(processDefinition, ProcessDefinitionVo.class); - if (CollUtil.isNotEmpty(deploymentList)) { - // 部署时间 - deploymentList.stream().filter(e -> e.getId().equals(processDefinition.getDeploymentId())).findFirst().ifPresent(e -> { - processDefinitionVo.setDeploymentTime(e.getDeploymentTime()); - }); - if (CollUtil.isNotEmpty(wfDefinitionConfigVos)) { - wfDefinitionConfigVos.stream().filter(e -> e.getDefinitionId().equals(processDefinition.getId())).findFirst().ifPresent(processDefinitionVo::setWfDefinitionConfigVo); - } - } - processDefinitionVoList.add(processDefinitionVo); - } - } - return CollUtil.reverse(processDefinitionVoList); - } - - /** - * 查看流程定义图片 - * - * @param processDefinitionId 流程定义id - */ - @SneakyThrows - @Override - public String definitionImage(String processDefinitionId) { - InputStream inputStream = repositoryService.getProcessDiagram(processDefinitionId); - return Base64.encode(IoUtil.readBytes(inputStream)); - } - - /** - * 查看流程定义xml文件 - * - * @param processDefinitionId 流程定义id - */ - @Override - public String definitionXml(String processDefinitionId) { - StringBuilder xml = new StringBuilder(); - ProcessDefinition processDefinition = repositoryService.getProcessDefinition(processDefinitionId); - InputStream inputStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), processDefinition.getResourceName()); - xml.append(IoUtil.read(inputStream, StandardCharsets.UTF_8)); - return xml.toString(); - } - - /** - * 删除流程定义 - * - * @param deploymentIds 部署id - * @param processDefinitionIds 流程定义id - */ - @Override - @Transactional(rollbackFor = Exception.class) - public boolean deleteDeployment(List deploymentIds, List processDefinitionIds) { - try { - List historicProcessInstances = QueryUtils.hisInstanceQuery().deploymentIdIn(deploymentIds).list(); - if (CollUtil.isNotEmpty(historicProcessInstances)) { - Set defIds = StreamUtils.toSet(historicProcessInstances, HistoricProcessInstance::getProcessDefinitionId); - List processDefinitions = QueryUtils.definitionQuery().processDefinitionIds(defIds).list(); - if (CollUtil.isNotEmpty(processDefinitions)) { - Set keys = StreamUtils.toSet(processDefinitions, ProcessDefinition::getKey); - throw new ServiceException("当前【" + String.join(",", keys) + "】流程定义已被使用不可删除!"); - } - } - //删除流程定义 - for (String deploymentId : deploymentIds) { - repositoryService.deleteDeployment(deploymentId); - } - //删除流程定义配置 - wfDefinitionConfigService.deleteByDefIds(processDefinitionIds); - //删除节点配置 - wfNodeConfigService.deleteByDefIds(processDefinitionIds); - return true; - } catch (Exception e) { - log.error(e.getMessage(), e); - throw new ServiceException(e.getMessage()); - } - } - - /** - * 激活或者挂起流程定义 - * - * @param processDefinitionId 流程定义id - */ - @Override - public boolean updateDefinitionState(String processDefinitionId) { - try { - ProcessDefinition processDefinition = QueryUtils.definitionQuery() - .processDefinitionId(processDefinitionId).singleResult(); - //将当前为挂起状态更新为激活状态 - //参数说明:参数1:流程定义id,参数2:是否激活(true是否级联对应流程实例,激活了则对应流程实例都可以审批), - //参数3:什么时候激活,如果为null则立即激活,如果为具体时间则到达此时间后激活 - if (processDefinition.isSuspended()) { - repositoryService.activateProcessDefinitionById(processDefinitionId, true, null); - } else { - repositoryService.suspendProcessDefinitionById(processDefinitionId, true, null); - } - return true; - } catch (Exception e) { - log.error(e.getMessage(), e); - throw new ServiceException("操作失败:" + e.getMessage()); - } - } - - /** - * 迁移流程定义 - * - * @param currentProcessDefinitionId 当前流程定义id - * @param fromProcessDefinitionId 需要迁移到的流程定义id - */ - - @Override - public boolean migrationDefinition(String currentProcessDefinitionId, String fromProcessDefinitionId) { - try { - // 迁移验证 - boolean migrationValid = processMigrationService.createProcessInstanceMigrationBuilder() - .migrateToProcessDefinition(currentProcessDefinitionId) - .validateMigrationOfProcessInstances(fromProcessDefinitionId) - .isMigrationValid(); - if (!migrationValid) { - throw new ServiceException("流程定义差异过大无法迁移,请修改流程图"); - } - // 已结束的流程实例不会迁移 - processMigrationService.createProcessInstanceMigrationBuilder() - .migrateToProcessDefinition(currentProcessDefinitionId) - .migrateProcessInstances(fromProcessDefinitionId); - return true; - } catch (Exception e) { - log.error(e.getMessage(), e); - throw new ServiceException(e.getMessage()); - } - } - - /** - * 流程定义转换为模型 - * - * @param processDefinitionId 流程定义id - */ - @Override - public boolean convertToModel(String processDefinitionId) { - ProcessDefinition pd = QueryUtils.definitionQuery() - .processDefinitionId(processDefinitionId).singleResult(); - InputStream inputStream = repositoryService.getResourceAsStream(pd.getDeploymentId(), pd.getResourceName()); - ModelQuery query = QueryUtils.modelQuery(); - Model model = query.modelKey(pd.getKey()).singleResult(); - try { - if (ObjectUtil.isNotNull(model)) { - repositoryService.addModelEditorSource(model.getId(), IoUtil.readBytes(inputStream)); - } else { - Model modelData = repositoryService.newModel(); - modelData.setKey(pd.getKey()); - modelData.setName(pd.getName()); - modelData.setCategory(pd.getCategory()); - modelData.setTenantId(pd.getTenantId()); - repositoryService.saveModel(modelData); - repositoryService.addModelEditorSource(modelData.getId(), IoUtil.readBytes(inputStream)); - } - return true; - } catch (Exception e) { - log.error(e.getMessage(), e); - throw new ServiceException(e.getMessage()); - } - } - - /** - * 通过zip或xml部署流程定义 - * - * @param file 文件 - * @param categoryCode 分类 - */ - @SneakyThrows - @Override - @Transactional(rollbackFor = Exception.class) - public void deployByFile(MultipartFile file, String categoryCode) { - - WfCategory wfCategory = wfCategoryService.queryByCategoryCode(categoryCode); - if (wfCategory == null) { - throw new ServiceException("流程分类不存在"); - } - // 文件后缀名 - String suffix = FileUtil.extName(file.getOriginalFilename()); - InputStream inputStream = file.getInputStream(); - if (FlowConstant.ZIP.equalsIgnoreCase(suffix)) { - ZipInputStream zipInputStream = null; - try { - zipInputStream = new ZipInputStream(inputStream); - ZipEntry zipEntry; - while ((zipEntry = zipInputStream.getNextEntry()) != null) { - String filename = zipEntry.getName(); - String[] splitFilename = filename.substring(0, filename.lastIndexOf(".")).split("-"); - //流程名称 - String processName = splitFilename[0]; - //流程key - String processKey = splitFilename[1]; - ProcessDefinition oldProcessDefinition = QueryUtils.definitionQuery().processDefinitionKey(processKey).latestVersion().singleResult(); - DeploymentBuilder builder = repositoryService.createDeployment(); - Deployment deployment = builder.addInputStream(filename, zipInputStream) - .tenantId(TenantHelper.getTenantId()) - .name(processName).key(processKey).category(categoryCode).deploy(); - ProcessDefinition definition = QueryUtils.definitionQuery().deploymentId(deployment.getId()).singleResult(); - repositoryService.setProcessDefinitionCategory(definition.getId(), categoryCode); - setWfConfig(oldProcessDefinition, definition); - zipInputStream.closeEntry(); - } - } catch (IOException e) { - throw new RuntimeException(e); - } finally { - if (zipInputStream != null) { - zipInputStream.close(); - } - } - //初始化配置数据(demo使用,不用可删除) - initWfDefConfig(); - } else { - String originalFilename = file.getOriginalFilename(); - if (StringUtils.containsAny(originalFilename, ResourceNameUtil.BPMN_RESOURCE_SUFFIXES)) { - // 文件名 = 流程名称-流程key - String[] splitFilename = originalFilename.substring(0, originalFilename.lastIndexOf(".")).split("-"); - if (splitFilename.length < 2) { - throw new ServiceException("文件名 = 流程名称-流程KEY"); - } - //流程名称 - String processName = splitFilename[0]; - //流程key - String processKey = splitFilename[1]; - ProcessDefinition oldProcessDefinition = QueryUtils.definitionQuery().processDefinitionKey(processKey).latestVersion().singleResult(); - DeploymentBuilder builder = repositoryService.createDeployment(); - Deployment deployment = builder.addInputStream(originalFilename, inputStream) - .tenantId(TenantHelper.getTenantId()) - .name(processName).key(processKey).category(categoryCode).deploy(); - // 更新分类 - ProcessDefinition definition = QueryUtils.definitionQuery().deploymentId(deployment.getId()).singleResult(); - repositoryService.setProcessDefinitionCategory(definition.getId(), categoryCode); - setWfConfig(oldProcessDefinition, definition); - } else { - throw new ServiceException("文件类型上传错误!"); - } - } - - } - - /** - * 初始化配置数据(demo使用,不用可删除) - */ - private void initWfDefConfig() { - List wfDefinitionConfigs = wfDefinitionConfigMapper.selectList(); - if (CollUtil.isEmpty(wfDefinitionConfigs)) { - ProcessDefinition processDefinition = QueryUtils.definitionQuery().processDefinitionKey("leave1").latestVersion().singleResult(); - if (processDefinition != null) { - WfDefinitionConfigBo wfDefinitionConfigBo = new WfDefinitionConfigBo(); - wfDefinitionConfigBo.setDefinitionId(processDefinition.getId()); - wfDefinitionConfigBo.setProcessKey(processDefinition.getKey()); - wfDefinitionConfigBo.setTableName("test_leave"); - wfDefinitionConfigBo.setVersion(processDefinition.getVersion()); - wfDefinitionConfigService.saveOrUpdate(wfDefinitionConfigBo); - } - } - - } - - /** - * 设置表单内容 - * - * @param oldProcessDefinition 部署前最新流程定义 - * @param definition 部署后最新流程定义 - */ - private void setWfConfig(ProcessDefinition oldProcessDefinition, ProcessDefinition definition) { - //更新流程定义表单 - if (oldProcessDefinition != null) { - WfDefinitionConfigVo definitionVo = wfDefinitionConfigService.getByDefId(oldProcessDefinition.getId()); - if (definitionVo != null) { - wfDefinitionConfigService.deleteByDefIds(Collections.singletonList(oldProcessDefinition.getId())); - WfDefinitionConfigBo wfDefinitionConfigBo = new WfDefinitionConfigBo(); - wfDefinitionConfigBo.setDefinitionId(definition.getId()); - wfDefinitionConfigBo.setProcessKey(definition.getKey()); - wfDefinitionConfigBo.setTableName(definitionVo.getTableName()); - wfDefinitionConfigBo.setVersion(definition.getVersion()); - wfDefinitionConfigBo.setRemark(definitionVo.getRemark()); - wfDefinitionConfigService.saveOrUpdate(wfDefinitionConfigBo); - } - } - //更新流程节点配置表单 - List userTasks = ModelUtils.getUserTaskFlowElements(definition.getId()); - UserTask applyUserTask = ModelUtils.getApplyUserTask(definition.getId()); - List wfNodeConfigList = new ArrayList<>(); - for (UserTask userTask : userTasks) { - if (StringUtils.isNotBlank(userTask.getFormKey()) && userTask.getFormKey().contains(StrUtil.COLON)) { - WfNodeConfig wfNodeConfig = new WfNodeConfig(); - wfNodeConfig.setNodeId(userTask.getId()); - wfNodeConfig.setNodeName(userTask.getName()); - wfNodeConfig.setDefinitionId(definition.getId()); - String[] split = userTask.getFormKey().split(StrUtil.COLON); - wfNodeConfig.setFormType(split[0]); - wfNodeConfig.setFormId(Long.valueOf(split[1])); - wfNodeConfig.setApplyUserTask(applyUserTask.getId().equals(userTask.getId()) ? FlowConstant.TRUE : FlowConstant.FALSE); - wfNodeConfigList.add(wfNodeConfig); - } - } - if (CollUtil.isNotEmpty(wfNodeConfigList)) { - wfNodeConfigService.saveOrUpdate(wfNodeConfigList); - } - } -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActProcessInstanceServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActProcessInstanceServiceImpl.java deleted file mode 100644 index 8b9b113fd..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActProcessInstanceServiceImpl.java +++ /dev/null @@ -1,691 +0,0 @@ -package org.dromara.workflow.service.impl; - -import cn.hutool.core.bean.BeanUtil; -import cn.hutool.core.codec.Base64; -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.convert.Convert; -import cn.hutool.core.io.IoUtil; -import cn.hutool.core.util.ObjectUtil; -import lombok.RequiredArgsConstructor; -import lombok.SneakyThrows; -import lombok.extern.slf4j.Slf4j; -import org.dromara.common.core.enums.BusinessStatusEnum; -import org.dromara.common.core.exception.ServiceException; -import org.dromara.common.core.service.UserService; -import org.dromara.common.core.utils.StreamUtils; -import org.dromara.common.core.utils.StringUtils; -import org.dromara.common.mybatis.core.page.PageQuery; -import org.dromara.common.mybatis.core.page.TableDataInfo; -import org.dromara.common.satoken.utils.LoginHelper; -import org.dromara.workflow.common.constant.FlowConstant; -import org.dromara.workflow.common.enums.TaskStatusEnum; -import org.dromara.workflow.domain.ActHiProcinst; -import org.dromara.workflow.domain.bo.ProcessInstanceBo; -import org.dromara.workflow.domain.bo.ProcessInvalidBo; -import org.dromara.workflow.domain.bo.TaskUrgingBo; -import org.dromara.workflow.domain.vo.*; -import org.dromara.workflow.flowable.CustomDefaultProcessDiagramGenerator; -import org.dromara.workflow.flowable.cmd.DeleteExecutionCmd; -import org.dromara.workflow.flowable.cmd.ExecutionChildByExecutionIdCmd; -import org.dromara.workflow.flowable.handler.FlowProcessEventHandler; -import org.dromara.workflow.service.IActHiProcinstService; -import org.dromara.workflow.service.IActProcessInstanceService; -import org.dromara.workflow.service.IWfNodeConfigService; -import org.dromara.workflow.service.IWfTaskBackNodeService; -import org.dromara.workflow.utils.QueryUtils; -import org.dromara.workflow.utils.WorkflowUtils; -import org.flowable.bpmn.model.BpmnModel; -import org.flowable.engine.*; -import org.flowable.engine.history.HistoricActivityInstance; -import org.flowable.engine.history.HistoricProcessInstance; -import org.flowable.engine.history.HistoricProcessInstanceQuery; -import org.flowable.engine.impl.persistence.entity.ExecutionEntity; -import org.flowable.engine.repository.ProcessDefinition; -import org.flowable.engine.runtime.ProcessInstance; -import org.flowable.engine.runtime.ProcessInstanceQuery; -import org.flowable.engine.task.Attachment; -import org.flowable.engine.task.Comment; -import org.flowable.task.api.Task; -import org.flowable.task.api.history.HistoricTaskInstance; -import org.springframework.beans.BeanUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.awt.*; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; -import java.util.List; -import java.util.*; - -/** - * 流程实例 服务层实现 - * - * @author may - */ -@Slf4j -@RequiredArgsConstructor -@Service -public class ActProcessInstanceServiceImpl implements IActProcessInstanceService { - - @Autowired(required = false) - private RepositoryService repositoryService; - @Autowired(required = false) - private RuntimeService runtimeService; - @Autowired(required = false) - private HistoryService historyService; - @Autowired(required = false) - private TaskService taskService; - @Autowired(required = false) - private ManagementService managementService; - private final IActHiProcinstService actHiProcinstService; - private final IWfTaskBackNodeService wfTaskBackNodeService; - private final IWfNodeConfigService wfNodeConfigService; - private final FlowProcessEventHandler flowProcessEventHandler; - private final UserService userService; - - @Value("${flowable.activity-font-name}") - private String activityFontName; - - @Value("${flowable.label-font-name}") - private String labelFontName; - - @Value("${flowable.annotation-font-name}") - private String annotationFontName; - - /** - * 分页查询正在运行的流程实例 - * - * @param bo 参数 - */ - @Override - public TableDataInfo getPageByRunning(ProcessInstanceBo bo, PageQuery pageQuery) { - List list = new ArrayList<>(); - ProcessInstanceQuery query = QueryUtils.instanceQuery(); - if (StringUtils.isNotBlank(bo.getName())) { - query.processInstanceNameLikeIgnoreCase("%" + bo.getName() + "%"); - } - if (StringUtils.isNotBlank(bo.getKey())) { - query.processDefinitionKey(bo.getKey()); - } - if (StringUtils.isNotBlank(bo.getStartUserId())) { - query.startedBy(bo.getStartUserId()); - } - if (StringUtils.isNotBlank(bo.getBusinessKey())) { - query.processInstanceBusinessKey(bo.getBusinessKey()); - } - if (StringUtils.isNotBlank(bo.getCategoryCode())) { - query.processDefinitionCategory(bo.getCategoryCode()); - } - query.orderByStartTime().desc(); - List processInstances = query.listPage(pageQuery.getFirstNum(), pageQuery.getPageSize()); - for (ProcessInstance processInstance : processInstances) { - ProcessInstanceVo processInstanceVo = BeanUtil.toBean(processInstance, ProcessInstanceVo.class); - processInstanceVo.setIsSuspended(processInstance.isSuspended()); - processInstanceVo.setBusinessStatusName(BusinessStatusEnum.findByStatus(processInstance.getBusinessStatus())); - list.add(processInstanceVo); - } - if (CollUtil.isNotEmpty(list)) { - List processDefinitionIds = StreamUtils.toList(list, ProcessInstanceVo::getProcessDefinitionId); - List wfNodeConfigVoList = wfNodeConfigService.selectByDefIds(processDefinitionIds); - for (ProcessInstanceVo processInstanceVo : list) { - if (CollUtil.isNotEmpty(wfNodeConfigVoList)) { - wfNodeConfigVoList.stream().filter(e -> e.getDefinitionId().equals(processInstanceVo.getProcessDefinitionId()) && FlowConstant.TRUE.equals(e.getApplyUserTask())).findFirst().ifPresent(processInstanceVo::setWfNodeConfigVo); - } - } - } - long count = query.count(); - TableDataInfo build = TableDataInfo.build(); - build.setRows(list); - build.setTotal(count); - return build; - } - - /** - * 分页查询已结束的流程实例 - * - * @param bo 参数 - */ - @Override - public TableDataInfo getPageByFinish(ProcessInstanceBo bo, PageQuery pageQuery) { - List list = new ArrayList<>(); - HistoricProcessInstanceQuery query = QueryUtils.hisInstanceQuery() - .finished().orderByProcessInstanceEndTime().desc(); - if (StringUtils.isNotEmpty(bo.getName())) { - query.processInstanceNameLikeIgnoreCase("%" + bo.getName() + "%"); - } - if (StringUtils.isNotBlank(bo.getKey())) { - query.processDefinitionKey(bo.getKey()); - } - if (StringUtils.isNotEmpty(bo.getStartUserId())) { - query.startedBy(bo.getStartUserId()); - } - if (StringUtils.isNotBlank(bo.getBusinessKey())) { - query.processInstanceBusinessKey(bo.getBusinessKey()); - } - if (StringUtils.isNotBlank(bo.getCategoryCode())) { - query.processDefinitionCategory(bo.getCategoryCode()); - } - List historicProcessInstances = query.listPage(pageQuery.getFirstNum(), pageQuery.getPageSize()); - for (HistoricProcessInstance historicProcessInstance : historicProcessInstances) { - ProcessInstanceVo processInstanceVo = BeanUtil.toBean(historicProcessInstance, ProcessInstanceVo.class); - processInstanceVo.setBusinessStatusName(BusinessStatusEnum.findByStatus(historicProcessInstance.getBusinessStatus())); - list.add(processInstanceVo); - } - if (CollUtil.isNotEmpty(list)) { - List processDefinitionIds = StreamUtils.toList(list, ProcessInstanceVo::getProcessDefinitionId); - List wfNodeConfigVoList = wfNodeConfigService.selectByDefIds(processDefinitionIds); - for (ProcessInstanceVo processInstanceVo : list) { - if (CollUtil.isNotEmpty(wfNodeConfigVoList)) { - wfNodeConfigVoList.stream().filter(e -> e.getDefinitionId().equals(processInstanceVo.getProcessDefinitionId()) && FlowConstant.TRUE.equals(e.getApplyUserTask())).findFirst().ifPresent(processInstanceVo::setWfNodeConfigVo); - } - } - } - long count = query.count(); - TableDataInfo build = TableDataInfo.build(); - build.setRows(list); - build.setTotal(count); - return build; - } - - /** - * 通过业务id获取历史流程图 - * - * @param businessKey 业务id - */ - @SneakyThrows - @Override - public String getHistoryImage(String businessKey) { - String processDefinitionId; - // 获取当前的流程实例 - ProcessInstance processInstance = QueryUtils.businessKeyQuery(businessKey).singleResult(); - // 如果流程已经结束,则得到结束节点 - if (Objects.isNull(processInstance)) { - HistoricProcessInstance pi = QueryUtils.hisInstanceQuery().processInstanceBusinessKey(businessKey).singleResult(); - processDefinitionId = pi.getProcessDefinitionId(); - } else { - // 根据流程实例ID获得当前处于活动状态的ActivityId合集 - ProcessInstance pi = QueryUtils.instanceQuery(processInstance.getProcessInstanceId()).singleResult(); - processDefinitionId = pi.getProcessDefinitionId(); - } - - // 获得活动的节点 - List highLightedFlowList = QueryUtils.hisActivityInstanceQuery(processInstance.getProcessInstanceId()).orderByHistoricActivityInstanceStartTime().asc().list(); - - List highLightedFlows = new ArrayList<>(); - List highLightedNodes = new ArrayList<>(); - //高亮 - for (HistoricActivityInstance tempActivity : highLightedFlowList) { - if (FlowConstant.SEQUENCE_FLOW.equals(tempActivity.getActivityType())) { - //高亮线 - highLightedFlows.add(tempActivity.getActivityId()); - } else { - //高亮节点 - if (tempActivity.getEndTime() == null) { - highLightedNodes.add(Color.RED.toString() + tempActivity.getActivityId()); - } else { - highLightedNodes.add(tempActivity.getActivityId()); - } - } - } - List highLightedNodeList = new ArrayList<>(); - //运行中的节点 - List redNodeCollect = StreamUtils.filter(highLightedNodes, e -> e.contains(Color.RED.toString())); - //排除与运行中相同的节点 - for (String nodeId : highLightedNodes) { - if (!nodeId.contains(Color.RED.toString()) && !redNodeCollect.contains(Color.RED + nodeId)) { - highLightedNodeList.add(nodeId); - } - } - highLightedNodeList.addAll(redNodeCollect); - BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId); - CustomDefaultProcessDiagramGenerator diagramGenerator = new CustomDefaultProcessDiagramGenerator(); - InputStream inputStream = diagramGenerator.generateDiagram(bpmnModel, "png", highLightedNodeList, highLightedFlows, activityFontName, labelFontName, annotationFontName, null, 1.0, true); - return Base64.encode(IoUtil.readBytes(inputStream)); - } - - /** - * 通过业务id获取历史流程图运行中,历史等节点 - * - * @param businessKey 业务id - */ - @Override - public Map getHistoryList(String businessKey) { - Map map = new HashMap<>(); - List> taskList = new ArrayList<>(); - HistoricProcessInstance historicProcessInstance = QueryUtils.hisBusinessKeyQuery(businessKey).singleResult(); - String processInstanceId = historicProcessInstance.getId(); - StringBuilder xml = new StringBuilder(); - ProcessDefinition processDefinition = repositoryService.getProcessDefinition(historicProcessInstance.getProcessDefinitionId()); - // 获取节点 - List highLightedFlowList = QueryUtils.hisActivityInstanceQuery(processInstanceId).orderByHistoricActivityInstanceStartTime().asc().list(); - for (HistoricActivityInstance tempActivity : highLightedFlowList) { - Map task = new HashMap<>(); - switch (tempActivity.getActivityType()) { - case FlowConstant.SEQUENCE_FLOW, FlowConstant.PARALLEL_GATEWAY, - FlowConstant.EXCLUSIVE_GATEWAY, FlowConstant.INCLUSIVE_GATEWAY -> {} - default -> { - task.put("key", tempActivity.getActivityId()); - task.put("completed", tempActivity.getEndTime() != null); - task.put("activityType", tempActivity.getActivityType()); - taskList.add(task); - } - } - } - ProcessInstance processInstance = QueryUtils.instanceQuery(processInstanceId).singleResult(); - if (processInstance != null) { - taskList = StreamUtils.filter(taskList, e -> !e.get("activityType").equals(FlowConstant.END_EVENT)); - } - //查询出运行中节点 - List> runtimeNodeList = StreamUtils.filter(taskList, e -> !(Boolean) e.get("completed")); - if (CollUtil.isNotEmpty(runtimeNodeList)) { - Iterator> iterator = taskList.iterator(); - while (iterator.hasNext()) { - Map next = iterator.next(); - runtimeNodeList.stream().filter(t -> t.get("key").equals(next.get("key")) && (Boolean) next.get("completed")).findFirst().ifPresent(t -> iterator.remove()); - } - } - map.put("taskList", taskList); - List historyTaskList = getHistoryTaskList(processInstanceId, processDefinition.getVersion()); - map.put("historyList", historyTaskList); - InputStream inputStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), processDefinition.getResourceName()); - xml.append(IoUtil.read(inputStream, StandardCharsets.UTF_8)); - map.put("xml", xml.toString()); - return map; - } - - /** - * 获取历史任务节点信息 - * - * @param processInstanceId 流程实例id - * @param version 版本 - */ - private List getHistoryTaskList(String processInstanceId, Integer version) { - //查询任务办理记录 - List list = QueryUtils.hisTaskInstanceQuery(processInstanceId).orderByHistoricTaskInstanceEndTime().desc().list(); - list = StreamUtils.sorted(list, Comparator.comparing(HistoricTaskInstance::getEndTime, Comparator.nullsFirst(Date::compareTo)).reversed()); - List actHistoryInfoVoList = new ArrayList<>(); - for (HistoricTaskInstance historicTaskInstance : list) { - ActHistoryInfoVo actHistoryInfoVo = new ActHistoryInfoVo(); - BeanUtils.copyProperties(historicTaskInstance, actHistoryInfoVo); - actHistoryInfoVo.setStatus(actHistoryInfoVo.getEndTime() == null ? "待处理" : "已处理"); - if (ObjectUtil.isNotEmpty(historicTaskInstance.getDurationInMillis())) { - actHistoryInfoVo.setRunDuration(getDuration(historicTaskInstance.getDurationInMillis())); - } - actHistoryInfoVo.setVersion(version); - actHistoryInfoVoList.add(actHistoryInfoVo); - } - List historyInfoVoList = new ArrayList<>(); - Map> groupByKey = StreamUtils.groupByKey(actHistoryInfoVoList, ActHistoryInfoVo::getTaskDefinitionKey); - for (Map.Entry> entry : groupByKey.entrySet()) { - ActHistoryInfoVo historyInfoVo = new ActHistoryInfoVo(); - if (entry.getValue().size() > 1) { - List historyInfoVos = StreamUtils.filter(entry.getValue(), e -> StringUtils.isNotBlank(e.getAssignee())); - if (CollUtil.isNotEmpty(historyInfoVos)) { - ActHistoryInfoVo infoVo = historyInfoVos.get(0); - BeanUtils.copyProperties(infoVo, historyInfoVo); - historyInfoVo.setStatus(infoVo.getEndTime() == null ? "待处理" : "已处理"); - historyInfoVo.setStartTime(infoVo.getStartTime()); - historyInfoVo.setEndTime(infoVo.getEndTime() == null ? null : infoVo.getEndTime()); - historyInfoVo.setRunDuration(infoVo.getEndTime() == null ? null : infoVo.getRunDuration()); - if (ObjectUtil.isEmpty(infoVo.getAssignee())) { - ParticipantVo participantVo = WorkflowUtils.getCurrentTaskParticipant(infoVo.getId(), userService); - if (ObjectUtil.isNotEmpty(participantVo) && CollUtil.isNotEmpty(participantVo.getCandidate())) { - historyInfoVo.setAssignee(StreamUtils.join(participantVo.getCandidate(), Convert::toStr)); - } - } - } - } else { - actHistoryInfoVoList.stream().filter(e -> e.getTaskDefinitionKey().equals(entry.getKey())).findFirst() - .ifPresent(e -> { - BeanUtils.copyProperties(e, historyInfoVo); - historyInfoVo.setStatus(e.getEndTime() == null ? "待处理" : "已处理"); - historyInfoVo.setStartTime(e.getStartTime()); - historyInfoVo.setEndTime(e.getEndTime() == null ? null : e.getEndTime()); - historyInfoVo.setRunDuration(e.getEndTime() == null ? null : e.getRunDuration()); - if (ObjectUtil.isEmpty(e.getAssignee())) { - ParticipantVo participantVo = WorkflowUtils.getCurrentTaskParticipant(e.getId(), userService); - if (ObjectUtil.isNotEmpty(participantVo) && CollUtil.isNotEmpty(participantVo.getCandidate())) { - historyInfoVo.setAssignee(StreamUtils.join(participantVo.getCandidate(), Convert::toStr)); - } - } - }); - - } - historyInfoVoList.add(historyInfoVo); - - } - return historyInfoVoList; - } - - /** - * 获取审批记录 - * - * @param businessKey 业务id - */ - @Override - public List getHistoryRecord(String businessKey) { - // 查询任务办理记录 - List list = QueryUtils.hisTaskBusinessKeyQuery(businessKey).orderByHistoricTaskInstanceEndTime().desc().list(); - list = StreamUtils.sorted(list, Comparator.comparing(HistoricTaskInstance::getEndTime, Comparator.nullsFirst(Date::compareTo)).reversed()); - HistoricProcessInstance historicProcessInstance = QueryUtils.hisBusinessKeyQuery(businessKey).singleResult(); - String processInstanceId = historicProcessInstance.getId(); - List actHistoryInfoVoList = new ArrayList<>(); - List processInstanceComments = taskService.getProcessInstanceComments(processInstanceId); - //附件 - List attachmentList = taskService.getProcessInstanceAttachments(processInstanceId); - for (HistoricTaskInstance historicTaskInstance : list) { - ActHistoryInfoVo actHistoryInfoVo = new ActHistoryInfoVo(); - BeanUtils.copyProperties(historicTaskInstance, actHistoryInfoVo); - if (actHistoryInfoVo.getEndTime() == null) { - actHistoryInfoVo.setStatus(TaskStatusEnum.WAITING.getStatus()); - actHistoryInfoVo.setStatusName(TaskStatusEnum.WAITING.getDesc()); - } - if (CollUtil.isNotEmpty(processInstanceComments)) { - processInstanceComments.stream().filter(e -> e.getTaskId().equals(historicTaskInstance.getId())).findFirst().ifPresent(e -> { - actHistoryInfoVo.setComment(e.getFullMessage()); - actHistoryInfoVo.setStatus(e.getType()); - actHistoryInfoVo.setStatusName(TaskStatusEnum.findByStatus(e.getType())); - }); - } - if (ObjectUtil.isNotEmpty(historicTaskInstance.getDurationInMillis())) { - actHistoryInfoVo.setRunDuration(getDuration(historicTaskInstance.getDurationInMillis())); - } - //附件 - if (CollUtil.isNotEmpty(attachmentList)) { - List attachments = StreamUtils.filter(attachmentList, e -> e.getTaskId().equals(historicTaskInstance.getId())); - if (CollUtil.isNotEmpty(attachments)) { - actHistoryInfoVo.setAttachmentList(attachments); - } - } - //设置人员id - if (ObjectUtil.isEmpty(historicTaskInstance.getAssignee())) { - ParticipantVo participantVo = WorkflowUtils.getCurrentTaskParticipant(historicTaskInstance.getId(), userService); - if (ObjectUtil.isNotEmpty(participantVo) && CollUtil.isNotEmpty(participantVo.getCandidate())) { - actHistoryInfoVo.setAssignee(StreamUtils.join(participantVo.getCandidate(), Convert::toStr)); - } - } - actHistoryInfoVoList.add(actHistoryInfoVo); - } - // 审批记录 - Map> groupByKey = StreamUtils.groupByKey(actHistoryInfoVoList, ActHistoryInfoVo::getTaskDefinitionKey); - for (Map.Entry> entry : groupByKey.entrySet()) { - ActHistoryInfoVo actHistoryInfoVo = BeanUtil.toBean(entry.getValue().get(0), ActHistoryInfoVo.class); - actHistoryInfoVoList.stream().filter(e -> e.getTaskDefinitionKey().equals(entry.getKey()) && e.getEndTime() != null).findFirst() - .ifPresent(e -> { - actHistoryInfoVo.setStatus("已处理"); - actHistoryInfoVo.setStartTime(e.getStartTime()); - }); - actHistoryInfoVoList.stream().filter(e -> e.getTaskDefinitionKey().equals(entry.getKey()) && e.getEndTime() == null).findFirst() - .ifPresent(e -> { - actHistoryInfoVo.setStatus("待处理"); - actHistoryInfoVo.setStartTime(e.getStartTime()); - actHistoryInfoVo.setEndTime(null); - actHistoryInfoVo.setRunDuration(null); - }); - } - List recordList = new ArrayList<>(); - // 待办理 - recordList.addAll(StreamUtils.filter(actHistoryInfoVoList, e -> e.getEndTime() == null)); - // 已办理 - recordList.addAll(StreamUtils.filter(actHistoryInfoVoList, e -> e.getEndTime() != null)); - - return recordList; - } - - /** - * 任务完成时间处理 - * - * @param time 时间 - */ - private String getDuration(long time) { - - long day = time / (24 * 60 * 60 * 1000); - long hour = (time / (60 * 60 * 1000) - day * 24); - long minute = ((time / (60 * 1000)) - day * 24 * 60 - hour * 60); - long second = (time / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - minute * 60); - - if (day > 0) { - return day + "天" + hour + "小时" + minute + "分钟"; - } - if (hour > 0) { - return hour + "小时" + minute + "分钟"; - } - if (minute > 0) { - return minute + "分钟"; - } - if (second > 0) { - return second + "秒"; - } else { - return 0 + "秒"; - } - } - - /** - * 作废流程实例,不会删除历史记录(删除运行中的实例) - * - * @param processInvalidBo 参数 - */ - @Override - @Transactional(rollbackFor = Exception.class) - public boolean deleteRunInstance(ProcessInvalidBo processInvalidBo) { - try { - List list = QueryUtils.taskQuery().processInstanceBusinessKey(processInvalidBo.getBusinessKey()).list(); - String processInstanceId = list.get(0).getProcessInstanceId(); - List subTasks = StreamUtils.filter(list, e -> StringUtils.isNotBlank(e.getParentTaskId())); - if (CollUtil.isNotEmpty(subTasks)) { - subTasks.forEach(e -> taskService.deleteTask(e.getId())); - } - String deleteReason = LoginHelper.getLoginUser().getNickname() + "作废了当前申请!"; - if (StringUtils.isNotBlank(processInvalidBo.getDeleteReason())) { - deleteReason = LoginHelper.getLoginUser().getNickname() + "作废理由:" + processInvalidBo.getDeleteReason(); - } - for (Task task : StreamUtils.filter(list, e -> StringUtils.isBlank(e.getParentTaskId()))) { - taskService.addComment(task.getId(), task.getProcessInstanceId(), TaskStatusEnum.INVALID.getStatus(), deleteReason); - } - HistoricProcessInstance historicProcessInstance = QueryUtils.hisInstanceQuery(processInstanceId).singleResult(); - BusinessStatusEnum.checkInvalidStatus(historicProcessInstance.getBusinessStatus()); - runtimeService.updateBusinessStatus(processInstanceId, BusinessStatusEnum.INVALID.getStatus()); - runtimeService.deleteProcessInstance(processInstanceId, deleteReason); - //流程作废监听 - flowProcessEventHandler.processHandler(historicProcessInstance.getProcessDefinitionKey(), - historicProcessInstance.getBusinessKey(), BusinessStatusEnum.INVALID.getStatus(), false); - return true; - } catch (Exception e) { - log.error(e.getMessage(), e); - throw new ServiceException(e.getMessage()); - } - } - - /** - * 运行中的实例 删除程实例,删除历史记录,删除业务与流程关联信息 - * - * @param businessKeys 业务id - */ - @Override - @Transactional(rollbackFor = Exception.class) - public boolean deleteRunAndHisInstance(List businessKeys) { - try { - // 1.删除运行中流程实例 - List actHiProcinsts = actHiProcinstService.selectByBusinessKeyIn(businessKeys); - if (CollUtil.isEmpty(actHiProcinsts)) { - log.warn("当前业务ID:{}查询到流程实例为空!", businessKeys); - return false; - } - List processInstanceIds = StreamUtils.toList(actHiProcinsts, ActHiProcinst::getId); - List list = QueryUtils.taskQuery(processInstanceIds).list(); - List subTasks = StreamUtils.filter(list, e -> StringUtils.isNotBlank(e.getParentTaskId())); - if (CollUtil.isNotEmpty(subTasks)) { - subTasks.forEach(e -> taskService.deleteTask(e.getId())); - } - runtimeService.bulkDeleteProcessInstances(processInstanceIds, LoginHelper.getUserId() + "删除了当前流程申请"); - // 2.删除历史记录 - List historicProcessInstanceList = QueryUtils.hisInstanceQuery(new HashSet<>(processInstanceIds)).list(); - if (ObjectUtil.isNotEmpty(historicProcessInstanceList)) { - historyService.bulkDeleteHistoricProcessInstances(processInstanceIds); - } - wfTaskBackNodeService.deleteByInstanceIds(processInstanceIds); - return true; - } catch (Exception e) { - log.error(e.getMessage(), e); - throw new ServiceException(e.getMessage()); - } - } - - /** - * 已完成的实例 删除程实例,删除历史记录,删除业务与流程关联信息 - * - * @param businessKeys 业务id - */ - @Override - @Transactional(rollbackFor = Exception.class) - public boolean deleteFinishAndHisInstance(List businessKeys) { - try { - List actHiProcinsts = actHiProcinstService.selectByBusinessKeyIn(businessKeys); - if (CollUtil.isEmpty(actHiProcinsts)) { - log.warn("当前业务ID:{}查询到流程实例为空!", businessKeys); - return false; - } - List processInstanceIds = StreamUtils.toList(actHiProcinsts, ActHiProcinst::getId); - historyService.bulkDeleteHistoricProcessInstances(processInstanceIds); - wfTaskBackNodeService.deleteByInstanceIds(processInstanceIds); - return true; - } catch (Exception e) { - log.error(e.getMessage(), e); - throw new ServiceException(e.getMessage()); - } - } - - /** - * 撤销流程申请 - * - * @param businessKey 业务id - */ - @Override - @Transactional(rollbackFor = Exception.class) - public boolean cancelProcessApply(String businessKey) { - try { - ProcessInstance processInstance = QueryUtils.businessKeyQuery(businessKey) - .startedBy(String.valueOf(LoginHelper.getUserId())).singleResult(); - if (ObjectUtil.isNull(processInstance)) { - throw new ServiceException("您不是流程发起人,撤销失败!"); - } - if (processInstance.isSuspended()) { - throw new ServiceException(FlowConstant.MESSAGE_SUSPENDED); - } - String processInstanceId = processInstance.getId(); - BusinessStatusEnum.checkCancelStatus(processInstance.getBusinessStatus()); - List taskList = QueryUtils.taskQuery(processInstanceId).list(); - for (Task task : taskList) { - taskService.setAssignee(task.getId(), null); - taskService.addComment(task.getId(), processInstanceId, TaskStatusEnum.CANCEL.getStatus(), LoginHelper.getLoginUser().getNickname() + ":撤销申请"); - } - HistoricTaskInstance historicTaskInstance = QueryUtils.hisTaskInstanceQuery(processInstanceId).finished().orderByHistoricTaskInstanceEndTime().asc().list().get(0); - List nodeIds = StreamUtils.toList(taskList, Task::getTaskDefinitionKey); - runtimeService.createChangeActivityStateBuilder() - .processInstanceId(processInstanceId) - .moveActivityIdsToSingleActivityId(nodeIds, historicTaskInstance.getTaskDefinitionKey()).changeState(); - Task task = QueryUtils.taskQuery(processInstanceId).list().get(0); - taskService.setAssignee(task.getId(), historicTaskInstance.getAssignee()); - //获取并行网关执行后保留的执行实例数据 - ExecutionChildByExecutionIdCmd childByExecutionIdCmd = new ExecutionChildByExecutionIdCmd(task.getExecutionId()); - List executionEntities = managementService.executeCommand(childByExecutionIdCmd); - //删除流程实例垃圾数据 - for (ExecutionEntity executionEntity : executionEntities) { - DeleteExecutionCmd deleteExecutionCmd = new DeleteExecutionCmd(executionEntity.getId()); - managementService.executeCommand(deleteExecutionCmd); - } - runtimeService.updateBusinessStatus(processInstanceId, BusinessStatusEnum.CANCEL.getStatus()); - //流程作废监听 - flowProcessEventHandler.processHandler(processInstance.getProcessDefinitionKey(), - processInstance.getBusinessKey(), BusinessStatusEnum.CANCEL.getStatus(), false); - return true; - } catch (Exception e) { - log.error("撤销失败:" + e.getMessage(), e); - throw new ServiceException("撤销失败:" + e.getMessage()); - } - } - - /** - * 分页查询当前登录人单据 - * - * @param bo 参数 - */ - @Override - public TableDataInfo getPageByCurrent(ProcessInstanceBo bo, PageQuery pageQuery) { - List list = new ArrayList<>(); - HistoricProcessInstanceQuery query = QueryUtils.hisInstanceQuery(); - query.startedBy(String.valueOf(LoginHelper.getUserId())); - if (StringUtils.isNotBlank(bo.getName())) { - query.processInstanceNameLikeIgnoreCase("%" + bo.getName() + "%"); - } - if (StringUtils.isNotBlank(bo.getKey())) { - query.processDefinitionKey(bo.getKey()); - } - if (StringUtils.isNotBlank(bo.getBusinessKey())) { - query.processInstanceBusinessKey(bo.getBusinessKey()); - } - if (StringUtils.isNotBlank(bo.getCategoryCode())) { - query.processDefinitionCategory(bo.getCategoryCode()); - } - query.orderByProcessInstanceStartTime().desc(); - List historicProcessInstanceList = query.listPage(pageQuery.getFirstNum(), pageQuery.getPageSize()); - List taskVoList = new ArrayList<>(); - if (CollUtil.isNotEmpty(historicProcessInstanceList)) { - List processInstanceIds = StreamUtils.toList(historicProcessInstanceList, HistoricProcessInstance::getId); - List taskList = QueryUtils.taskQuery(processInstanceIds).list(); - for (Task task : taskList) { - taskVoList.add(BeanUtil.toBean(task, TaskVo.class)); - } - } - for (HistoricProcessInstance processInstance : historicProcessInstanceList) { - ProcessInstanceVo processInstanceVo = BeanUtil.toBean(processInstance, ProcessInstanceVo.class); - processInstanceVo.setBusinessStatusName(BusinessStatusEnum.findByStatus(processInstance.getBusinessStatus())); - if (CollUtil.isNotEmpty(taskVoList)) { - List collect = StreamUtils.filter(taskVoList, e -> e.getProcessInstanceId().equals(processInstance.getId())); - processInstanceVo.setTaskVoList(CollUtil.isNotEmpty(collect) ? collect : Collections.emptyList()); - } - list.add(processInstanceVo); - } - if (CollUtil.isNotEmpty(list)) { - List processDefinitionIds = StreamUtils.toList(list, ProcessInstanceVo::getProcessDefinitionId); - List wfNodeConfigVoList = wfNodeConfigService.selectByDefIds(processDefinitionIds); - for (ProcessInstanceVo processInstanceVo : list) { - if (CollUtil.isNotEmpty(wfNodeConfigVoList)) { - wfNodeConfigVoList.stream().filter(e -> e.getDefinitionId().equals(processInstanceVo.getProcessDefinitionId()) && FlowConstant.TRUE.equals(e.getApplyUserTask())).findFirst().ifPresent(processInstanceVo::setWfNodeConfigVo); - } - } - } - long count = query.count(); - TableDataInfo build = TableDataInfo.build(); - build.setRows(list); - build.setTotal(count); - return build; - } - - /** - * 任务催办(给当前任务办理人发送站内信,邮件,短信等) - * - * @param taskUrgingBo 任务催办 - */ - @Override - @Transactional(rollbackFor = Exception.class) - public boolean taskUrging(TaskUrgingBo taskUrgingBo) { - try { - ProcessInstance processInstance = QueryUtils.instanceQuery(taskUrgingBo.getProcessInstanceId()).singleResult(); - if (processInstance == null) { - throw new ServiceException("任务已结束!"); - } - String message = taskUrgingBo.getMessage(); - if (StringUtils.isBlank(message)) { - message = "您的【" + processInstance.getName() + "】单据还未审批,请您及时处理。"; - } - List list = QueryUtils.taskQuery(taskUrgingBo.getProcessInstanceId()).list(); - WorkflowUtils.sendMessage(list, processInstance.getName(), taskUrgingBo.getMessageType(), message, userService); - } catch (ServiceException e) { - throw new ServiceException(e.getMessage()); - } - return true; - } -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActTaskServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActTaskServiceImpl.java deleted file mode 100644 index d9a674a78..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActTaskServiceImpl.java +++ /dev/null @@ -1,861 +0,0 @@ -package org.dromara.workflow.service.impl; - -import cn.hutool.core.bean.BeanUtil; -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.core.util.StrUtil; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.dromara.common.core.domain.dto.RoleDTO; -import org.dromara.common.core.domain.dto.UserDTO; -import org.dromara.common.core.exception.ServiceException; -import org.dromara.common.core.service.OssService; -import org.dromara.common.core.service.UserService; -import org.dromara.common.core.utils.StreamUtils; -import org.dromara.common.core.utils.StringUtils; -import org.dromara.common.mybatis.core.page.PageQuery; -import org.dromara.common.mybatis.core.page.TableDataInfo; -import org.dromara.common.satoken.utils.LoginHelper; -import org.dromara.common.tenant.helper.TenantHelper; -import org.dromara.workflow.common.constant.FlowConstant; -import org.dromara.common.core.enums.BusinessStatusEnum; -import org.dromara.workflow.common.enums.TaskStatusEnum; -import org.dromara.workflow.domain.ActHiTaskinst; -import org.dromara.workflow.domain.WfTaskBackNode; -import org.dromara.workflow.domain.bo.*; -import org.dromara.workflow.domain.vo.*; -import org.dromara.workflow.flowable.cmd.*; -import org.dromara.workflow.flowable.handler.FlowProcessEventHandler; -import org.dromara.workflow.mapper.ActHiTaskinstMapper; -import org.dromara.workflow.mapper.ActTaskMapper; -import org.dromara.workflow.service.IActTaskService; -import org.dromara.workflow.service.IWfDefinitionConfigService; -import org.dromara.workflow.service.IWfNodeConfigService; -import org.dromara.workflow.service.IWfTaskBackNodeService; -import org.dromara.workflow.utils.ModelUtils; -import org.dromara.workflow.utils.QueryUtils; -import org.dromara.workflow.utils.WorkflowUtils; -import org.flowable.common.engine.api.FlowableObjectNotFoundException; -import org.flowable.common.engine.impl.identity.Authentication; -import org.flowable.engine.*; -import org.flowable.engine.history.HistoricProcessInstance; -import org.flowable.engine.history.HistoricProcessInstanceQuery; -import org.flowable.engine.impl.bpmn.behavior.ParallelMultiInstanceBehavior; -import org.flowable.engine.impl.bpmn.behavior.SequentialMultiInstanceBehavior; -import org.flowable.engine.impl.persistence.entity.ExecutionEntity; -import org.flowable.engine.runtime.ProcessInstance; -import org.flowable.identitylink.api.history.HistoricIdentityLink; -import org.flowable.task.api.Task; -import org.flowable.task.api.TaskQuery; -import org.flowable.task.api.history.HistoricTaskInstance; -import org.flowable.task.service.impl.persistence.entity.TaskEntity; -import org.flowable.variable.api.persistence.entity.VariableInstance; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.scheduling.annotation.Async; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.util.*; -import java.util.stream.Collectors; - -import static org.dromara.workflow.common.constant.FlowConstant.*; - -/** - * 任务 服务层实现 - * - * @author may - */ -@Slf4j -@RequiredArgsConstructor -@Service -public class ActTaskServiceImpl implements IActTaskService { - - @Autowired(required = false) - private RuntimeService runtimeService; - @Autowired(required = false) - private TaskService taskService; - @Autowired(required = false) - private HistoryService historyService; - @Autowired(required = false) - private IdentityService identityService; - @Autowired(required = false) - private ManagementService managementService; - private final ActTaskMapper actTaskMapper; - private final IWfTaskBackNodeService wfTaskBackNodeService; - private final ActHiTaskinstMapper actHiTaskinstMapper; - private final IWfNodeConfigService wfNodeConfigService; - private final IWfDefinitionConfigService wfDefinitionConfigService; - private final FlowProcessEventHandler flowProcessEventHandler; - private final UserService userService; - private final OssService ossService; - - /** - * 启动任务 - * - * @param startProcessBo 启动流程参数 - */ - @Override - @Transactional(rollbackFor = Exception.class) - public Map startWorkFlow(StartProcessBo startProcessBo) { - Map map = new HashMap<>(); - if (StringUtils.isBlank(startProcessBo.getBusinessKey())) { - throw new ServiceException("启动工作流时必须包含业务ID"); - } - // 判断当前业务是否启动过流程 - HistoricProcessInstanceQuery query = QueryUtils.hisInstanceQuery(); - HistoricProcessInstance historicProcessInstance = query.processInstanceBusinessKey(startProcessBo.getBusinessKey()).singleResult(); - if (ObjectUtil.isNotEmpty(historicProcessInstance)) { - BusinessStatusEnum.checkStartStatus(historicProcessInstance.getBusinessStatus()); - } - List taskResult = QueryUtils.taskQuery().processInstanceBusinessKey(startProcessBo.getBusinessKey()).list(); - if (CollUtil.isNotEmpty(taskResult)) { - if (CollUtil.isNotEmpty(startProcessBo.getVariables())) { - taskService.setVariables(taskResult.get(0).getId(), startProcessBo.getVariables()); - } - map.put(PROCESS_INSTANCE_ID, taskResult.get(0).getProcessInstanceId()); - map.put("taskId", taskResult.get(0).getId()); - return map; - } - WfDefinitionConfigVo wfDefinitionConfigVo = wfDefinitionConfigService.getByTableNameLastVersion(startProcessBo.getTableName()); - if (wfDefinitionConfigVo == null) { - throw new ServiceException("请到流程定义绑定业务表名与流程KEY!"); - } - // 设置启动人 - identityService.setAuthenticatedUserId(String.valueOf(LoginHelper.getUserId())); - Authentication.setAuthenticatedUserId(String.valueOf(LoginHelper.getUserId())); - // 启动流程实例(提交申请) - Map variables = startProcessBo.getVariables(); - // 启动跳过表达式 - variables.put(FLOWABLE_SKIP_EXPRESSION_ENABLED, true); - // 流程发起人 - variables.put(INITIATOR, (String.valueOf(LoginHelper.getUserId()))); - ProcessInstance pi; - try { - if (TenantHelper.isEnable()) { - pi = runtimeService.startProcessInstanceByKeyAndTenantId(wfDefinitionConfigVo.getProcessKey(), startProcessBo.getBusinessKey(), variables, TenantHelper.getTenantId()); - } else { - pi = runtimeService.startProcessInstanceByKey(wfDefinitionConfigVo.getProcessKey(), startProcessBo.getBusinessKey(), variables); - } - } catch (FlowableObjectNotFoundException e) { - throw new ServiceException("找不到当前【" + wfDefinitionConfigVo.getProcessKey() + "】流程定义!"); - } - // 将流程定义名称 作为 流程实例名称 - runtimeService.setProcessInstanceName(pi.getProcessInstanceId(), pi.getProcessDefinitionName()); - // 申请人执行流程 - List taskList = QueryUtils.taskQuery(pi.getId()).list(); - if (taskList.size() > 1) { - throw new ServiceException("请检查流程第一个环节是否为申请人!"); - } - - runtimeService.updateBusinessStatus(pi.getProcessInstanceId(), BusinessStatusEnum.DRAFT.getStatus()); - taskService.setAssignee(taskList.get(0).getId(), LoginHelper.getUserId().toString()); - taskService.setVariable(taskList.get(0).getId(), PROCESS_INSTANCE_ID, pi.getProcessInstanceId()); - taskService.setVariable(taskList.get(0).getId(), BUSINESS_KEY, pi.getBusinessKey()); - map.put("processInstanceId", pi.getProcessInstanceId()); - map.put("taskId", taskList.get(0).getId()); - return map; - } - - /** - * 办理任务 - * - * @param completeTaskBo 办理任务参数 - */ - @Override - @Transactional(rollbackFor = Exception.class) - public boolean completeTask(CompleteTaskBo completeTaskBo) { - try { - String userId = String.valueOf(LoginHelper.getUserId()); - Task task = WorkflowUtils.getTaskByCurrentUser(completeTaskBo.getTaskId()); - if (task == null) { - throw new ServiceException(FlowConstant.MESSAGE_CURRENT_TASK_IS_NULL); - } - if (task.isSuspended()) { - throw new ServiceException(FlowConstant.MESSAGE_SUSPENDED); - } - ProcessInstance processInstance = QueryUtils.instanceQuery(task.getProcessInstanceId()).singleResult(); - //办理委托任务 - if (ObjectUtil.isNotEmpty(task.getDelegationState()) && FlowConstant.PENDING.equals(task.getDelegationState().name())) { - taskService.resolveTask(completeTaskBo.getTaskId()); - TaskEntity newTask = WorkflowUtils.createNewTask(task); - taskService.addComment(newTask.getId(), task.getProcessInstanceId(), TaskStatusEnum.PASS.getStatus(), StringUtils.isNotBlank(completeTaskBo.getMessage()) ? completeTaskBo.getMessage() : StrUtil.EMPTY); - taskService.complete(newTask.getId()); - return true; - } - //附件上传 - AttachmentCmd attachmentCmd = new AttachmentCmd(completeTaskBo.getFileId(), task.getId(), task.getProcessInstanceId(), ossService); - managementService.executeCommand(attachmentCmd); - String businessStatus = WorkflowUtils.getBusinessStatus(processInstance.getBusinessKey()); - //流程提交监听 - if (BusinessStatusEnum.DRAFT.getStatus().equals(businessStatus) || BusinessStatusEnum.BACK.getStatus().equals(businessStatus) || BusinessStatusEnum.CANCEL.getStatus().equals(businessStatus)) { - flowProcessEventHandler.processHandler(processInstance.getProcessDefinitionKey(), processInstance.getBusinessKey(), businessStatus, true); - } - runtimeService.updateBusinessStatus(task.getProcessInstanceId(), BusinessStatusEnum.WAITING.getStatus()); - //办理监听 - flowProcessEventHandler.processTaskHandler(processInstance.getProcessDefinitionKey(), task.getTaskDefinitionKey(), - task.getId(), processInstance.getBusinessKey()); - //办理意见 - taskService.addComment(completeTaskBo.getTaskId(), task.getProcessInstanceId(), TaskStatusEnum.PASS.getStatus(), StringUtils.isBlank(completeTaskBo.getMessage()) ? "同意" : completeTaskBo.getMessage()); - //办理任务 - taskService.setAssignee(task.getId(), userId); - if (CollUtil.isNotEmpty(completeTaskBo.getVariables())) { - taskService.complete(completeTaskBo.getTaskId(), completeTaskBo.getVariables()); - } else { - taskService.complete(completeTaskBo.getTaskId()); - } - //记录执行过的流程任务节点 - wfTaskBackNodeService.recordExecuteNode(task); - ProcessInstance pi = QueryUtils.instanceQuery(task.getProcessInstanceId()).singleResult(); - if (pi == null) { - UpdateBusinessStatusCmd updateBusinessStatusCmd = new UpdateBusinessStatusCmd(task.getProcessInstanceId(), BusinessStatusEnum.FINISH.getStatus()); - managementService.executeCommand(updateBusinessStatusCmd); - flowProcessEventHandler.processHandler(processInstance.getProcessDefinitionKey(), processInstance.getBusinessKey(), - BusinessStatusEnum.FINISH.getStatus(), false); - } else { - List list = QueryUtils.taskQuery(task.getProcessInstanceId()).list(); - for (Task t : list) { - if (ModelUtils.isUserTask(t.getProcessDefinitionId(), t.getTaskDefinitionKey())) { - List links = historyService.getHistoricIdentityLinksForTask(t.getId()); - if (CollUtil.isEmpty(links) && StringUtils.isBlank(t.getAssignee())) { - throw new ServiceException("下一节点【" + t.getName() + "】没有办理人!"); - } - } - } - - if (CollUtil.isNotEmpty(list) && CollUtil.isNotEmpty(completeTaskBo.getWfCopyList())) { - TaskEntity newTask = WorkflowUtils.createNewTask(task); - taskService.addComment(newTask.getId(), task.getProcessInstanceId(), TaskStatusEnum.COPY.getStatus(), LoginHelper.getLoginUser().getNickname() + "【抄送】给" + String.join(",", StreamUtils.toList(completeTaskBo.getWfCopyList(), WfCopy::getUserName))); - taskService.complete(newTask.getId()); - List taskList = QueryUtils.taskQuery(task.getProcessInstanceId()).list(); - WorkflowUtils.createCopyTask(taskList, StreamUtils.toList(completeTaskBo.getWfCopyList(), WfCopy::getUserId)); - } - sendMessage(list, processInstance.getName(), completeTaskBo.getMessageType(), null); - } - return true; - } catch (Exception e) { - log.error(e.getMessage(), e); - throw new ServiceException(e.getMessage()); - } - } - - /** - * 发送消息 - * - * @param list 任务 - * @param name 流程名称 - * @param messageType 消息类型 - * @param message 消息内容,为空则发送默认配置的消息内容 - */ - @Async - public void sendMessage(List list, String name, List messageType, String message) { - WorkflowUtils.sendMessage(list, name, messageType, message, userService); - } - - /** - * 查询当前用户的待办任务 - * - * @param taskBo 参数 - */ - @Override - public TableDataInfo getPageByTaskWait(TaskBo taskBo, PageQuery pageQuery) { - QueryWrapper queryWrapper = new QueryWrapper<>(); - List roles = LoginHelper.getLoginUser().getRoles(); - List roleIds = StreamUtils.toList(roles, e -> String.valueOf(e.getRoleId())); - String userId = String.valueOf(LoginHelper.getUserId()); - queryWrapper.eq("t.business_status_", BusinessStatusEnum.WAITING.getStatus()); - queryWrapper.eq(TenantHelper.isEnable(), "t.tenant_id_", TenantHelper.getTenantId()); - String ids = StreamUtils.join(roleIds, x -> "'" + x + "'"); - queryWrapper.and(w1 -> w1.eq("t.assignee_", userId).or(w2 -> w2.isNull("t.assignee_").apply("exists ( select LINK.ID_ from ACT_RU_IDENTITYLINK LINK where LINK.TASK_ID_ = t.ID_ and LINK.TYPE_ = 'candidate' and (LINK.USER_ID_ = {0} or ( LINK.GROUP_ID_ IN (" + ids + ") ) ))", userId))); - if (StringUtils.isNotBlank(taskBo.getName())) { - queryWrapper.like("t.name_", taskBo.getName()); - } - if (StringUtils.isNotBlank(taskBo.getProcessDefinitionName())) { - queryWrapper.like("t.processDefinitionName", taskBo.getProcessDefinitionName()); - } - if (StringUtils.isNotBlank(taskBo.getProcessDefinitionKey())) { - queryWrapper.eq("t.processDefinitionKey", taskBo.getProcessDefinitionKey()); - } - queryWrapper.orderByDesc("t.CREATE_TIME_"); - Page page = actTaskMapper.getTaskWaitByPage(pageQuery.build(), queryWrapper); - - List taskList = page.getRecords(); - if (CollUtil.isNotEmpty(taskList)) { - List processDefinitionIds = StreamUtils.toList(taskList, TaskVo::getProcessDefinitionId); - List wfNodeConfigVoList = wfNodeConfigService.selectByDefIds(processDefinitionIds); - for (TaskVo task : taskList) { - task.setBusinessStatusName(BusinessStatusEnum.findByStatus(task.getBusinessStatus())); - task.setParticipantVo(WorkflowUtils.getCurrentTaskParticipant(task.getId(), userService)); - task.setMultiInstance(WorkflowUtils.isMultiInstance(task.getProcessDefinitionId(), task.getTaskDefinitionKey()) != null); - if (CollUtil.isNotEmpty(wfNodeConfigVoList)) { - wfNodeConfigVoList.stream().filter(e -> e.getDefinitionId().equals(task.getProcessDefinitionId()) && FlowConstant.TRUE.equals(e.getApplyUserTask())).findFirst().ifPresent(task::setWfNodeConfigVo); - wfNodeConfigVoList.stream().filter(e -> e.getDefinitionId().equals(task.getProcessDefinitionId()) && e.getNodeId().equals(task.getTaskDefinitionKey()) && FlowConstant.FALSE.equals(e.getApplyUserTask())).findFirst().ifPresent(task::setWfNodeConfigVo); - } - } - } - return TableDataInfo.build(page); - } - - /** - * 查询当前租户所有待办任务 - * - * @param taskBo 参数 - */ - @Override - public TableDataInfo getPageByAllTaskWait(TaskBo taskBo, PageQuery pageQuery) { - TaskQuery query = QueryUtils.taskQuery(); - if (StringUtils.isNotBlank(taskBo.getName())) { - query.taskNameLike("%" + taskBo.getName() + "%"); - } - if (StringUtils.isNotBlank(taskBo.getProcessDefinitionName())) { - query.processDefinitionNameLike("%" + taskBo.getProcessDefinitionName() + "%"); - } - if (StringUtils.isNotBlank(taskBo.getProcessDefinitionKey())) { - query.processDefinitionKey(taskBo.getProcessDefinitionKey()); - } - query.orderByTaskCreateTime().desc(); - List taskList = query.listPage(pageQuery.getFirstNum(), pageQuery.getPageSize()); - List processInstanceList = null; - if (CollUtil.isNotEmpty(taskList)) { - Set processInstanceIds = StreamUtils.toSet(taskList, Task::getProcessInstanceId); - processInstanceList = QueryUtils.instanceQuery(processInstanceIds).list(); - } - List list = new ArrayList<>(); - if (CollUtil.isNotEmpty(taskList)) { - List processDefinitionIds = StreamUtils.toList(taskList, Task::getProcessDefinitionId); - List wfNodeConfigVoList = wfNodeConfigService.selectByDefIds(processDefinitionIds); - for (Task task : taskList) { - TaskVo taskVo = BeanUtil.toBean(task, TaskVo.class); - if (CollUtil.isNotEmpty(processInstanceList)) { - processInstanceList.stream().filter(e -> e.getId().equals(task.getProcessInstanceId())).findFirst().ifPresent(e -> { - taskVo.setBusinessStatus(e.getBusinessStatus()); - taskVo.setBusinessStatusName(BusinessStatusEnum.findByStatus(taskVo.getBusinessStatus())); - taskVo.setProcessDefinitionKey(e.getProcessDefinitionKey()); - taskVo.setProcessDefinitionName(e.getProcessDefinitionName()); - taskVo.setProcessDefinitionVersion(e.getProcessDefinitionVersion()); - taskVo.setBusinessKey(e.getBusinessKey()); - }); - } - taskVo.setAssignee(StringUtils.isNotBlank(task.getAssignee()) ? Long.valueOf(task.getAssignee()) : null); - taskVo.setParticipantVo(WorkflowUtils.getCurrentTaskParticipant(task.getId(), userService)); - taskVo.setMultiInstance(WorkflowUtils.isMultiInstance(task.getProcessDefinitionId(), task.getTaskDefinitionKey()) != null); - if (CollUtil.isNotEmpty(wfNodeConfigVoList)) { - wfNodeConfigVoList.stream().filter(e -> e.getDefinitionId().equals(task.getProcessDefinitionId()) && FlowConstant.TRUE.equals(e.getApplyUserTask())).findFirst().ifPresent(taskVo::setWfNodeConfigVo); - wfNodeConfigVoList.stream().filter(e -> e.getDefinitionId().equals(task.getProcessDefinitionId()) && e.getNodeId().equals(task.getTaskDefinitionKey()) && FlowConstant.FALSE.equals(e.getApplyUserTask())).findFirst().ifPresent(taskVo::setWfNodeConfigVo); - } - list.add(taskVo); - } - } - long count = query.count(); - TableDataInfo build = TableDataInfo.build(); - build.setRows(list); - build.setTotal(count); - return build; - } - - /** - * 查询当前用户的已办任务 - * - * @param taskBo 参数 - */ - @Override - public TableDataInfo getPageByTaskFinish(TaskBo taskBo, PageQuery pageQuery) { - String userId = String.valueOf(LoginHelper.getUserId()); - QueryWrapper queryWrapper = new QueryWrapper<>(); - queryWrapper.like(StringUtils.isNotBlank(taskBo.getName()), "t.name_", taskBo.getName()); - queryWrapper.like(StringUtils.isNotBlank(taskBo.getProcessDefinitionName()), "t.processDefinitionName", taskBo.getProcessDefinitionName()); - queryWrapper.eq(StringUtils.isNotBlank(taskBo.getProcessDefinitionKey()), "t.processDefinitionKey", taskBo.getProcessDefinitionKey()); - queryWrapper.eq("t.assignee_", userId); - queryWrapper.orderByDesc("t.START_TIME_"); - Page page = actTaskMapper.getTaskFinishByPage(pageQuery.build(), queryWrapper); - - List taskList = page.getRecords(); - if (CollUtil.isNotEmpty(taskList)) { - List processDefinitionIds = StreamUtils.toList(taskList, TaskVo::getProcessDefinitionId); - List wfNodeConfigVoList = wfNodeConfigService.selectByDefIds(processDefinitionIds); - for (TaskVo task : taskList) { - task.setBusinessStatusName(BusinessStatusEnum.findByStatus(task.getBusinessStatus())); - if (CollUtil.isNotEmpty(wfNodeConfigVoList)) { - wfNodeConfigVoList.stream().filter(e -> e.getDefinitionId().equals(task.getProcessDefinitionId()) && FlowConstant.TRUE.equals(e.getApplyUserTask())).findFirst().ifPresent(task::setWfNodeConfigVo); - wfNodeConfigVoList.stream().filter(e -> e.getDefinitionId().equals(task.getProcessDefinitionId()) && e.getNodeId().equals(task.getTaskDefinitionKey()) && FlowConstant.FALSE.equals(e.getApplyUserTask())).findFirst().ifPresent(task::setWfNodeConfigVo); - } - } - } - return TableDataInfo.build(page); - } - - /** - * 查询当前用户的抄送 - * - * @param taskBo 参数 - */ - @Override - public TableDataInfo getPageByTaskCopy(TaskBo taskBo, PageQuery pageQuery) { - QueryWrapper queryWrapper = new QueryWrapper<>(); - String userId = String.valueOf(LoginHelper.getUserId()); - if (StringUtils.isNotBlank(taskBo.getName())) { - queryWrapper.like("t.name_", taskBo.getName()); - } - if (StringUtils.isNotBlank(taskBo.getProcessDefinitionName())) { - queryWrapper.like("t.processDefinitionName", taskBo.getProcessDefinitionName()); - } - if (StringUtils.isNotBlank(taskBo.getProcessDefinitionKey())) { - queryWrapper.eq("t.processDefinitionKey", taskBo.getProcessDefinitionKey()); - } - queryWrapper.eq("t.assignee_", userId); - queryWrapper.orderByDesc("t.START_TIME_"); - Page page = actTaskMapper.getTaskCopyByPage(pageQuery.build(), queryWrapper); - - List taskList = page.getRecords(); - if (CollUtil.isNotEmpty(taskList)) { - List processDefinitionIds = StreamUtils.toList(taskList, TaskVo::getProcessDefinitionId); - List wfNodeConfigVoList = wfNodeConfigService.selectByDefIds(processDefinitionIds); - for (TaskVo task : taskList) { - task.setBusinessStatusName(BusinessStatusEnum.findByStatus(task.getBusinessStatus())); - if (CollUtil.isNotEmpty(wfNodeConfigVoList)) { - wfNodeConfigVoList.stream().filter(e -> e.getDefinitionId().equals(task.getProcessDefinitionId()) && FlowConstant.TRUE.equals(e.getApplyUserTask())).findFirst().ifPresent(task::setWfNodeConfigVo); - wfNodeConfigVoList.stream().filter(e -> e.getDefinitionId().equals(task.getProcessDefinitionId()) && e.getNodeId().equals(task.getTaskDefinitionKey()) && FlowConstant.FALSE.equals(e.getApplyUserTask())).findFirst().ifPresent(task::setWfNodeConfigVo); - } - } - } - return TableDataInfo.build(page); - } - - /** - * 查询当前租户所有已办任务 - * - * @param taskBo 参数 - */ - @Override - public TableDataInfo getPageByAllTaskFinish(TaskBo taskBo, PageQuery pageQuery) { - QueryWrapper queryWrapper = new QueryWrapper<>(); - queryWrapper.like(StringUtils.isNotBlank(taskBo.getName()), "t.name_", taskBo.getName()); - queryWrapper.like(StringUtils.isNotBlank(taskBo.getProcessDefinitionName()), "t.processDefinitionName", taskBo.getProcessDefinitionName()); - queryWrapper.eq(StringUtils.isNotBlank(taskBo.getProcessDefinitionKey()), "t.processDefinitionKey", taskBo.getProcessDefinitionKey()); - Page page = actTaskMapper.getTaskFinishByPage(pageQuery.build(), queryWrapper); - - List taskList = page.getRecords(); - if (CollUtil.isNotEmpty(taskList)) { - List processDefinitionIds = StreamUtils.toList(taskList, TaskVo::getProcessDefinitionId); - List wfNodeConfigVoList = wfNodeConfigService.selectByDefIds(processDefinitionIds); - for (TaskVo task : taskList) { - task.setBusinessStatusName(BusinessStatusEnum.findByStatus(task.getBusinessStatus())); - if (CollUtil.isNotEmpty(wfNodeConfigVoList)) { - wfNodeConfigVoList.stream().filter(e -> e.getDefinitionId().equals(task.getProcessDefinitionId()) && FlowConstant.TRUE.equals(e.getApplyUserTask())).findFirst().ifPresent(task::setWfNodeConfigVo); - wfNodeConfigVoList.stream().filter(e -> e.getDefinitionId().equals(task.getProcessDefinitionId()) && e.getNodeId().equals(task.getTaskDefinitionKey()) && FlowConstant.FALSE.equals(e.getApplyUserTask())).findFirst().ifPresent(task::setWfNodeConfigVo); - } - } - } - return TableDataInfo.build(page); - } - - /** - * 委派任务 - * - * @param delegateBo 参数 - */ - @Override - @Transactional(rollbackFor = Exception.class) - public boolean delegateTask(DelegateBo delegateBo) { - Task task = WorkflowUtils.getTaskByCurrentUser(delegateBo.getTaskId()); - - if (ObjectUtil.isEmpty(task)) { - throw new ServiceException(FlowConstant.MESSAGE_CURRENT_TASK_IS_NULL); - } - if (task.isSuspended()) { - throw new ServiceException(FlowConstant.MESSAGE_SUSPENDED); - } - try { - TaskEntity newTask = WorkflowUtils.createNewTask(task); - taskService.addComment(newTask.getId(), task.getProcessInstanceId(), TaskStatusEnum.PENDING.getStatus(), "【" + LoginHelper.getLoginUser().getNickname() + "】委派给【" + delegateBo.getNickName() + "】"); - //委托任务 - taskService.delegateTask(delegateBo.getTaskId(), delegateBo.getUserId()); - //办理生成的任务记录 - taskService.complete(newTask.getId()); - return true; - } catch (Exception e) { - log.error(e.getMessage(), e); - throw new ServiceException(e.getMessage()); - } - } - - /** - * 终止任务 - * - * @param terminationBo 参数 - */ - @Override - @Transactional(rollbackFor = Exception.class) - public boolean terminationTask(TerminationBo terminationBo) { - TaskQuery query = QueryUtils.taskQuery(); - Task task = query.taskId(terminationBo.getTaskId()).singleResult(); - - if (ObjectUtil.isEmpty(task)) { - throw new ServiceException(FlowConstant.MESSAGE_CURRENT_TASK_IS_NULL); - } - if (task.isSuspended()) { - throw new ServiceException(FlowConstant.MESSAGE_SUSPENDED); - } - HistoricProcessInstance historicProcessInstance = QueryUtils.hisInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult(); - BusinessStatusEnum.checkInvalidStatus(historicProcessInstance.getBusinessStatus()); - try { - if (StringUtils.isBlank(terminationBo.getComment())) { - terminationBo.setComment(LoginHelper.getLoginUser().getNickname() + "终止了申请"); - } else { - terminationBo.setComment(LoginHelper.getLoginUser().getNickname() + "终止了申请:" + terminationBo.getComment()); - } - taskService.addComment(task.getId(), task.getProcessInstanceId(), TaskStatusEnum.TERMINATION.getStatus(), terminationBo.getComment()); - List list = QueryUtils.taskQuery(task.getProcessInstanceId()).list(); - if (CollUtil.isNotEmpty(list)) { - List subTasks = StreamUtils.filter(list, e -> StringUtils.isNotBlank(e.getParentTaskId())); - if (CollUtil.isNotEmpty(subTasks)) { - subTasks.forEach(e -> taskService.deleteTask(e.getId())); - } - runtimeService.updateBusinessStatus(task.getProcessInstanceId(), BusinessStatusEnum.TERMINATION.getStatus()); - runtimeService.deleteProcessInstance(task.getProcessInstanceId(), StrUtil.EMPTY); - } - //流程终止监听 - flowProcessEventHandler.processHandler(historicProcessInstance.getProcessDefinitionKey(), - historicProcessInstance.getBusinessKey(), BusinessStatusEnum.TERMINATION.getStatus(), false); - return true; - } catch (Exception e) { - throw new ServiceException(e.getMessage()); - } - } - - /** - * 转办任务 - * - * @param transmitBo 参数 - */ - @Override - public boolean transferTask(TransmitBo transmitBo) { - Task task = WorkflowUtils.getTaskByCurrentUser(transmitBo.getTaskId()); - if (ObjectUtil.isEmpty(task)) { - throw new ServiceException(FlowConstant.MESSAGE_CURRENT_TASK_IS_NULL); - } - if (task.isSuspended()) { - throw new ServiceException(FlowConstant.MESSAGE_SUSPENDED); - } - try { - TaskEntity newTask = WorkflowUtils.createNewTask(task); - taskService.addComment(newTask.getId(), task.getProcessInstanceId(), TaskStatusEnum.TRANSFER.getStatus(), StringUtils.isNotBlank(transmitBo.getComment()) ? transmitBo.getComment() : LoginHelper.getUsername() + "转办了任务"); - taskService.complete(newTask.getId()); - taskService.setAssignee(task.getId(), transmitBo.getUserId()); - return true; - } catch (Exception e) { - log.error(e.getMessage(), e); - throw new ServiceException(e.getMessage()); - } - } - - /** - * 会签任务加签 - * - * @param addMultiBo 参数 - */ - @Override - public boolean addMultiInstanceExecution(AddMultiBo addMultiBo) { - TaskQuery taskQuery = QueryUtils.taskQuery(); - taskQuery.taskId(addMultiBo.getTaskId()); - if (!LoginHelper.isSuperAdmin() && !LoginHelper.isTenantAdmin()) { - taskQuery.taskCandidateOrAssigned(String.valueOf(LoginHelper.getUserId())); - } - Task task = taskQuery.singleResult(); - if (ObjectUtil.isEmpty(task)) { - throw new ServiceException(FlowConstant.MESSAGE_CURRENT_TASK_IS_NULL); - } - if (task.isSuspended()) { - throw new ServiceException(FlowConstant.MESSAGE_SUSPENDED); - } - String taskDefinitionKey = task.getTaskDefinitionKey(); - String processInstanceId = task.getProcessInstanceId(); - String processDefinitionId = task.getProcessDefinitionId(); - - try { - MultiInstanceVo multiInstanceVo = WorkflowUtils.isMultiInstance(processDefinitionId, taskDefinitionKey); - if (multiInstanceVo == null) { - throw new ServiceException("当前环节不是会签节点"); - } - if (multiInstanceVo.getType() instanceof ParallelMultiInstanceBehavior) { - for (Long assignee : addMultiBo.getAssignees()) { - runtimeService.addMultiInstanceExecution(taskDefinitionKey, processInstanceId, Collections.singletonMap(multiInstanceVo.getAssignee(), assignee)); - } - } else if (multiInstanceVo.getType() instanceof SequentialMultiInstanceBehavior) { - AddSequenceMultiInstanceCmd addSequenceMultiInstanceCmd = new AddSequenceMultiInstanceCmd(task.getExecutionId(), multiInstanceVo.getAssigneeList(), addMultiBo.getAssignees()); - managementService.executeCommand(addSequenceMultiInstanceCmd); - } - List assigneeNames = addMultiBo.getAssigneeNames(); - String username = LoginHelper.getUsername(); - TaskEntity newTask = WorkflowUtils.createNewTask(task); - taskService.addComment(newTask.getId(), processInstanceId, TaskStatusEnum.SIGN.getStatus(), username + "加签【" + String.join(StringUtils.SEPARATOR, assigneeNames) + "】"); - taskService.complete(newTask.getId()); - return true; - } catch (Exception e) { - log.error(e.getMessage(), e); - throw new ServiceException(e.getMessage()); - } - } - - /** - * 会签任务减签 - * - * @param deleteMultiBo 参数 - */ - @Override - public boolean deleteMultiInstanceExecution(DeleteMultiBo deleteMultiBo) { - TaskQuery taskQuery = QueryUtils.taskQuery(); - taskQuery.taskId(deleteMultiBo.getTaskId()); - if (!LoginHelper.isSuperAdmin() && !LoginHelper.isTenantAdmin()) { - taskQuery.taskCandidateOrAssigned(String.valueOf(LoginHelper.getUserId())); - } - Task task = taskQuery.singleResult(); - if (ObjectUtil.isEmpty(task)) { - throw new ServiceException(FlowConstant.MESSAGE_CURRENT_TASK_IS_NULL); - } - if (task.isSuspended()) { - throw new ServiceException(FlowConstant.MESSAGE_SUSPENDED); - } - String taskDefinitionKey = task.getTaskDefinitionKey(); - String processInstanceId = task.getProcessInstanceId(); - String processDefinitionId = task.getProcessDefinitionId(); - try { - MultiInstanceVo multiInstanceVo = WorkflowUtils.isMultiInstance(processDefinitionId, taskDefinitionKey); - if (multiInstanceVo == null) { - throw new ServiceException("当前环节不是会签节点"); - } - if (multiInstanceVo.getType() instanceof ParallelMultiInstanceBehavior) { - for (String executionId : deleteMultiBo.getExecutionIds()) { - runtimeService.deleteMultiInstanceExecution(executionId, false); - } - for (String taskId : deleteMultiBo.getTaskIds()) { - historyService.deleteHistoricTaskInstance(taskId); - } - } else if (multiInstanceVo.getType() instanceof SequentialMultiInstanceBehavior) { - DeleteSequenceMultiInstanceCmd deleteSequenceMultiInstanceCmd = new DeleteSequenceMultiInstanceCmd(task.getAssignee(), task.getExecutionId(), multiInstanceVo.getAssigneeList(), deleteMultiBo.getAssigneeIds()); - managementService.executeCommand(deleteSequenceMultiInstanceCmd); - } - List assigneeNames = deleteMultiBo.getAssigneeNames(); - String username = LoginHelper.getUsername(); - TaskEntity newTask = WorkflowUtils.createNewTask(task); - taskService.addComment(newTask.getId(), processInstanceId, TaskStatusEnum.SIGN_OFF.getStatus(), username + "减签【" + String.join(StringUtils.SEPARATOR, assigneeNames) + "】"); - taskService.complete(newTask.getId()); - return true; - } catch (Exception e) { - log.error(e.getMessage(), e); - throw new ServiceException(e.getMessage()); - } - } - - /** - * 驳回审批 - * - * @param backProcessBo 参数 - */ - @Override - @Transactional(rollbackFor = Exception.class) - public String backProcess(BackProcessBo backProcessBo) { - String userId = String.valueOf(LoginHelper.getUserId()); - Task task = WorkflowUtils.getTaskByCurrentUser(backProcessBo.getTaskId()); - - if (ObjectUtil.isEmpty(task)) { - throw new ServiceException(FlowConstant.MESSAGE_CURRENT_TASK_IS_NULL); - } - if (task.isSuspended()) { - throw new ServiceException(FlowConstant.MESSAGE_SUSPENDED); - } - try { - String processInstanceId = task.getProcessInstanceId(); - ProcessInstance processInstance = QueryUtils.instanceQuery(task.getProcessInstanceId()).singleResult(); - //获取并行网关执行后保留的执行实例数据 - ExecutionChildByExecutionIdCmd childByExecutionIdCmd = new ExecutionChildByExecutionIdCmd(task.getExecutionId()); - List executionEntities = managementService.executeCommand(childByExecutionIdCmd); - //校验单据 - BusinessStatusEnum.checkBackStatus(processInstance.getBusinessStatus()); - //判断是否有多个任务 - List taskList = QueryUtils.taskQuery(processInstanceId).list(); - String backTaskDefinitionKey = backProcessBo.getTargetActivityId(); - taskService.addComment(task.getId(), processInstanceId, TaskStatusEnum.BACK.getStatus(), StringUtils.isNotBlank(backProcessBo.getMessage()) ? backProcessBo.getMessage() : "退回"); - if (taskList.size() > 1) { - //当前多个任务驳回到单个节点 - runtimeService.createChangeActivityStateBuilder().processInstanceId(processInstanceId).moveActivityIdsToSingleActivityId(taskList.stream().map(Task::getTaskDefinitionKey).distinct().collect(Collectors.toList()), backTaskDefinitionKey).changeState(); - ActHiTaskinst actHiTaskinst = new ActHiTaskinst(); - actHiTaskinst.setAssignee(userId); - actHiTaskinst.setId(task.getId()); - actHiTaskinstMapper.updateById(actHiTaskinst); - } else { - //当前单个节点驳回单个节点 - runtimeService.createChangeActivityStateBuilder().processInstanceId(processInstanceId).moveActivityIdTo(task.getTaskDefinitionKey(), backTaskDefinitionKey).changeState(); - } - //删除并行环节未办理记录 - MultiInstanceVo multiInstance = WorkflowUtils.isMultiInstance(task.getProcessDefinitionId(), task.getTaskDefinitionKey()); - if (multiInstance == null && taskList.size() > 1) { - List tasks = StreamUtils.filter(taskList, e -> !e.getTaskDefinitionKey().equals(task.getTaskDefinitionKey())); - if (CollUtil.isNotEmpty(tasks)) { - actHiTaskinstMapper.deleteByIds(StreamUtils.toList(tasks, Task::getId)); - } - } - - - List instanceList = QueryUtils.hisTaskInstanceQuery(processInstanceId).finished().orderByHistoricTaskInstanceEndTime().desc().list(); - List list = QueryUtils.taskQuery(processInstanceId).list(); - for (Task t : list) { - instanceList.stream().filter(e -> e.getTaskDefinitionKey().equals(t.getTaskDefinitionKey())).findFirst().ifPresent(e -> { - taskService.setAssignee(t.getId(), e.getAssignee()); - }); - } - //发送消息 - String message = "您的【" + processInstance.getName() + "】单据已经被驳回,请您注意查收。"; - sendMessage(list, processInstance.getName(), backProcessBo.getMessageType(), message); - //删除流程实例垃圾数据 - for (ExecutionEntity executionEntity : executionEntities) { - DeleteExecutionCmd deleteExecutionCmd = new DeleteExecutionCmd(executionEntity.getId()); - managementService.executeCommand(deleteExecutionCmd); - } - - WfTaskBackNode wfTaskBackNode = wfTaskBackNodeService.getListByInstanceIdAndNodeId(task.getProcessInstanceId(), backProcessBo.getTargetActivityId()); - if (ObjectUtil.isNotNull(wfTaskBackNode) && wfTaskBackNode.getOrderNo() == 0) { - runtimeService.updateBusinessStatus(processInstanceId, BusinessStatusEnum.BACK.getStatus()); - flowProcessEventHandler.processHandler(processInstance.getProcessDefinitionKey(), - processInstance.getBusinessKey(), BusinessStatusEnum.BACK.getStatus(), false); - } - //删除驳回后的流程节点 - wfTaskBackNodeService.deleteBackTaskNode(processInstanceId, backProcessBo.getTargetActivityId()); - } catch (Exception e) { - log.error(e.getMessage(), e); - throw new ServiceException(e.getMessage()); - } - return task.getProcessInstanceId(); - } - - /** - * 修改任务办理人 - * - * @param taskIds 任务id - * @param userId 办理人id - */ - @Override - @Transactional(rollbackFor = Exception.class) - public boolean updateAssignee(String[] taskIds, String userId) { - try { - List list = QueryUtils.taskQuery().taskIds(Arrays.asList(taskIds)).list(); - for (Task task : list) { - taskService.setAssignee(task.getId(), userId); - } - } catch (Exception e) { - log.error("修改失败:" + e.getMessage(), e); - throw new ServiceException("修改失败:" + e.getMessage()); - } - return true; - } - - /** - * 查询流程变量 - * - * @param taskId 任务id - */ - @Override - public List getInstanceVariable(String taskId) { - List variableVoList = new ArrayList<>(); - Map variableInstances = taskService.getVariableInstances(taskId); - if (CollUtil.isNotEmpty(variableInstances)) { - for (Map.Entry entry : variableInstances.entrySet()) { - VariableVo variableVo = new VariableVo(); - variableVo.setKey(entry.getKey()); - variableVo.setValue(entry.getValue().getValue().toString()); - variableVoList.add(variableVo); - } - } - return variableVoList; - } - - /** - * 查询工作流任务用户选择加签人员 - * - * @param taskId 任务id - * @return - */ - @Override - @SuppressWarnings("unchecked") - public String getTaskUserIdsByAddMultiInstance(String taskId) { - Task task = QueryUtils.taskQuery().taskId(taskId).singleResult(); - if (task == null) { - throw new ServiceException("任务不存在"); - } - MultiInstanceVo multiInstance = WorkflowUtils.isMultiInstance(task.getProcessDefinitionId(), task.getTaskDefinitionKey()); - if (multiInstance == null) { - return ""; - } - List userIds; - if (multiInstance.getType() instanceof SequentialMultiInstanceBehavior) { - userIds = (List) runtimeService.getVariable(task.getExecutionId(), multiInstance.getAssigneeList()); - } else { - List list = QueryUtils.taskQuery(task.getProcessInstanceId()).list(); - userIds = StreamUtils.toList(list, e -> Long.valueOf(e.getAssignee())); - } - return StringUtils.join(userIds, StringUtils.SEPARATOR); - } - - /** - * 查询工作流选择减签人员 - * - * @param taskId 任务id 任务id - */ - @Override - @SuppressWarnings("unchecked") - public List getListByDeleteMultiInstance(String taskId) { - Task task = QueryUtils.taskQuery().taskId(taskId).singleResult(); - List taskList = QueryUtils.taskQuery(task.getProcessInstanceId()).list(); - MultiInstanceVo multiInstance = WorkflowUtils.isMultiInstance(task.getProcessDefinitionId(), task.getTaskDefinitionKey()); - List taskListVo = new ArrayList<>(); - if (multiInstance == null) { - return List.of(); - } - List assigneeList = new ArrayList<>(); - if (multiInstance.getType() instanceof SequentialMultiInstanceBehavior) { - List variable = (List) runtimeService.getVariable(task.getExecutionId(), multiInstance.getAssigneeList()); - for (Object o : variable) { - assigneeList.add(Long.valueOf(o.toString())); - } - } - - if (multiInstance.getType() instanceof SequentialMultiInstanceBehavior) { - List userIds = StreamUtils.filter(assigneeList, e -> !String.valueOf(e).equals(task.getAssignee())); - List userList = userService.selectListByIds(userIds); - for (Long userId : userIds) { - TaskVo taskVo = new TaskVo(); - taskVo.setId("串行会签"); - taskVo.setExecutionId("串行会签"); - taskVo.setProcessInstanceId(task.getProcessInstanceId()); - taskVo.setName(task.getName()); - taskVo.setAssignee(userId); - if (CollUtil.isNotEmpty(userList)) { - userList.stream().filter(u -> u.getUserId().toString().equals(userId.toString())).findFirst().ifPresent(u -> taskVo.setAssigneeName(u.getNickName())); - } - taskListVo.add(taskVo); - } - return taskListVo; - } else if (multiInstance.getType() instanceof ParallelMultiInstanceBehavior) { - List tasks = StreamUtils.filter(taskList, e -> StringUtils.isBlank(e.getParentTaskId()) && !e.getExecutionId().equals(task.getExecutionId()) && e.getTaskDefinitionKey().equals(task.getTaskDefinitionKey())); - if (CollUtil.isNotEmpty(tasks)) { - List userIds = StreamUtils.toList(tasks, e -> Long.valueOf(e.getAssignee())); - List userList = userService.selectListByIds(userIds); - for (Task t : tasks) { - TaskVo taskVo = new TaskVo(); - taskVo.setId(t.getId()); - taskVo.setExecutionId(t.getExecutionId()); - taskVo.setProcessInstanceId(t.getProcessInstanceId()); - taskVo.setName(t.getName()); - taskVo.setAssignee(Long.valueOf(t.getAssignee())); - if (CollUtil.isNotEmpty(userList)) { - userList.stream().filter(u -> u.getUserId().toString().equals(t.getAssignee())).findFirst().ifPresent(e -> taskVo.setAssigneeName(e.getNickName())); - } - taskListVo.add(taskVo); - } - return taskListVo; - } - } - return List.of(); - } -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/CategoryNameTranslationImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/CategoryNameTranslationImpl.java new file mode 100644 index 000000000..f13e66645 --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/CategoryNameTranslationImpl.java @@ -0,0 +1,33 @@ +package org.dromara.workflow.service.impl; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.dromara.common.translation.annotation.TranslationType; +import org.dromara.common.translation.core.TranslationInterface; +import org.dromara.workflow.common.ConditionalOnEnable; +import org.dromara.workflow.common.constant.FlowConstant; +import org.dromara.workflow.service.IFlwCategoryService; +import org.springframework.stereotype.Service; + +/** + * 流程分类名称翻译实现 + * + * @author AprilWind + */ +@ConditionalOnEnable +@Slf4j +@RequiredArgsConstructor +@Service +@TranslationType(type = FlowConstant.CATEGORY_ID_TO_NAME) +public class CategoryNameTranslationImpl implements TranslationInterface { + + private final IFlwCategoryService flwCategoryService; + + @Override + public String translation(Object key, String other) { + if (key instanceof String categoryId) { + return flwCategoryService.selectCategoryNameById(categoryId); + } + return null; + } +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwCategoryServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwCategoryServiceImpl.java new file mode 100644 index 000000000..1e9507b80 --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwCategoryServiceImpl.java @@ -0,0 +1,269 @@ +package org.dromara.workflow.service.impl; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.lang.tree.Tree; +import cn.hutool.core.util.ObjectUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import lombok.RequiredArgsConstructor; +import org.dromara.common.core.constant.SystemConstants; +import org.dromara.common.core.exception.ServiceException; +import org.dromara.common.core.utils.*; +import org.dromara.common.mybatis.helper.DataBaseHelper; +import org.dromara.common.satoken.utils.LoginHelper; +import org.dromara.warm.flow.core.service.DefService; +import org.dromara.warm.flow.orm.entity.FlowDefinition; +import org.dromara.workflow.common.ConditionalOnEnable; +import org.dromara.workflow.common.constant.FlowConstant; +import org.dromara.workflow.domain.FlowCategory; +import org.dromara.workflow.domain.bo.FlowCategoryBo; +import org.dromara.workflow.domain.vo.FlowCategoryVo; +import org.dromara.workflow.mapper.FlwCategoryMapper; +import org.dromara.workflow.service.IFlwCategoryService; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; + +/** + * 流程分类Service业务层处理 + * + * @author may + */ +@ConditionalOnEnable +@RequiredArgsConstructor +@Service +public class FlwCategoryServiceImpl implements IFlwCategoryService { + + private final DefService defService; + private final FlwCategoryMapper baseMapper; + + /** + * 查询流程分类 + * + * @param categoryId 主键 + * @return 流程分类 + */ + @Override + public FlowCategoryVo queryById(Long categoryId) { + FlowCategoryVo category = baseMapper.selectVoById(categoryId); + if (ObjectUtil.isNull(category)) { + return null; + } + FlowCategoryVo parentCategory = baseMapper.selectVoOne(new LambdaQueryWrapper() + .select(FlowCategory::getCategoryName).eq(FlowCategory::getCategoryId, category.getParentId())); + category.setParentName(ObjectUtils.notNullGetter(parentCategory, FlowCategoryVo::getCategoryName)); + return category; + } + + /** + * 根据流程分类ID查询流程分类名称 + * + * @param categoryId 流程分类ID + * @return 流程分类名称 + */ + @Cacheable(cacheNames = FlowConstant.FLOW_CATEGORY_NAME, key = "#categoryId") + @Override + public String selectCategoryNameById(String categoryId) { + if (StringUtils.isBlank(categoryId)) { + return null; + } + FlowCategory category = baseMapper.selectOne(new LambdaQueryWrapper() + .select(FlowCategory::getCategoryName).eq(FlowCategory::getCategoryId, categoryId)); + return ObjectUtils.notNullGetter(category, FlowCategory::getCategoryName); + } + + /** + * 查询符合条件的流程分类列表 + * + * @param bo 查询条件 + * @return 流程分类列表 + */ + @Override + public List queryList(FlowCategoryBo bo) { + LambdaQueryWrapper lqw = buildQueryWrapper(bo); + return baseMapper.selectVoList(lqw); + } + + /** + * 查询流程分类树结构信息 + * + * @param category 流程分类信息 + * @return 流程分类树信息集合 + */ + @Override + public List> selectCategoryTreeList(FlowCategoryBo category) { + LambdaQueryWrapper lqw = buildQueryWrapper(category); + List categorys = baseMapper.selectVoList(lqw); + if (CollUtil.isEmpty(categorys)) { + return CollUtil.newArrayList(); + } + // 获取当前列表中每一个节点的parentId,然后在列表中查找是否有id与其parentId对应,若无对应,则表明此时节点列表中,该节点在当前列表中属于顶级节点 + List> treeList = CollUtil.newArrayList(); + for (FlowCategoryVo d : categorys) { + Long parentId = d.getParentId(); + FlowCategoryVo categoryVo = StreamUtils.findFirst(categorys, it -> it.getCategoryId().longValue() == parentId); + if (ObjectUtil.isNull(categoryVo)) { + List> trees = TreeBuildUtils.build(categorys, parentId, (dept, tree) -> + tree.setId(dept.getCategoryId()) + .setParentId(dept.getParentId()) + .setName(dept.getCategoryName()) + .setWeight(dept.getOrderNum())); + Tree tree = StreamUtils.findFirst(trees, it -> it.getId().longValue() == d.getCategoryId()); + treeList.add(tree); + } + } + return treeList; + } + + /** + * 校验流程分类是否有数据权限 + * + * @param categoryId 流程分类ID + */ + @Override + public void checkCategoryDataScope(Long categoryId) { + if (ObjectUtil.isNull(categoryId)) { + return; + } + if (LoginHelper.isSuperAdmin()) { + return; + } + if (baseMapper.countCategoryById(categoryId) == 0) { + throw new ServiceException("没有权限访问流程分类数据!"); + } + } + + /** + * 校验流程分类名称是否唯一 + * + * @param category 流程分类信息 + * @return 结果 + */ + @Override + public boolean checkCategoryNameUnique(FlowCategoryBo category) { + boolean exist = baseMapper.exists(new LambdaQueryWrapper() + .eq(FlowCategory::getCategoryName, category.getCategoryName()) + .eq(FlowCategory::getParentId, category.getParentId()) + .ne(ObjectUtil.isNotNull(category.getCategoryId()), FlowCategory::getCategoryId, category.getCategoryId())); + return !exist; + } + + /** + * 查询流程分类是否存在流程定义 + * + * @param categoryId 流程分类ID + * @return 结果 true 存在 false 不存在 + */ + @Override + public boolean checkCategoryExistDefinition(Long categoryId) { + FlowDefinition definition = new FlowDefinition(); + definition.setCategory(categoryId.toString()); + return defService.exists(definition); + } + + /** + * 是否存在流程分类子节点 + * + * @param categoryId 流程分类ID + * @return 结果 + */ + @Override + public boolean hasChildByCategoryId(Long categoryId) { + return baseMapper.exists(new LambdaQueryWrapper() + .eq(FlowCategory::getParentId, categoryId)); + } + + private LambdaQueryWrapper buildQueryWrapper(FlowCategoryBo bo) { + LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); + lqw.eq(FlowCategory::getDelFlag, SystemConstants.NORMAL); + lqw.eq(ObjectUtil.isNotNull(bo.getCategoryId()), FlowCategory::getCategoryId, bo.getCategoryId()); + lqw.eq(ObjectUtil.isNotNull(bo.getParentId()), FlowCategory::getParentId, bo.getParentId()); + lqw.like(StringUtils.isNotBlank(bo.getCategoryName()), FlowCategory::getCategoryName, bo.getCategoryName()); + lqw.orderByAsc(FlowCategory::getAncestors); + lqw.orderByAsc(FlowCategory::getParentId); + lqw.orderByAsc(FlowCategory::getOrderNum); + lqw.orderByAsc(FlowCategory::getCategoryId); + return lqw; + } + + /** + * 新增流程分类 + * + * @param bo 流程分类 + * @return 是否新增成功 + */ + @Override + public int insertByBo(FlowCategoryBo bo) { + FlowCategory info = baseMapper.selectById(bo.getParentId()); + FlowCategory category = MapstructUtils.convert(bo, FlowCategory.class); + category.setAncestors(info.getAncestors() + StringUtils.SEPARATOR + category.getParentId()); + return baseMapper.insert(category); + } + + /** + * 修改流程分类 + * + * @param bo 流程分类 + * @return 是否修改成功 + */ + @CacheEvict(cacheNames = FlowConstant.FLOW_CATEGORY_NAME, key = "#bo.categoryId") + @Override + public int updateByBo(FlowCategoryBo bo) { + FlowCategory category = MapstructUtils.convert(bo, FlowCategory.class); + FlowCategory oldCategory = baseMapper.selectById(category.getCategoryId()); + if (ObjectUtil.isNull(oldCategory)) { + throw new ServiceException("流程分类不存在,无法修改"); + } + if (!oldCategory.getParentId().equals(category.getParentId())) { + // 如果是新父流程分类 则校验是否具有新父流程分类权限 避免越权 + this.checkCategoryDataScope(category.getParentId()); + FlowCategory newParentCategory = baseMapper.selectById(category.getParentId()); + if (ObjectUtil.isNotNull(newParentCategory)) { + String newAncestors = newParentCategory.getAncestors() + StringUtils.SEPARATOR + newParentCategory.getCategoryId(); + String oldAncestors = oldCategory.getAncestors(); + category.setAncestors(newAncestors); + updateCategoryChildren(category.getCategoryId(), newAncestors, oldAncestors); + } + } else { + category.setAncestors(oldCategory.getAncestors()); + } + return baseMapper.updateById(category); + } + + /** + * 修改子元素关系 + * + * @param categoryId 被修改的流程分类ID + * @param newAncestors 新的父ID集合 + * @param oldAncestors 旧的父ID集合 + */ + private void updateCategoryChildren(Long categoryId, String newAncestors, String oldAncestors) { + List children = baseMapper.selectList(new LambdaQueryWrapper() + .apply(DataBaseHelper.findInSet(categoryId, "ancestors"))); + List list = new ArrayList<>(); + for (FlowCategory child : children) { + FlowCategory category = new FlowCategory(); + category.setCategoryId(child.getCategoryId()); + category.setAncestors(child.getAncestors().replaceFirst(oldAncestors, newAncestors)); + list.add(category); + } + if (CollUtil.isNotEmpty(list)) { + baseMapper.updateBatchById(list); + } + } + + /** + * 删除流程分类信息 + * + * @param categoryId 主键 + * @return 是否删除成功 + */ + @CacheEvict(cacheNames = FlowConstant.FLOW_CATEGORY_NAME, key = "#categoryId") + @Override + public int deleteWithValidById(Long categoryId) { + return baseMapper.deleteById(categoryId); + } +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwDefinitionServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwDefinitionServiceImpl.java new file mode 100644 index 000000000..a881ba692 --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwDefinitionServiceImpl.java @@ -0,0 +1,266 @@ +package org.dromara.workflow.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.convert.Convert; +import cn.hutool.core.io.IoUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.dromara.common.core.exception.ServiceException; +import org.dromara.common.core.utils.StreamUtils; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.json.utils.JsonUtils; +import org.dromara.common.mybatis.core.page.PageQuery; +import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.warm.flow.core.dto.DefJson; +import org.dromara.warm.flow.core.enums.NodeType; +import org.dromara.warm.flow.core.enums.PublishStatus; +import org.dromara.warm.flow.core.service.DefService; +import org.dromara.warm.flow.orm.entity.FlowDefinition; +import org.dromara.warm.flow.orm.entity.FlowHisTask; +import org.dromara.warm.flow.orm.entity.FlowNode; +import org.dromara.warm.flow.orm.entity.FlowSkip; +import org.dromara.warm.flow.orm.mapper.FlowDefinitionMapper; +import org.dromara.warm.flow.orm.mapper.FlowHisTaskMapper; +import org.dromara.warm.flow.orm.mapper.FlowNodeMapper; +import org.dromara.warm.flow.orm.mapper.FlowSkipMapper; +import org.dromara.workflow.common.ConditionalOnEnable; +import org.dromara.workflow.common.constant.FlowConstant; +import org.dromara.workflow.domain.FlowCategory; +import org.dromara.workflow.domain.vo.FlowDefinitionVo; +import org.dromara.workflow.mapper.FlwCategoryMapper; +import org.dromara.workflow.service.IFlwDefinitionService; +import org.dromara.workflow.utils.WorkflowUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static org.dromara.common.core.constant.TenantConstants.DEFAULT_TENANT_ID; + +/** + * 流程定义 服务层实现 + * + * @author may + */ +@ConditionalOnEnable +@Slf4j +@RequiredArgsConstructor +@Service +public class FlwDefinitionServiceImpl implements IFlwDefinitionService { + + private final DefService defService; + private final FlowDefinitionMapper flowDefinitionMapper; + private final FlowHisTaskMapper flowHisTaskMapper; + private final FlowNodeMapper flowNodeMapper; + private final FlowSkipMapper flowSkipMapper; + private final FlwCategoryMapper flwCategoryMapper; + + /** + * 查询流程定义列表 + * + * @param flowDefinition 流程定义信息 + * @param pageQuery 分页 + * @return 返回分页列表 + */ + @Override + public TableDataInfo queryList(FlowDefinition flowDefinition, PageQuery pageQuery) { + LambdaQueryWrapper wrapper = buildQueryWrapper(flowDefinition); + wrapper.eq(FlowDefinition::getIsPublish, PublishStatus.PUBLISHED.getKey()); + Page page = flowDefinitionMapper.selectPage(pageQuery.build(), wrapper); + TableDataInfo build = TableDataInfo.build(); + build.setRows(BeanUtil.copyToList(page.getRecords(), FlowDefinitionVo.class)); + build.setTotal(page.getTotal()); + return build; + } + + /** + * 查询未发布的流程定义列表 + * + * @param flowDefinition 流程定义信息 + * @param pageQuery 分页 + * @return 返回分页列表 + */ + @Override + public TableDataInfo unPublishList(FlowDefinition flowDefinition, PageQuery pageQuery) { + LambdaQueryWrapper wrapper = buildQueryWrapper(flowDefinition); + wrapper.in(FlowDefinition::getIsPublish, Arrays.asList(PublishStatus.UNPUBLISHED.getKey(), PublishStatus.EXPIRED.getKey())); + Page page = flowDefinitionMapper.selectPage(pageQuery.build(), wrapper); + TableDataInfo build = TableDataInfo.build(); + build.setRows(BeanUtil.copyToList(page.getRecords(), FlowDefinitionVo.class)); + build.setTotal(page.getTotal()); + return build; + } + + private LambdaQueryWrapper buildQueryWrapper(FlowDefinition flowDefinition) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(); + wrapper.like(StringUtils.isNotBlank(flowDefinition.getFlowCode()), FlowDefinition::getFlowCode, flowDefinition.getFlowCode()); + wrapper.like(StringUtils.isNotBlank(flowDefinition.getFlowName()), FlowDefinition::getFlowName, flowDefinition.getFlowName()); + if (StringUtils.isNotBlank(flowDefinition.getCategory())) { + List categoryIds = flwCategoryMapper.selectCategoryIdsByParentId(Convert.toLong(flowDefinition.getCategory())); + wrapper.in(FlowDefinition::getCategory, categoryIds); + } + wrapper.orderByDesc(FlowDefinition::getCreateTime); + return wrapper; + } + + /** + * 发布流程定义 + * + * @param id 流程定义id + */ + @Override + @Transactional(rollbackFor = Exception.class) + public boolean publish(Long id) { + List flowNodes = flowNodeMapper.selectList(new LambdaQueryWrapper().eq(FlowNode::getDefinitionId, id)); + List errorMsg = new ArrayList<>(); + if (CollUtil.isNotEmpty(flowNodes)) { + for (FlowNode flowNode : flowNodes) { + String applyNodeCode = WorkflowUtils.applyNodeCode(id); + if (StringUtils.isBlank(flowNode.getPermissionFlag()) && !applyNodeCode.equals(flowNode.getNodeCode()) && NodeType.BETWEEN.getKey().equals(flowNode.getNodeType())) { + errorMsg.add(flowNode.getNodeName()); + } + } + if (CollUtil.isNotEmpty(errorMsg)) { + throw new ServiceException("节点【" + StringUtils.join(errorMsg, ",") + "】未配置办理人!"); + } + } + return defService.publish(id); + } + + /** + * 导入流程定义 + * + * @param file 文件 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public boolean importJson(MultipartFile file, String category) { + try { + DefJson defJson = JsonUtils.parseObject(file.getBytes(), DefJson.class); + defJson.setCategory(category); + defService.importDef(defJson); + } catch (IOException e) { + log.error("读取文件流错误: {}", e.getMessage(), e); + throw new IllegalStateException("文件读取失败,请检查文件内容", e); + } + return true; + } + + /** + * 导出流程定义 + * + * @param id 流程定义id + * @param response 响应 + * @throws IOException 异常 + */ + @Override + public void exportDef(Long id, HttpServletResponse response) throws IOException { + byte[] data = defService.exportJson(id).getBytes(StandardCharsets.UTF_8); + // 设置响应头和内容类型 + response.reset(); + response.setCharacterEncoding(StandardCharsets.UTF_8.name()); + response.setContentType("application/text"); + response.setHeader("Content-Disposition", "attachment;"); + response.addHeader("Content-Length", "" + data.length); + IoUtil.write(response.getOutputStream(), false, data); + } + + /** + * 删除流程定义 + * + * @param ids 流程定义id + */ + @Override + @Transactional(rollbackFor = Exception.class) + public boolean removeDef(List ids) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(); + wrapper.in(FlowHisTask::getDefinitionId, ids); + List flowHisTasks = flowHisTaskMapper.selectList(wrapper); + if (CollUtil.isNotEmpty(flowHisTasks)) { + List flowDefinitions = flowDefinitionMapper.selectByIds(StreamUtils.toList(flowHisTasks, FlowHisTask::getDefinitionId)); + if (CollUtil.isNotEmpty(flowDefinitions)) { + String join = StreamUtils.join(flowDefinitions, FlowDefinition::getFlowCode); + log.error("流程定义【{}】已被使用不可被删除!", join); + throw new ServiceException("流程定义【" + join + "】已被使用不可被删除!"); + } + } + try { + defService.removeDef(ids); + } catch (Exception e) { + log.error("Error removing flow definitions: {}", e.getMessage(), e); + throw new RuntimeException("Failed to remove flow definitions", e); + } + return true; + } + + /** + * 新增租户流程定义 + * + * @param tenantId 租户id + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void syncDef(String tenantId) { + List flowDefinitions = flowDefinitionMapper.selectList(new LambdaQueryWrapper().eq(FlowDefinition::getTenantId, DEFAULT_TENANT_ID)); + if (CollUtil.isEmpty(flowDefinitions)) { + return; + } + FlowCategory flowCategory = flwCategoryMapper.selectOne(new LambdaQueryWrapper() + .eq(FlowCategory::getTenantId, DEFAULT_TENANT_ID).eq(FlowCategory::getCategoryId, FlowConstant.FLOW_CATEGORY_ID)); + flowCategory.setCategoryId(null); + flowCategory.setTenantId(tenantId); + flwCategoryMapper.insert(flowCategory); + List defIds = StreamUtils.toList(flowDefinitions, FlowDefinition::getId); + List flowNodes = flowNodeMapper.selectList(new LambdaQueryWrapper().in(FlowNode::getDefinitionId, defIds)); + List flowSkips = flowSkipMapper.selectList(new LambdaQueryWrapper().in(FlowSkip::getDefinitionId, defIds)); + for (FlowDefinition definition : flowDefinitions) { + FlowDefinition flowDefinition = BeanUtil.toBean(definition, FlowDefinition.class); + flowDefinition.setId(null); + flowDefinition.setTenantId(tenantId); + flowDefinition.setIsPublish(0); + flowDefinition.setCategory(String.valueOf(flowCategory.getCategoryId())); + int insert = flowDefinitionMapper.insert(flowDefinition); + if (insert <= 0) { + log.info("同步流程定义【{}】失败!", definition.getFlowCode()); + continue; + } + log.info("同步流程定义【{}】成功!", definition.getFlowCode()); + Long definitionId = flowDefinition.getId(); + if (CollUtil.isNotEmpty(flowNodes)) { + List nodes = StreamUtils.filter(flowNodes, node -> node.getDefinitionId().equals(definition.getId())); + if (CollUtil.isNotEmpty(nodes)) { + List flowNodeList = BeanUtil.copyToList(nodes, FlowNode.class); + flowNodeList.forEach(e -> { + e.setId(null); + e.setDefinitionId(definitionId); + e.setTenantId(tenantId); + e.setPermissionFlag(null); + }); + flowNodeMapper.insertOrUpdate(flowNodeList); + } + } + if (CollUtil.isNotEmpty(flowSkips)) { + List skips = StreamUtils.filter(flowSkips, skip -> skip.getDefinitionId().equals(definition.getId())); + if (CollUtil.isNotEmpty(skips)) { + List flowSkipList = BeanUtil.copyToList(skips, FlowSkip.class); + flowSkipList.forEach(e -> { + e.setId(null); + e.setDefinitionId(definitionId); + e.setTenantId(tenantId); + }); + flowSkipMapper.insertOrUpdate(flowSkipList); + } + } + } + } +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwInstanceServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwInstanceServiceImpl.java new file mode 100644 index 000000000..f5153c8db --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwInstanceServiceImpl.java @@ -0,0 +1,451 @@ +package org.dromara.workflow.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.convert.Convert; +import cn.hutool.core.util.ObjectUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.dromara.common.core.domain.dto.UserDTO; +import org.dromara.common.core.enums.BusinessStatusEnum; +import org.dromara.common.core.exception.ServiceException; +import org.dromara.common.core.utils.StreamUtils; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.mybatis.core.page.PageQuery; +import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.common.satoken.utils.LoginHelper; +import org.dromara.warm.flow.core.FlowEngine; +import org.dromara.warm.flow.core.constant.ExceptionCons; +import org.dromara.warm.flow.core.dto.FlowParams; +import org.dromara.warm.flow.core.entity.Definition; +import org.dromara.warm.flow.core.entity.Instance; +import org.dromara.warm.flow.core.entity.Task; +import org.dromara.warm.flow.core.enums.NodeType; +import org.dromara.warm.flow.core.service.ChartService; +import org.dromara.warm.flow.core.service.DefService; +import org.dromara.warm.flow.core.service.InsService; +import org.dromara.warm.flow.core.service.TaskService; +import org.dromara.warm.flow.orm.entity.FlowHisTask; +import org.dromara.warm.flow.orm.entity.FlowInstance; +import org.dromara.warm.flow.orm.entity.FlowTask; +import org.dromara.warm.flow.orm.mapper.FlowHisTaskMapper; +import org.dromara.warm.flow.orm.mapper.FlowInstanceMapper; +import org.dromara.workflow.common.ConditionalOnEnable; +import org.dromara.workflow.common.enums.TaskStatusEnum; +import org.dromara.workflow.domain.bo.FlowCancelBo; +import org.dromara.workflow.domain.bo.FlowInstanceBo; +import org.dromara.workflow.domain.bo.FlowInvalidBo; +import org.dromara.workflow.domain.vo.FlowHisTaskVo; +import org.dromara.workflow.domain.vo.FlowInstanceVo; +import org.dromara.workflow.domain.vo.FlowVariableVo; +import org.dromara.workflow.handler.FlowProcessEventHandler; +import org.dromara.workflow.mapper.FlwCategoryMapper; +import org.dromara.workflow.mapper.FlwInstanceMapper; +import org.dromara.workflow.service.IFlwInstanceService; +import org.dromara.workflow.service.IFlwTaskService; +import org.dromara.workflow.utils.WorkflowUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * 流程实例 服务层实现 + * + * @author may + */ +@ConditionalOnEnable +@Slf4j +@RequiredArgsConstructor +@Service +public class FlwInstanceServiceImpl implements IFlwInstanceService { + + private final InsService insService; + private final DefService defService; + private final ChartService chartService; + private final TaskService taskService; + private final FlowHisTaskMapper flowHisTaskMapper; + private final FlowInstanceMapper flowInstanceMapper; + private final FlowProcessEventHandler flowProcessEventHandler; + private final IFlwTaskService flwTaskService; + private final FlwInstanceMapper flwInstanceMapper; + private final FlwCategoryMapper flwCategoryMapper; + + /** + * 分页查询正在运行的流程实例 + * + * @param flowInstanceBo 流程实例 + * @param pageQuery 分页 + */ + @Override + public TableDataInfo selectRunningInstanceList(FlowInstanceBo flowInstanceBo, PageQuery pageQuery) { + QueryWrapper queryWrapper = buildQueryWrapper(flowInstanceBo); + queryWrapper.in("fi.flow_status", BusinessStatusEnum.runningStatus()); + Page page = flwInstanceMapper.selectInstanceList(pageQuery.build(), queryWrapper); + return TableDataInfo.build(page); + } + + /** + * 分页查询已结束的流程实例 + * + * @param flowInstanceBo 流程实例 + * @param pageQuery 分页 + */ + @Override + public TableDataInfo selectFinishInstanceList(FlowInstanceBo flowInstanceBo, PageQuery pageQuery) { + QueryWrapper queryWrapper = buildQueryWrapper(flowInstanceBo); + queryWrapper.in("fi.flow_status", BusinessStatusEnum.finishStatus()); + Page page = flwInstanceMapper.selectInstanceList(pageQuery.build(), queryWrapper); + return TableDataInfo.build(page); + } + + /** + * 根据业务id查询流程实例详细信息 + * + * @param businessId 业务id + * @return 结果 + */ + @Override + public FlowInstanceVo queryByBusinessId(Long businessId) { + FlowInstance instance = this.selectInstByBusinessId(String.valueOf(businessId)); + FlowInstanceVo instanceVo = BeanUtil.toBean(instance, FlowInstanceVo.class); + Definition definition = defService.getById(instanceVo.getDefinitionId()); + instanceVo.setFlowName(definition.getFlowName()); + instanceVo.setFlowCode(definition.getFlowCode()); + instanceVo.setVersion(definition.getVersion()); + instanceVo.setFormCustom(definition.getFormCustom()); + instanceVo.setFormPath(definition.getFormPath()); + instanceVo.setCategory(definition.getCategory()); + return instanceVo; + } + + /** + * 通用查询条件 + * + * @param flowInstanceBo 查询条件 + * @return 查询条件构造方法 + */ + private QueryWrapper buildQueryWrapper(FlowInstanceBo flowInstanceBo) { + QueryWrapper queryWrapper = Wrappers.query(); + queryWrapper.like(StringUtils.isNotBlank(flowInstanceBo.getNodeName()), "fi.node_name", flowInstanceBo.getNodeName()); + queryWrapper.like(StringUtils.isNotBlank(flowInstanceBo.getFlowName()), "fd.flow_name", flowInstanceBo.getFlowName()); + queryWrapper.like(StringUtils.isNotBlank(flowInstanceBo.getFlowCode()), "fd.flow_code", flowInstanceBo.getFlowCode()); + if (StringUtils.isNotBlank(flowInstanceBo.getCategory())) { + List categoryIds = flwCategoryMapper.selectCategoryIdsByParentId(Convert.toLong(flowInstanceBo.getCategory())); + queryWrapper.in("fd.category", categoryIds); + } + queryWrapper.eq(StringUtils.isNotBlank(flowInstanceBo.getBusinessId()), "fi.business_id", flowInstanceBo.getBusinessId()); + queryWrapper.in(CollUtil.isNotEmpty(flowInstanceBo.getCreateByIds()), "fi.create_by", flowInstanceBo.getCreateByIds()); + queryWrapper.eq("fi.del_flag", "0"); + queryWrapper.orderByDesc("fi.create_time"); + return queryWrapper; + } + + /** + * 根据业务id查询流程实例 + * + * @param businessId 业务id + */ + @Override + public FlowInstance selectInstByBusinessId(String businessId) { + return flowInstanceMapper.selectOne(new LambdaQueryWrapper().eq(FlowInstance::getBusinessId, businessId)); + } + + /** + * 按照实例id查询流程实例 + * + * @param instanceId 实例id + */ + @Override + public FlowInstance selectInstById(Long instanceId) { + return flowInstanceMapper.selectById(instanceId); + } + + /** + * 按照实例id查询流程实例 + * + * @param instanceIds 实例id + */ + @Override + public List selectInstListByIdList(List instanceIds) { + return flowInstanceMapper.selectByIds(instanceIds); + } + + /** + * 按照业务id删除流程实例 + * + * @param businessIds 业务id + */ + @Override + @Transactional(rollbackFor = Exception.class) + public boolean deleteByBusinessIds(List businessIds) { + List flowInstances = flowInstanceMapper.selectList(new LambdaQueryWrapper().in(FlowInstance::getBusinessId, businessIds)); + if (CollUtil.isEmpty(flowInstances)) { + log.warn("未找到对应的流程实例信息,无法执行删除操作。"); + return false; + } + return insService.remove(StreamUtils.toList(flowInstances, FlowInstance::getId)); + } + + /** + * 按照实例id删除流程实例 + * + * @param instanceIds 实例id + */ + @Override + @Transactional(rollbackFor = Exception.class) + public boolean deleteByInstanceIds(List instanceIds) { + // 获取实例信息 + List instances = insService.getByIds(instanceIds); + if (CollUtil.isEmpty(instances)) { + log.warn("未找到对应的流程实例信息,无法执行删除操作。"); + return false; + } + // 获取定义信息 + Map definitionMap = defService.getByIds( + StreamUtils.toList(instances, Instance::getDefinitionId) + ).stream().collect(Collectors.toMap(Definition::getId, definition -> definition)); + + // 逐一触发删除事件 + instances.forEach(instance -> { + Definition definition = definitionMap.get(instance.getDefinitionId()); + if (ObjectUtil.isNull(definition)) { + log.warn("实例 ID: {} 对应的流程定义信息未找到,跳过删除事件触发。", instance.getId()); + return; + } + flowProcessEventHandler.processDeleteHandler(definition.getFlowCode(), instance.getBusinessId()); + }); + + // 删除实例 + return insService.remove(instanceIds); + } + + /** + * 撤销流程 + * + * @param bo 参数 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public boolean cancelProcessApply(FlowCancelBo bo) { + try { + Instance instance = selectInstByBusinessId(bo.getBusinessId()); + if (instance == null) { + throw new ServiceException(ExceptionCons.NOT_FOUNT_INSTANCE); + } + Definition definition = defService.getById(instance.getDefinitionId()); + if (definition == null) { + throw new ServiceException(ExceptionCons.NOT_FOUNT_DEF); + } + String message = bo.getMessage(); + BusinessStatusEnum.checkCancelStatus(instance.getFlowStatus()); + String applyNodeCode = WorkflowUtils.applyNodeCode(definition.getId()); + //撤销 + WorkflowUtils.backTask(message, instance.getId(), applyNodeCode, BusinessStatusEnum.CANCEL.getStatus(), BusinessStatusEnum.CANCEL.getStatus()); + //判断或签节点是否有多个,只保留一个 + List currentTaskList = taskService.list(FlowEngine.newTask().setInstanceId(instance.getId())); + if (CollUtil.isNotEmpty(currentTaskList)) { + if (currentTaskList.size() > 1) { + currentTaskList.remove(0); + WorkflowUtils.deleteRunTask(StreamUtils.toList(currentTaskList, Task::getId)); + } + } + + } catch (Exception e) { + log.error("撤销失败: {}", e.getMessage(), e); + throw new ServiceException(e.getMessage()); + } + return true; + } + + /** + * 获取当前登陆人发起的流程实例 + * + * @param instanceBo 流程实例 + * @param pageQuery 分页 + */ + @Override + public TableDataInfo selectCurrentInstanceList(FlowInstanceBo instanceBo, PageQuery pageQuery) { + QueryWrapper queryWrapper = buildQueryWrapper(instanceBo); + queryWrapper.eq("fi.create_by", LoginHelper.getUserIdStr()); + Page page = flwInstanceMapper.selectInstanceList(pageQuery.build(), queryWrapper); + return TableDataInfo.build(page); + } + + /** + * 获取流程图,流程记录 + * + * @param businessId 业务id + */ + @Override + public Map flowImage(String businessId) { + FlowInstance flowInstance = this.selectInstByBusinessId(businessId); + if (ObjectUtil.isNull(flowInstance)) { + throw new ServiceException(ExceptionCons.NOT_FOUNT_INSTANCE); + } + Long instanceId = flowInstance.getId(); + //运行中的任务 + List list = new ArrayList<>(); + List flowTaskList = flwTaskService.selectByInstId(instanceId); + if (CollUtil.isNotEmpty(flowTaskList)) { + List flowHisTaskVos = BeanUtil.copyToList(flowTaskList, FlowHisTaskVo.class); + for (FlowHisTaskVo flowHisTaskVo : flowHisTaskVos) { + flowHisTaskVo.setFlowStatus(TaskStatusEnum.WAITING.getStatus()); + flowHisTaskVo.setUpdateTime(null); + flowHisTaskVo.setRunDuration(null); + List allUser = flwTaskService.currentTaskAllUser(flowHisTaskVo.getId()); + if (CollUtil.isNotEmpty(allUser)) { + String join = StreamUtils.join(allUser, e -> String.valueOf(e.getUserId())); + flowHisTaskVo.setApprover(join); + } + if (BusinessStatusEnum.isDraftOrCancelOrBack(flowInstance.getFlowStatus())) { + flowHisTaskVo.setApprover(LoginHelper.getUserIdStr()); + flowHisTaskVo.setApproveName(LoginHelper.getLoginUser().getNickname()); + } + } + list.addAll(flowHisTaskVos); + } + //历史任务 + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(); + wrapper.eq(FlowHisTask::getInstanceId, instanceId); + wrapper.eq(FlowHisTask::getNodeType, NodeType.BETWEEN.getKey()); + wrapper.orderByDesc(FlowHisTask::getCreateTime).orderByDesc(FlowHisTask::getUpdateTime); + List flowHisTasks = flowHisTaskMapper.selectList(wrapper); + if (CollUtil.isNotEmpty(flowHisTasks)) { + list.addAll(BeanUtil.copyToList(flowHisTasks, FlowHisTaskVo.class)); + } + String flowChart = chartService.chartIns(instanceId); + return Map.of("list", list, "image", flowChart); + } + + /** + * 按照实例id更新状态 + * + * @param instanceId 实例id + * @param status 状态 + */ + @Override + public void updateStatus(Long instanceId, String status) { + LambdaUpdateWrapper wrapper = new LambdaUpdateWrapper<>(); + wrapper.set(FlowInstance::getFlowStatus, status); + wrapper.eq(FlowInstance::getId, instanceId); + flowInstanceMapper.update(wrapper); + } + + /** + * 获取流程变量 + * + * @param instanceId 实例id + */ + @Override + public Map instanceVariable(String instanceId) { + Map map = new HashMap<>(); + FlowInstance flowInstance = flowInstanceMapper.selectById(instanceId); + Map variableMap = flowInstance.getVariableMap(); + List list = new ArrayList<>(); + if (CollUtil.isNotEmpty(variableMap)) { + for (Map.Entry entry : variableMap.entrySet()) { + FlowVariableVo flowVariableVo = new FlowVariableVo(); + flowVariableVo.setKey(entry.getKey()); + flowVariableVo.setValue(entry.getValue().toString()); + list.add(flowVariableVo); + } + } + map.put("variableList", list); + map.put("variable", flowInstance.getVariable()); + return map; + } + + /** + * 设置流程变量 + * + * @param instanceId 实例id + * @param variable 流程变量 + */ + @Override + public void setVariable(Long instanceId, Map variable) { + Instance instance = insService.getById(instanceId); + if (instance != null) { + taskService.mergeVariable(instance, variable); + } + } + + /** + * 按任务id查询实例 + * + * @param taskId 任务id + */ + @Override + public FlowInstance selectByTaskId(Long taskId) { + Task task = taskService.getById(taskId); + if (task == null) { + FlowHisTask flowHisTask = flwTaskService.selectHisTaskById(taskId); + if (flowHisTask != null) { + return this.selectInstById(flowHisTask.getInstanceId()); + } + } else { + return this.selectInstById(task.getInstanceId()); + } + return null; + } + + /** + * 按任务id查询实例 + * + * @param taskIdList 任务id + */ + @Override + public List selectByTaskIdList(List taskIdList) { + if (CollUtil.isEmpty(taskIdList)) { + return Collections.emptyList(); + } + Set instanceIds = new HashSet<>(); + List flowTaskList = flwTaskService.selectByIdList(taskIdList); + for (FlowTask flowTask : flowTaskList) { + instanceIds.add(flowTask.getInstanceId()); + } + List flowHisTaskList = flwTaskService.selectHisTaskByIdList(taskIdList); + for (FlowHisTask flowHisTask : flowHisTaskList) { + instanceIds.add(flowHisTask.getInstanceId()); + } + if (!instanceIds.isEmpty()) { + return this.selectInstListByIdList(new ArrayList<>(instanceIds)); + } + return Collections.emptyList(); + } + + /** + * 作废流程 + * + * @param bo 参数 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public boolean processInvalid(FlowInvalidBo bo) { + try { + Instance instance = insService.getById(bo.getId()); + if (instance != null) { + BusinessStatusEnum.checkInvalidStatus(instance.getFlowStatus()); + } + List flowTaskList = flwTaskService.selectByInstId(bo.getId()); + for (FlowTask flowTask : flowTaskList) { + FlowParams flowParams = new FlowParams(); + flowParams.message(bo.getComment()); + flowParams.flowStatus(BusinessStatusEnum.INVALID.getStatus()) + .hisStatus(TaskStatusEnum.INVALID.getStatus()); + flowParams.ignore(true); + taskService.termination(flowTask.getId(), flowParams); + } + return true; + } catch (Exception e) { + log.error(e.getMessage(), e); + throw new ServiceException(e.getMessage()); + } + } +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskAssigneeServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskAssigneeServiceImpl.java new file mode 100644 index 000000000..5877bb503 --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskAssigneeServiceImpl.java @@ -0,0 +1,165 @@ +package org.dromara.workflow.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.util.StrUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.dromara.common.core.domain.dto.DeptDTO; +import org.dromara.common.core.domain.dto.TaskAssigneeDTO; +import org.dromara.common.core.domain.dto.UserDTO; +import org.dromara.common.core.domain.model.TaskAssigneeBody; +import org.dromara.common.core.enums.FormatsType; +import org.dromara.common.core.exception.ServiceException; +import org.dromara.common.core.service.DeptService; +import org.dromara.common.core.service.TaskAssigneeService; +import org.dromara.common.core.service.UserService; +import org.dromara.common.core.utils.DateUtils; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.warm.flow.ui.dto.HandlerFunDto; +import org.dromara.warm.flow.ui.dto.HandlerQuery; +import org.dromara.warm.flow.ui.dto.TreeFunDto; +import org.dromara.warm.flow.ui.service.HandlerSelectService; +import org.dromara.warm.flow.ui.vo.HandlerSelectVo; +import org.dromara.workflow.common.ConditionalOnEnable; +import org.dromara.workflow.common.enums.TaskAssigneeEnum; +import org.dromara.workflow.service.IFlwTaskAssigneeService; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +/** + * 流程设计器-获取办理人权限设置列表 + * + * @author AprilWind + */ +@ConditionalOnEnable +@Slf4j +@RequiredArgsConstructor +@Service +public class FlwTaskAssigneeServiceImpl implements IFlwTaskAssigneeService, HandlerSelectService { + + private static final String DEFAULT_GROUP_NAME = "默认分组"; + private final TaskAssigneeService taskAssigneeService; + private final UserService userService; + private final DeptService deptService; + + /** + * 获取办理人权限设置列表tabs页签 + * + * @return tabs页签 + */ + @Override + public List getHandlerType() { + return TaskAssigneeEnum.getAssigneeTypeList(); + } + + /** + * 获取办理列表, 同时构建左侧部门树状结构 + * + * @param query 查询条件 + * @return HandlerSelectVo + */ + @Override + public HandlerSelectVo getHandlerSelect(HandlerQuery query) { + // 获取任务办理类型 + TaskAssigneeEnum type = TaskAssigneeEnum.fromDesc(query.getHandlerType()); + // 转换查询条件为 TaskAssigneeBody + TaskAssigneeBody taskQuery = BeanUtil.toBean(query, TaskAssigneeBody.class); + + // 统一查询并构建业务数据 + TaskAssigneeDTO dto = fetchTaskAssigneeData(type, taskQuery); + List depts = fetchDeptData(type); + + return getHandlerSelectVo(buildHandlerData(dto, type), buildDeptTree(depts)); + } + + /** + * 根据任务办理类型查询对应的数据 + */ + private TaskAssigneeDTO fetchTaskAssigneeData(TaskAssigneeEnum type, TaskAssigneeBody taskQuery) { + return switch (type) { + case USER -> taskAssigneeService.selectUsersByTaskAssigneeList(taskQuery); + case ROLE -> taskAssigneeService.selectRolesByTaskAssigneeList(taskQuery); + case DEPT -> taskAssigneeService.selectDeptsByTaskAssigneeList(taskQuery); + case POST -> taskAssigneeService.selectPostsByTaskAssigneeList(taskQuery); + default -> throw new ServiceException("Unsupported handler type"); + }; + } + + /** + * 根据任务办理类型获取部门数据 + */ + private List fetchDeptData(TaskAssigneeEnum type) { + if (type == TaskAssigneeEnum.USER || type == TaskAssigneeEnum.DEPT || type == TaskAssigneeEnum.POST) { + return deptService.selectDeptsByList(); + } + return new ArrayList<>(); + } + + /** + * 构建部门树状结构 + */ + private TreeFunDto buildDeptTree(List depts) { + return new TreeFunDto<>(depts) + .setId(dept -> String.valueOf(dept.getDeptId())) + .setName(DeptDTO::getDeptName) + .setParentId(dept -> String.valueOf(dept.getParentId())); + } + + /** + * 构建任务办理人数据 + */ + private HandlerFunDto buildHandlerData(TaskAssigneeDTO dto, TaskAssigneeEnum type) { + return new HandlerFunDto<>(dto.getList(), dto.getTotal()) + .setStorageId(assignee -> type.getCode() + assignee.getStorageId()) + .setHandlerCode(assignee -> StringUtils.blankToDefault(assignee.getHandlerCode(), "无")) + .setHandlerName(assignee -> StringUtils.blankToDefault(assignee.getHandlerName(), "无")) + .setGroupName(assignee -> StringUtils.defaultIfBlank( + Optional.ofNullable(assignee.getGroupName()) + .map(deptService::selectDeptNameByIds) + .orElse(DEFAULT_GROUP_NAME), DEFAULT_GROUP_NAME)) + .setCreateTime(assignee -> DateUtils.parseDateToStr(FormatsType.YYYY_MM_DD_HH_MM_SS, assignee.getCreateTime())); + } + + /** + * 根据存储标识符(storageId)解析分配类型和ID,并获取对应的用户列表 + * + * @param storageId 包含分配类型和ID的字符串(例如 "user:123" 或 "role:456") + * @return 与分配类型和ID匹配的用户列表,如果格式无效则返回空列表 + */ + @Override + public List fetchUsersByStorageId(String storageId) { + List list = new ArrayList<>(); + for (String str : storageId.split(StrUtil.COMMA)) { + String[] parts = str.split(StrUtil.COLON, 2); + if (parts.length < 2) { + list.addAll(getUsersByType(TaskAssigneeEnum.USER, List.of(Long.valueOf(parts[0])))); + } else { + list.addAll(getUsersByType(TaskAssigneeEnum.fromCode(parts[0] + StrUtil.COLON), List.of(Long.valueOf(parts[1])))); + } + } + return list; + } + + /** + * 根据指定的任务分配类型(TaskAssigneeEnum)和 ID 列表,获取对应的用户信息列表 + * + * @param type 任务分配类型,表示用户、角色、部门或其他(TaskAssigneeEnum 枚举值) + * @param ids 与指定分配类型关联的 ID 列表(例如用户ID、角色ID、部门ID等) + * @return 返回包含用户信息的列表。如果类型为用户(USER),则通过用户ID列表查询; + * 如果类型为角色(ROLE),则通过角色ID列表查询; + * 如果类型为部门(DEPT),则通过部门ID列表查询; + * 如果类型为岗位(POST)或无法识别的类型,则返回空列表 + */ + private List getUsersByType(TaskAssigneeEnum type, List ids) { + return switch (type) { + case USER -> userService.selectListByIds(ids); + case ROLE -> userService.selectUsersByRoleIds(ids); + case DEPT -> userService.selectUsersByDeptIds(ids); + case POST -> userService.selectUsersByPostIds(ids); + }; + } + +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskServiceImpl.java new file mode 100644 index 000000000..f95821d32 --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskServiceImpl.java @@ -0,0 +1,679 @@ +package org.dromara.workflow.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.convert.Convert; +import cn.hutool.core.util.ObjectUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.dromara.common.core.domain.dto.UserDTO; +import org.dromara.common.core.enums.BusinessStatusEnum; +import org.dromara.common.core.exception.ServiceException; +import org.dromara.common.core.service.UserService; +import org.dromara.common.core.utils.SpringUtils; +import org.dromara.common.core.utils.StreamUtils; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.core.utils.ValidatorUtils; +import org.dromara.common.core.validate.AddGroup; +import org.dromara.common.core.validate.EditGroup; +import org.dromara.common.mybatis.core.page.PageQuery; +import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.common.satoken.utils.LoginHelper; +import org.dromara.warm.flow.core.dto.FlowParams; +import org.dromara.warm.flow.core.entity.*; +import org.dromara.warm.flow.core.enums.NodeType; +import org.dromara.warm.flow.core.enums.SkipType; +import org.dromara.warm.flow.core.service.*; +import org.dromara.warm.flow.orm.entity.*; +import org.dromara.warm.flow.orm.mapper.FlowHisTaskMapper; +import org.dromara.warm.flow.orm.mapper.FlowInstanceMapper; +import org.dromara.warm.flow.orm.mapper.FlowTaskMapper; +import org.dromara.workflow.common.ConditionalOnEnable; +import org.dromara.workflow.common.enums.TaskAssigneeType; +import org.dromara.workflow.common.enums.TaskStatusEnum; +import org.dromara.workflow.domain.bo.*; +import org.dromara.workflow.domain.vo.FlowHisTaskVo; +import org.dromara.workflow.domain.vo.FlowTaskVo; +import org.dromara.workflow.handler.FlowProcessEventHandler; +import org.dromara.workflow.handler.WorkflowPermissionHandler; +import org.dromara.workflow.mapper.FlwCategoryMapper; +import org.dromara.workflow.mapper.FlwTaskMapper; +import org.dromara.workflow.service.IFlwTaskService; +import org.dromara.workflow.utils.WorkflowUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.math.BigDecimal; +import java.util.*; +import java.util.stream.Collectors; + +import static org.dromara.workflow.common.constant.FlowConstant.*; + +/** + * 任务 服务层实现 + * + * @author may + */ +@ConditionalOnEnable +@Slf4j +@RequiredArgsConstructor +@Service +public class FlwTaskServiceImpl implements IFlwTaskService { + + private final TaskService taskService; + private final InsService insService; + private final DefService defService; + private final HisTaskService hisTaskService; + private final NodeService nodeService; + private final FlowInstanceMapper flowInstanceMapper; + private final FlowTaskMapper flowTaskMapper; + private final FlowHisTaskMapper flowHisTaskMapper; + private final IdentifierGenerator identifierGenerator; + private final FlowProcessEventHandler flowProcessEventHandler; + private final UserService userService; + private final FlwTaskMapper flwTaskMapper; + private final FlwCategoryMapper flwCategoryMapper; + + /** + * 启动任务 + * + * @param startProcessBo 启动流程参数 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public Map startWorkFlow(StartProcessBo startProcessBo) { + String businessId = startProcessBo.getBusinessId(); + if (StringUtils.isBlank(businessId)) { + throw new ServiceException("启动工作流时必须包含业务ID"); + } + // 启动流程实例(提交申请) + Map variables = startProcessBo.getVariables(); + // 流程发起人 + variables.put(INITIATOR, LoginHelper.getUserIdStr()); + // 业务id + variables.put(BUSINESS_ID, businessId); + FlowInstance flowInstance = flowInstanceMapper.selectOne(new LambdaQueryWrapper<>(FlowInstance.class) + .eq(FlowInstance::getBusinessId, businessId)); + if (ObjectUtil.isNotNull(flowInstance)) { + BusinessStatusEnum.checkStartStatus(flowInstance.getFlowStatus()); + List taskList = taskService.list(new FlowTask().setInstanceId(flowInstance.getId())); + return Map.of(PROCESS_INSTANCE_ID, taskList.get(0).getInstanceId(), TASK_ID, taskList.get(0).getId()); + } + FlowParams flowParams = new FlowParams(); + flowParams.flowCode(startProcessBo.getFlowCode()); + flowParams.variable(startProcessBo.getVariables()); + flowParams.flowStatus(BusinessStatusEnum.DRAFT.getStatus()); + Instance instance; + try { + instance = insService.start(businessId, flowParams); + } catch (Exception e) { + throw new ServiceException(e.getMessage()); + } + // 申请人执行流程 + List taskList = taskService.list(new FlowTask().setInstanceId(instance.getId())); + if (taskList.size() > 1) { + throw new ServiceException("请检查流程第一个环节是否为申请人!"); + } + return Map.of(PROCESS_INSTANCE_ID, instance.getId(), TASK_ID, taskList.get(0).getId()); + } + + /** + * 办理任务 + * + * @param completeTaskBo 办理任务参数 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public boolean completeTask(CompleteTaskBo completeTaskBo) { + try { + // 获取任务ID并查询对应的流程任务和实例信息 + Long taskId = completeTaskBo.getTaskId(); + List messageType = completeTaskBo.getMessageType(); + String notice = completeTaskBo.getNotice(); + // 获取抄送人 + List flowCopyList = completeTaskBo.getFlowCopyList(); + FlowTask flowTask = flowTaskMapper.selectById(taskId); + if (ObjectUtil.isNull(flowTask)) { + throw new ServiceException("流程任务不存在或任务已审批!"); + } + Instance ins = insService.getById(flowTask.getInstanceId()); + // 获取流程定义信息 + Definition definition = defService.getById(flowTask.getDefinitionId()); + // 检查流程状态是否为草稿、已撤销或已退回状态,若是则执行流程提交监听 + if (BusinessStatusEnum.isDraftOrCancelOrBack(ins.getFlowStatus())) { + flowProcessEventHandler.processHandler(definition.getFlowCode(), ins.getBusinessId(), ins.getFlowStatus(), true); + } + // 构建流程参数,包括变量、跳转类型、消息、处理人、权限等信息 + FlowParams flowParams = new FlowParams(); + flowParams.variable(completeTaskBo.getVariables()); + flowParams.skipType(SkipType.PASS.getKey()); + flowParams.message(completeTaskBo.getMessage()); + flowParams.flowStatus(BusinessStatusEnum.WAITING.getStatus()).hisStatus(TaskStatusEnum.PASS.getStatus()); + + flowParams.hisTaskExt(completeTaskBo.getFileId()); + // 执行任务跳转,并根据返回的处理人设置下一步处理人 + Instance instance = taskService.skip(taskId, flowParams); + this.setHandler(instance, flowTask, flowCopyList); + // 消息通知 + WorkflowUtils.sendMessage(definition.getFlowName(), ins.getId(), messageType, notice); + return true; + } catch (Exception e) { + log.error(e.getMessage(), e); + throw new ServiceException(e.getMessage()); + } + } + + /** + * 设置办理人 + * + * @param instance 实例 + * @param task (当前任务)未办理的任务 + * @param flowCopyList 抄送人 + */ + private void setHandler(Instance instance, FlowTask task, List flowCopyList) { + if (ObjectUtil.isNull(instance)) { + return; + } + // 添加抄送人 + this.setCopy(task, flowCopyList); + // 根据流程实例ID查询所有关联的任务 + List flowTasks = this.selectByInstId(instance.getId()); + if (CollUtil.isEmpty(flowTasks)) { + return; + } + List taskIdList = StreamUtils.toList(flowTasks, FlowTask::getId); + // 获取与当前任务关联的用户列表 + List associatedUsers = WorkflowUtils.getFlowUserService().getByAssociateds(taskIdList); + if (CollUtil.isEmpty(associatedUsers)) { + return; + } + List userList = new ArrayList<>(); + // 遍历任务列表,处理每个任务的办理人 + for (FlowTask flowTask : flowTasks) { + List users = StreamUtils.filter(associatedUsers, user -> Objects.equals(user.getAssociated(), flowTask.getId())); + if (CollUtil.isNotEmpty(users)) { + userList.addAll(WorkflowUtils.buildUser(users, flowTask.getId())); + } + } + // 批量删除现有任务的办理人记录 + WorkflowUtils.getFlowUserService().deleteByTaskIds(taskIdList); + // 确保要保存的 userList 不为空 + if (CollUtil.isEmpty(userList)) { + return; + } + WorkflowUtils.getFlowUserService().saveBatch(userList); + } + + /** + * 添加抄送人 + * + * @param task 任务信息 + * @param flowCopyList 抄送人 + */ + public void setCopy(FlowTask task, List flowCopyList) { + if (CollUtil.isEmpty(flowCopyList)) { + return; + } + // 添加抄送人记录 + FlowHisTask flowHisTask = flowHisTaskMapper.selectList(new LambdaQueryWrapper<>(FlowHisTask.class).eq(FlowHisTask::getTaskId, task.getId())).get(0); + FlowNode flowNode = new FlowNode(); + flowNode.setNodeCode(flowHisTask.getTargetNodeCode()); + flowNode.setNodeName(flowHisTask.getTargetNodeName()); + //生成新的任务id + long taskId = identifierGenerator.nextId(null).longValue(); + task.setId(taskId); + task.setNodeName("【抄送】" + task.getNodeName()); + Date updateTime = new Date(flowHisTask.getUpdateTime().getTime() - 1000); + FlowParams flowParams = FlowParams.build(); + flowParams.skipType(SkipType.NONE.getKey()); + flowParams.hisStatus(TaskStatusEnum.COPY.getStatus()); + flowParams.message("【抄送给】" + StreamUtils.join(flowCopyList, FlowCopyBo::getUserName)); + HisTask hisTask = hisTaskService.setSkipHisTask(task, flowNode, flowParams); + hisTask.setCreateTime(updateTime); + hisTask.setUpdateTime(updateTime); + hisTaskService.save(hisTask); + List userList = flowCopyList.stream() + .map(flowCopy -> { + FlowUser flowUser = new FlowUser(); + flowUser.setType(TaskAssigneeType.COPY.getCode()); + flowUser.setProcessedBy(String.valueOf(flowCopy.getUserId())); + flowUser.setAssociated(taskId); + return flowUser; + }).collect(Collectors.toList()); + // 批量保存抄送人员 + WorkflowUtils.getFlowUserService().saveBatch(userList); + } + + /** + * 查询当前用户的待办任务 + * + * @param flowTaskBo 参数 + * @param pageQuery 分页 + */ + @Override + public TableDataInfo pageByTaskWait(FlowTaskBo flowTaskBo, PageQuery pageQuery) { + QueryWrapper queryWrapper = buildQueryWrapper(flowTaskBo); + queryWrapper.eq("t.node_type", NodeType.BETWEEN.getKey()); + queryWrapper.in("t.processed_by", SpringUtils.getBean(WorkflowPermissionHandler.class).permissions()); + queryWrapper.in("t.flow_status", BusinessStatusEnum.WAITING.getStatus()); + Page page = this.getFlowTaskVoPage(pageQuery, queryWrapper); + return TableDataInfo.build(page); + } + + /** + * 查询当前用户的已办任务 + * + * @param flowTaskBo 参数 + * @param pageQuery 分页 + */ + @Override + public TableDataInfo pageByTaskFinish(FlowTaskBo flowTaskBo, PageQuery pageQuery) { + QueryWrapper queryWrapper = buildQueryWrapper(flowTaskBo); + queryWrapper.eq("t.node_type", NodeType.BETWEEN.getKey()); + queryWrapper.in("t.approver", LoginHelper.getUserIdStr()); + queryWrapper.orderByDesc("t.create_time").orderByDesc("t.update_time"); + Page page = flwTaskMapper.getListFinishTask(pageQuery.build(), queryWrapper); + return TableDataInfo.build(page); + } + + /** + * 查询待办任务 + * + * @param flowTaskBo 参数 + * @param pageQuery 分页 + */ + @Override + public TableDataInfo pageByAllTaskWait(FlowTaskBo flowTaskBo, PageQuery pageQuery) { + QueryWrapper queryWrapper = buildQueryWrapper(flowTaskBo); + queryWrapper.eq("t.node_type", NodeType.BETWEEN.getKey()); + Page page = getFlowTaskVoPage(pageQuery, queryWrapper); + return TableDataInfo.build(page); + } + + private Page getFlowTaskVoPage(PageQuery pageQuery, QueryWrapper queryWrapper) { + Page page = flwTaskMapper.getListRunTask(pageQuery.build(), queryWrapper); + List records = page.getRecords(); + if (CollUtil.isNotEmpty(records)) { + List taskIds = StreamUtils.toList(records, FlowTaskVo::getId); + Map> listMap = currentTaskAllUser(taskIds); + records.forEach(t -> { + List userList = listMap.getOrDefault(t.getId(), Collections.emptyList()); + if (CollUtil.isNotEmpty(userList)) { + t.setAssigneeIds(StreamUtils.join(userList, e -> String.valueOf(e.getUserId()))); + t.setAssigneeNames(StreamUtils.join(userList, UserDTO::getNickName)); + } + }); + } + return page; + } + + /** + * 查询已办任务 + * + * @param flowTaskBo 参数 + * @param pageQuery 分页 + */ + @Override + public TableDataInfo pageByAllTaskFinish(FlowTaskBo flowTaskBo, PageQuery pageQuery) { + QueryWrapper queryWrapper = buildQueryWrapper(flowTaskBo); + Page page = flwTaskMapper.getListFinishTask(pageQuery.build(), queryWrapper); + return TableDataInfo.build(page); + } + + /** + * 查询当前用户的抄送 + * + * @param flowTaskBo 参数 + * @param pageQuery 分页 + */ + @Override + public TableDataInfo pageByTaskCopy(FlowTaskBo flowTaskBo, PageQuery pageQuery) { + QueryWrapper queryWrapper = buildQueryWrapper(flowTaskBo); + queryWrapper.in("t.processed_by", LoginHelper.getUserIdStr()); + Page page = flwTaskMapper.getTaskCopyByPage(pageQuery.build(), queryWrapper); + return TableDataInfo.build(page); + } + + private QueryWrapper buildQueryWrapper(FlowTaskBo flowTaskBo) { + QueryWrapper wrapper = Wrappers.query(); + wrapper.like(StringUtils.isNotBlank(flowTaskBo.getNodeName()), "t.node_name", flowTaskBo.getNodeName()); + wrapper.like(StringUtils.isNotBlank(flowTaskBo.getFlowName()), "t.flow_name", flowTaskBo.getFlowName()); + wrapper.like(StringUtils.isNotBlank(flowTaskBo.getFlowCode()), "t.flow_code", flowTaskBo.getFlowCode()); + wrapper.in(CollUtil.isNotEmpty(flowTaskBo.getCreateByIds()), "t.create_by", flowTaskBo.getCreateByIds()); + if (StringUtils.isNotBlank(flowTaskBo.getCategory())) { + List categoryIds = flwCategoryMapper.selectCategoryIdsByParentId(Convert.toLong(flowTaskBo.getCategory())); + wrapper.in("t.category", categoryIds); + } + wrapper.orderByDesc("t.create_time"); + return wrapper; + } + + /** + * 驳回任务 + * + * @param bo 参数 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public boolean backProcess(BackProcessBo bo) { + try { + Long taskId = bo.getTaskId(); + String notice = bo.getNotice(); + List messageType = bo.getMessageType(); + String message = bo.getMessage(); + FlowTask task = flowTaskMapper.selectById(taskId); + if (ObjectUtil.isNull(task)) { + throw new ServiceException("任务不存在!"); + } + Instance inst = insService.getById(task.getInstanceId()); + BusinessStatusEnum.checkBackStatus(inst.getFlowStatus()); + Long definitionId = task.getDefinitionId(); + Definition definition = defService.getById(definitionId); + String applyNodeCode = WorkflowUtils.applyNodeCode(definitionId); + FlowParams flowParams = FlowParams.build(); + flowParams.nodeCode(bo.getNodeCode()); + flowParams.message(message); + flowParams.skipType(SkipType.REJECT.getKey()); + flowParams.flowStatus(applyNodeCode.equals(bo.getNodeCode()) ? TaskStatusEnum.BACK.getStatus() : TaskStatusEnum.WAITING.getStatus()) + .hisStatus(TaskStatusEnum.BACK.getStatus()); + taskService.skip(task.getId(), flowParams); + + Instance instance = insService.getById(inst.getId()); + this.setHandler(instance, task, null); + // 消息通知 + WorkflowUtils.sendMessage(definition.getFlowName(), instance.getId(), messageType, notice); + return true; + } catch (Exception e) { + log.error(e.getMessage(), e); + throw new ServiceException(e.getMessage()); + } + } + + /** + * 获取可驳回的前置节点 + * + * @param definitionId 流程定义id + * @param nowNodeCode 当前节点 + */ + @Override + public List getBackTaskNode(Long definitionId, String nowNodeCode) { + List nodeCodes = nodeService.getByNodeCodes(Collections.singletonList(nowNodeCode), definitionId); + if (!CollUtil.isNotEmpty(nodeCodes)) { + return nodeCodes; + } + //判断是否配置了固定驳回节点 + Node node = nodeCodes.get(0); + if (StringUtils.isNotBlank(node.getAnyNodeSkip())) { + return nodeService.getByNodeCodes(Collections.singletonList(node.getAnyNodeSkip()), definitionId); + } + //获取可驳回的前置节点 + List nodes = nodeService.previousNodeList(definitionId, nowNodeCode); + if (CollUtil.isNotEmpty(nodes)) { + return StreamUtils.filter(nodes, e -> NodeType.BETWEEN.getKey().equals(e.getNodeType())); + } + return nodes; + } + + /** + * 终止任务 + * + * @param bo 参数 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public boolean terminationTask(FlowTerminationBo bo) { + try { + Long taskId = bo.getTaskId(); + Task task = taskService.getById(taskId); + if (task == null) { + throw new ServiceException("任务不存在!"); + } + Instance instance = insService.getById(task.getInstanceId()); + if (ObjectUtil.isNotNull(instance)) { + BusinessStatusEnum.checkInvalidStatus(instance.getFlowStatus()); + } + FlowParams flowParams = new FlowParams(); + flowParams.message(bo.getComment()); + flowParams.flowStatus(BusinessStatusEnum.TERMINATION.getStatus()) + .hisStatus(TaskStatusEnum.TERMINATION.getStatus()); + taskService.termination(taskId, flowParams); + return true; + } catch (Exception e) { + log.error(e.getMessage(), e); + throw new ServiceException(e.getMessage()); + } + } + + /** + * 按照任务id查询任务 + * + * @param taskIdList 任务id + */ + @Override + public List selectByIdList(List taskIdList) { + return flowTaskMapper.selectList(new LambdaQueryWrapper<>(FlowTask.class) + .in(FlowTask::getId, taskIdList)); + } + + /** + * 按照任务id查询任务 + * + * @param taskId 任务id + */ + @Override + public FlowTaskVo selectById(Long taskId) { + Task task = taskService.getById(taskId); + if (ObjectUtil.isNull(task)) { + return null; + } + FlowTaskVo flowTaskVo = BeanUtil.toBean(task, FlowTaskVo.class); + Instance instance = insService.getById(task.getInstanceId()); + Definition definition = defService.getById(task.getDefinitionId()); + flowTaskVo.setFlowStatus(instance.getFlowStatus()); + flowTaskVo.setVersion(definition.getVersion()); + flowTaskVo.setFlowCode(definition.getFlowCode()); + flowTaskVo.setFlowName(definition.getFlowName()); + flowTaskVo.setBusinessId(instance.getBusinessId()); + List nodeList = nodeService.getByNodeCodes(Collections.singletonList(flowTaskVo.getNodeCode()), instance.getDefinitionId()); + if (CollUtil.isNotEmpty(nodeList)) { + Node node = nodeList.get(0); + flowTaskVo.setNodeRatio(node.getNodeRatio()); + } + return flowTaskVo; + } + + /** + * 按照任务id查询任务 + * + * @param taskIdList 任务id + * @return 结果 + */ + @Override + public List selectHisTaskByIdList(List taskIdList) { + return flowHisTaskMapper.selectList(new LambdaQueryWrapper<>(FlowHisTask.class) + .in(FlowHisTask::getId, taskIdList)); + } + + /** + * 按照任务id查询任务 + * + * @param taskId 任务id + * @return 结果 + */ + @Override + public FlowHisTask selectHisTaskById(Long taskId) { + return flowHisTaskMapper.selectOne(new LambdaQueryWrapper<>(FlowHisTask.class) + .eq(FlowHisTask::getId, taskId)); + } + + /** + * 按照实例id查询任务 + * + * @param instanceIdList 流程实例id + */ + @Override + public List selectByInstIdList(List instanceIdList) { + return flowTaskMapper.selectList(new LambdaQueryWrapper<>(FlowTask.class) + .in(FlowTask::getInstanceId, instanceIdList)); + } + + /** + * 按照实例id查询任务 + * + * @param instanceId 流程实例id + */ + @Override + public List selectByInstId(Long instanceId) { + return flowTaskMapper.selectList(new LambdaQueryWrapper<>(FlowTask.class) + .eq(FlowTask::getInstanceId, instanceId)); + } + + /** + * 任务操作 + * + * @param bo 参数 + * @param taskOperation 操作类型,委派 delegateTask、转办 transferTask、加签 addSignature、减签 reductionSignature + */ + @Override + @Transactional(rollbackFor = Exception.class) + public boolean taskOperation(TaskOperationBo bo, String taskOperation) { + FlowParams flowParams = new FlowParams(); + flowParams.message(bo.getMessage()); + if (LoginHelper.isSuperAdmin() || LoginHelper.isTenantAdmin()) { + flowParams.ignore(true); + } + + // 根据操作类型构建 FlowParams + switch (taskOperation) { + case DELEGATE_TASK, TRANSFER_TASK -> { + ValidatorUtils.validate(bo, AddGroup.class); + flowParams.addHandlers(Collections.singletonList(bo.getUserId())); + } + case ADD_SIGNATURE -> { + ValidatorUtils.validate(bo, EditGroup.class); + flowParams.addHandlers(bo.getUserIds()); + } + case REDUCTION_SIGNATURE -> { + ValidatorUtils.validate(bo, EditGroup.class); + flowParams.reductionHandlers(bo.getUserIds()); + } + default -> { + log.error("Invalid operation type:{} ", taskOperation); + throw new ServiceException("Invalid operation type " + taskOperation); + } + } + + Long taskId = bo.getTaskId(); + FlowTaskVo flowTaskVo = selectById(taskId); + if ("addSignature".equals(taskOperation) || "reductionSignature".equals(taskOperation)) { + if (flowTaskVo.getNodeRatio().compareTo(BigDecimal.ZERO) == 0) { + throw new ServiceException(flowTaskVo.getNodeName() + "不是会签节点!"); + } + } + // 设置任务状态并执行对应的任务操作 + switch (taskOperation) { + //委派任务 + case DELEGATE_TASK -> { + flowParams.hisStatus(TaskStatusEnum.DEPUTE.getStatus()); + return taskService.depute(taskId, flowParams); + } + //转办任务 + case TRANSFER_TASK -> { + flowParams.hisStatus(TaskStatusEnum.TRANSFER.getStatus()); + return taskService.transfer(taskId, flowParams); + } + //加签,增加办理人 + case ADD_SIGNATURE -> { + flowParams.hisStatus(TaskStatusEnum.SIGN.getStatus()); + return taskService.addSignature(taskId, flowParams); + } + //减签,减少办理人 + case REDUCTION_SIGNATURE -> { + flowParams.hisStatus(TaskStatusEnum.SIGN_OFF.getStatus()); + return taskService.reductionSignature(taskId, flowParams); + } + default -> { + log.error("Invalid operation type:{} ", taskOperation); + throw new ServiceException("Invalid operation type " + taskOperation); + } + } + } + + /** + * 修改任务办理人(此方法将会批量修改所有任务的办理人) + * + * @param taskIdList 任务id + * @param userId 用户id + */ + @Override + @Transactional(rollbackFor = Exception.class) + public boolean updateAssignee(List taskIdList, String userId) { + if (CollUtil.isEmpty(taskIdList)) { + return false; + } + try { + List flowTasks = this.selectByIdList(taskIdList); + // 批量删除现有任务的办理人记录 + if (CollUtil.isNotEmpty(flowTasks)) { + WorkflowUtils.getFlowUserService().deleteByTaskIds(StreamUtils.toList(flowTasks, FlowTask::getId)); + List userList = flowTasks.stream() + .map(flowTask -> { + FlowUser flowUser = new FlowUser(); + flowUser.setType(TaskAssigneeType.APPROVER.getCode()); + flowUser.setProcessedBy(userId); + flowUser.setAssociated(flowTask.getId()); + return flowUser; + }) + .collect(Collectors.toList()); + if (CollUtil.isNotEmpty(userList)) { + WorkflowUtils.getFlowUserService().saveBatch(userList); + } + } + } catch (Exception e) { + log.error(e.getMessage(), e); + throw new ServiceException(e.getMessage()); + } + return true; + } + + /** + * 获取任务所有办理人 + * + * @param taskIdList 任务id + */ + @Override + public Map> currentTaskAllUser(List taskIdList) { + Map> map = new HashMap<>(); + // 获取与当前任务关联的用户列表 + List associatedUsers = WorkflowUtils.getFlowUserService().getByAssociateds(taskIdList); + Map> listMap = StreamUtils.groupByKey(associatedUsers, User::getAssociated); + for (Map.Entry> entry : listMap.entrySet()) { + List value = entry.getValue(); + if (CollUtil.isNotEmpty(value)) { + List userDTOS = userService.selectListByIds(StreamUtils.toList(value, e -> Long.valueOf(e.getProcessedBy()))); + map.put(entry.getKey(), userDTOS); + } + } + return map; + } + + /** + * 获取当前任务的所有办理人 + * + * @param taskId 任务id + */ + @Override + public List currentTaskAllUser(Long taskId) { + // 获取与当前任务关联的用户列表 + List userList = WorkflowUtils.getFlowUserService().getByAssociateds(Collections.singletonList(taskId)); + if (CollUtil.isEmpty(userList)) { + return Collections.emptyList(); + } + return userService.selectListByIds(StreamUtils.toList(userList, e -> Long.valueOf(e.getProcessedBy()))); + } +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/TestLeaveServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/TestLeaveServiceImpl.java index f81c85f7c..a11e6c19a 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/TestLeaveServiceImpl.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/TestLeaveServiceImpl.java @@ -1,20 +1,23 @@ package org.dromara.workflow.service.impl; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.dromara.common.core.domain.event.ProcessDeleteEvent; import org.dromara.common.core.domain.event.ProcessEvent; import org.dromara.common.core.domain.event.ProcessTaskEvent; import org.dromara.common.core.enums.BusinessStatusEnum; import org.dromara.common.core.service.WorkflowService; import org.dromara.common.core.utils.MapstructUtils; -import org.dromara.common.core.utils.StreamUtils; import org.dromara.common.core.utils.StringUtils; import org.dromara.common.mybatis.core.domain.BaseEntity; import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.workflow.common.ConditionalOnEnable; import org.dromara.workflow.domain.TestLeave; import org.dromara.workflow.domain.bo.TestLeaveBo; import org.dromara.workflow.domain.vo.TestLeaveVo; @@ -24,7 +27,6 @@ import org.springframework.context.event.EventListener; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.Collection; import java.util.List; /** @@ -33,6 +35,7 @@ import java.util.List; * @author may * @date 2023-07-21 */ +@ConditionalOnEnable @RequiredArgsConstructor @Service @Slf4j @@ -82,6 +85,9 @@ public class TestLeaveServiceImpl implements ITestLeaveService { */ @Override public TestLeaveVo insertByBo(TestLeaveBo bo) { + long day = DateUtil.betweenDay(bo.getStartDate(), bo.getEndDate(), true); + // 截止日期也算一天 + bo.setLeaveDays((int) day + 1); TestLeave add = MapstructUtils.convert(bo, TestLeave.class); if (StringUtils.isBlank(add.getStatus())) { add.setStatus(BusinessStatusEnum.DRAFT.getStatus()); @@ -108,23 +114,22 @@ public class TestLeaveServiceImpl implements ITestLeaveService { */ @Override @Transactional(rollbackFor = Exception.class) - public Boolean deleteWithValidByIds(Collection ids) { - List idList = StreamUtils.toList(ids, String::valueOf); - workflowService.deleteRunAndHisInstance(idList); + public Boolean deleteWithValidByIds(List ids) { + workflowService.deleteInstance(ids); return baseMapper.deleteByIds(ids) > 0; } /** - * 总体流程监听(例如: 提交 退回 撤销 终止 作废等) - * 正常使用只需#processEvent.key=='leave1' + * 总体流程监听(例如: 草稿,撤销,退回,作废,终止,已完成等) + * 正常使用只需#processEvent.flowCode=='leave1' * 示例为了方便则使用startsWith匹配了全部示例key * * @param processEvent 参数 */ - @EventListener(condition = "#processEvent.key.startsWith('leave')") + @EventListener(condition = "#processEvent.flowCode.startsWith('leave')") public void processHandler(ProcessEvent processEvent) { log.info("当前任务执行了{}", processEvent.toString()); - TestLeave testLeave = baseMapper.selectById(Long.valueOf(processEvent.getBusinessKey())); + TestLeave testLeave = baseMapper.selectById(Long.valueOf(processEvent.getBusinessId())); testLeave.setStatus(processEvent.getStatus()); if (processEvent.isSubmit()) { testLeave.setStatus(BusinessStatusEnum.WAITING.getStatus()); @@ -134,24 +139,37 @@ public class TestLeaveServiceImpl implements ITestLeaveService { /** * 执行办理任务监听 - * 示例:也可通过 @EventListener(condition = "#processTaskEvent.key=='leave1'")进行判断 + * 示例:也可通过 @EventListener(condition = "#processTaskEvent.flowCode=='leave1'")进行判断 * 在方法中判断流程节点key - * if ("xxx".equals(processTaskEvent.getTaskDefinitionKey())) { + * if ("xxx".equals(processTaskEvent.getNodeCode())) { * //执行业务逻辑 * } * * @param processTaskEvent 参数 */ - @EventListener(condition = "#processTaskEvent.key.startsWith('leave')") + @EventListener(condition = "#processTaskEvent.flowCode.startsWith('leave')") public void processTaskHandler(ProcessTaskEvent processTaskEvent) { - // 所有demo案例的申请人节点id - String[] ids = {"Activity_14633hx", "Activity_19b1i4j", "Activity_0uscrk3", - "Activity_0uscrk3", "Activity_0x6b71j", "Activity_0zy3g6j", "Activity_06a55t0"}; - if (StringUtils.equalsAny(processTaskEvent.getTaskDefinitionKey(), ids)) { - log.info("当前任务执行了{}", processTaskEvent.toString()); - TestLeave testLeave = baseMapper.selectById(Long.valueOf(processTaskEvent.getBusinessKey())); - testLeave.setStatus(BusinessStatusEnum.WAITING.getStatus()); - baseMapper.updateById(testLeave); - } + log.info("当前任务执行了{}", processTaskEvent.toString()); + TestLeave testLeave = baseMapper.selectById(Long.valueOf(processTaskEvent.getBusinessId())); + testLeave.setStatus(BusinessStatusEnum.WAITING.getStatus()); + baseMapper.updateById(testLeave); } + + /** + * 监听删除流程事件 + * 正常使用只需#processDeleteEvent.flowCode=='leave1' + * 示例为了方便则使用startsWith匹配了全部示例key + * + * @param processDeleteEvent 参数 + */ + @EventListener(condition = "#processDeleteEvent.flowCode.startsWith('leave')") + public void processDeleteHandler(ProcessDeleteEvent processDeleteEvent) { + log.info("监听删除流程事件,当前任务执行了{}", processDeleteEvent.toString()); + TestLeave testLeave = baseMapper.selectById(Long.valueOf(processDeleteEvent.getBusinessId())); + if (ObjectUtil.isNull(testLeave)) { + return; + } + baseMapper.deleteById(testLeave.getId()); + } + } diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WfCategoryServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WfCategoryServiceImpl.java deleted file mode 100644 index e5628232b..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WfCategoryServiceImpl.java +++ /dev/null @@ -1,130 +0,0 @@ -package org.dromara.workflow.service.impl; - -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.core.toolkit.Wrappers; -import lombok.RequiredArgsConstructor; -import org.dromara.common.core.utils.MapstructUtils; -import org.dromara.common.core.utils.StringUtils; -import org.dromara.workflow.domain.WfCategory; -import org.dromara.workflow.domain.bo.WfCategoryBo; -import org.dromara.workflow.domain.vo.WfCategoryVo; -import org.dromara.workflow.mapper.WfCategoryMapper; -import org.dromara.workflow.service.IWfCategoryService; -import org.dromara.workflow.utils.QueryUtils; -import org.flowable.engine.RepositoryService; -import org.flowable.engine.repository.Deployment; -import org.flowable.engine.repository.Model; -import org.flowable.engine.repository.ProcessDefinition; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.util.Collection; -import java.util.List; - -/** - * 流程分类Service业务层处理 - * - * @author may - * @date 2023-06-28 - */ -@RequiredArgsConstructor -@Service -public class WfCategoryServiceImpl implements IWfCategoryService { - - private final WfCategoryMapper baseMapper; - @Autowired(required = false) - private RepositoryService repositoryService; - - /** - * 查询流程分类 - */ - @Override - public WfCategoryVo queryById(Long id) { - return baseMapper.selectVoById(id); - } - - - /** - * 查询流程分类列表 - */ - @Override - public List queryList(WfCategoryBo bo) { - LambdaQueryWrapper lqw = buildQueryWrapper(bo); - return baseMapper.selectVoList(lqw); - } - - private LambdaQueryWrapper buildQueryWrapper(WfCategoryBo bo) { - LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); - lqw.like(StringUtils.isNotBlank(bo.getCategoryName()), WfCategory::getCategoryName, bo.getCategoryName()); - lqw.eq(StringUtils.isNotBlank(bo.getCategoryCode()), WfCategory::getCategoryCode, bo.getCategoryCode()); - return lqw; - } - - /** - * 新增流程分类 - */ - @Override - public Boolean insertByBo(WfCategoryBo bo) { - WfCategory add = MapstructUtils.convert(bo, WfCategory.class); - validEntityBeforeSave(add); - boolean flag = baseMapper.insert(add) > 0; - if (flag) { - bo.setId(add.getId()); - } - return flag; - } - - /** - * 修改流程分类 - */ - @Override - @Transactional(rollbackFor = Exception.class) - public Boolean updateByBo(WfCategoryBo bo) { - WfCategory update = MapstructUtils.convert(bo, WfCategory.class); - validEntityBeforeSave(update); - WfCategoryVo wfCategoryVo = baseMapper.selectVoById(bo.getId()); - List processDefinitionList = QueryUtils.definitionQuery().processDefinitionCategory(wfCategoryVo.getCategoryCode()).list(); - for (ProcessDefinition processDefinition : processDefinitionList) { - repositoryService.setProcessDefinitionCategory(processDefinition.getId(), bo.getCategoryCode()); - } - List deploymentList = QueryUtils.deploymentQuery().deploymentCategory(wfCategoryVo.getCategoryCode()).list(); - for (Deployment deployment : deploymentList) { - repositoryService.setDeploymentCategory(deployment.getId(), bo.getCategoryCode()); - } - List modelList = QueryUtils.modelQuery().modelCategory(wfCategoryVo.getCategoryCode()).list(); - for (Model model : modelList) { - model.setCategory(bo.getCategoryCode()); - repositoryService.saveModel(model); - } - return baseMapper.updateById(update) > 0; - } - - /** - * 保存前的数据校验 - */ - private void validEntityBeforeSave(WfCategory entity) { - //TODO 做一些数据校验,如唯一约束 - } - - /** - * 批量删除流程分类 - */ - @Override - public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) { - if (isValid) { - //TODO 做一些业务上的校验,判断是否需要校验 - } - return baseMapper.deleteByIds(ids) > 0; - } - - /** - * 按照类别编码查询 - * - * @param categoryCode 分类比吗 - */ - @Override - public WfCategory queryByCategoryCode(String categoryCode) { - return baseMapper.selectOne(new LambdaQueryWrapper().eq(WfCategory::getCategoryCode, categoryCode)); - } -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WfDefinitionConfigServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WfDefinitionConfigServiceImpl.java deleted file mode 100644 index b2ffb9ef9..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WfDefinitionConfigServiceImpl.java +++ /dev/null @@ -1,117 +0,0 @@ -package org.dromara.workflow.service.impl; - -import cn.hutool.core.collection.CollUtil; -import org.dromara.common.core.utils.MapstructUtils; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import lombok.RequiredArgsConstructor; -import org.dromara.workflow.domain.WfDefinitionConfig; -import org.dromara.workflow.domain.bo.WfDefinitionConfigBo; -import org.dromara.workflow.domain.vo.WfDefinitionConfigVo; -import org.dromara.workflow.service.IWfDefinitionConfigService; -import org.springframework.stereotype.Service; -import org.dromara.workflow.mapper.WfDefinitionConfigMapper; -import org.springframework.transaction.annotation.Transactional; - -import java.util.List; -import java.util.Collection; - -/** - * 流程定义配置Service业务层处理 - * - * @author may - * @date 2024-03-18 - */ -@RequiredArgsConstructor -@Service -public class WfDefinitionConfigServiceImpl implements IWfDefinitionConfigService { - - private final WfDefinitionConfigMapper baseMapper; - - /** - * 查询流程定义配置 - */ - @Override - public WfDefinitionConfigVo getByDefId(String definitionId) { - return baseMapper.selectVoOne(new LambdaQueryWrapper().eq(WfDefinitionConfig::getDefinitionId, definitionId)); - } - - /** - * 查询流程定义配置 - * - * @param tableName 表名 - * @return 结果 - */ - @Override - public WfDefinitionConfigVo getByTableNameLastVersion(String tableName) { - List wfDefinitionConfigVos = baseMapper.selectVoList( - new LambdaQueryWrapper().eq(WfDefinitionConfig::getTableName, tableName).orderByDesc(WfDefinitionConfig::getVersion)); - if (CollUtil.isNotEmpty(wfDefinitionConfigVos)) { - return wfDefinitionConfigVos.get(0); - } - return null; - } - - /** - * 查询流程定义配置 - * - * @param definitionId 流程定义id - * @param tableName 表名 - * @return 结果 - */ - @Override - public WfDefinitionConfigVo getByDefIdAndTableName(String definitionId, String tableName) { - return baseMapper.selectVoOne(new LambdaQueryWrapper() - .eq(WfDefinitionConfig::getDefinitionId, definitionId) - .eq(WfDefinitionConfig::getTableName, tableName)); - } - - /** - * 查询流程定义配置排除当前查询的流程定义 - * - * @param tableName 表名 - * @param definitionId 流程定义id - */ - @Override - public List getByTableNameNotDefId(String tableName, String definitionId) { - return baseMapper.selectVoList(new LambdaQueryWrapper() - .eq(WfDefinitionConfig::getTableName, tableName) - .ne(WfDefinitionConfig::getDefinitionId, definitionId)); - } - - /** - * 查询流程定义配置列表 - */ - @Override - public List queryList(List definitionIds) { - return baseMapper.selectVoList(new LambdaQueryWrapper().in(WfDefinitionConfig::getDefinitionId, definitionIds)); - } - - /** - * 新增流程定义配置 - */ - @Override - @Transactional(rollbackFor = Exception.class) - public Boolean saveOrUpdate(WfDefinitionConfigBo bo) { - WfDefinitionConfig add = MapstructUtils.convert(bo, WfDefinitionConfig.class); - baseMapper.delete(new LambdaQueryWrapper().eq(WfDefinitionConfig::getTableName, bo.getTableName())); - add.setTableName(add.getTableName().toLowerCase()); - boolean flag = baseMapper.insertOrUpdate(add); - if (flag) { - bo.setId(add.getId()); - } - return flag; - } - - /** - * 批量删除流程定义配置 - */ - @Override - public Boolean deleteByIds(Collection ids) { - return baseMapper.deleteByIds(ids) > 0; - } - - @Override - public Boolean deleteByDefIds(Collection ids) { - return baseMapper.delete(new LambdaQueryWrapper().in(WfDefinitionConfig::getDefinitionId, ids)) > 0; - } -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WfFormManageServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WfFormManageServiceImpl.java deleted file mode 100644 index 55e491178..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WfFormManageServiceImpl.java +++ /dev/null @@ -1,111 +0,0 @@ -package org.dromara.workflow.service.impl; - -import org.dromara.common.core.utils.MapstructUtils; -import org.dromara.common.core.utils.StringUtils; -import org.dromara.common.mybatis.core.page.TableDataInfo; -import org.dromara.common.mybatis.core.page.PageQuery; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.core.toolkit.Wrappers; -import lombok.RequiredArgsConstructor; -import org.dromara.workflow.common.enums.FormTypeEnum; -import org.springframework.stereotype.Service; -import org.dromara.workflow.domain.bo.WfFormManageBo; -import org.dromara.workflow.domain.vo.WfFormManageVo; -import org.dromara.workflow.domain.WfFormManage; -import org.dromara.workflow.mapper.WfFormManageMapper; -import org.dromara.workflow.service.IWfFormManageService; - -import java.util.List; -import java.util.Collection; - -/** - * 表单管理Service业务层处理 - * - * @author may - * @date 2024-03-29 - */ -@RequiredArgsConstructor -@Service -public class WfFormManageServiceImpl implements IWfFormManageService { - - private final WfFormManageMapper baseMapper; - - /** - * 查询表单管理 - */ - @Override - public WfFormManageVo queryById(Long id) { - return baseMapper.selectVoById(id); - } - - @Override - public List queryByIds(List ids) { - return baseMapper.selectVoByIds(ids); - } - - /** - * 查询表单管理列表 - */ - @Override - public TableDataInfo queryPageList(WfFormManageBo bo, PageQuery pageQuery) { - LambdaQueryWrapper lqw = buildQueryWrapper(bo); - Page result = baseMapper.selectVoPage(pageQuery.build(), lqw); - return TableDataInfo.build(result); - } - - @Override - public List selectList() { - List wfFormManageVos = baseMapper.selectVoList(new LambdaQueryWrapper().orderByDesc(WfFormManage::getUpdateTime)); - for (WfFormManageVo wfFormManageVo : wfFormManageVos) { - wfFormManageVo.setFormTypeName(FormTypeEnum.findByType(wfFormManageVo.getFormType())); - } - return wfFormManageVos; - } - - /** - * 查询表单管理列表 - */ - @Override - public List queryList(WfFormManageBo bo) { - LambdaQueryWrapper lqw = buildQueryWrapper(bo); - return baseMapper.selectVoList(lqw); - } - - private LambdaQueryWrapper buildQueryWrapper(WfFormManageBo bo) { - LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); - lqw.like(StringUtils.isNotBlank(bo.getFormName()), WfFormManage::getFormName, bo.getFormName()); - lqw.eq(StringUtils.isNotBlank(bo.getFormType()), WfFormManage::getFormType, bo.getFormType()); - return lqw; - } - - /** - * 新增表单管理 - */ - @Override - public Boolean insertByBo(WfFormManageBo bo) { - WfFormManage add = MapstructUtils.convert(bo, WfFormManage.class); - boolean flag = baseMapper.insert(add) > 0; - if (flag) { - bo.setId(add.getId()); - } - return flag; - } - - /** - * 修改表单管理 - */ - @Override - public Boolean updateByBo(WfFormManageBo bo) { - WfFormManage update = MapstructUtils.convert(bo, WfFormManage.class); - return baseMapper.updateById(update) > 0; - } - - /** - * 批量删除表单管理 - */ - @Override - public Boolean deleteByIds(Collection ids) { - return baseMapper.deleteByIds(ids) > 0; - } -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WfNodeConfigServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WfNodeConfigServiceImpl.java deleted file mode 100644 index 2f71482fa..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WfNodeConfigServiceImpl.java +++ /dev/null @@ -1,75 +0,0 @@ -package org.dromara.workflow.service.impl; - -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.util.ObjectUtil; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import lombok.RequiredArgsConstructor; -import org.dromara.common.core.utils.StreamUtils; -import org.dromara.workflow.domain.vo.WfFormManageVo; -import org.dromara.workflow.service.IWfFormManageService; -import org.springframework.stereotype.Service; -import org.dromara.workflow.domain.vo.WfNodeConfigVo; -import org.dromara.workflow.domain.WfNodeConfig; -import org.dromara.workflow.mapper.WfNodeConfigMapper; -import org.dromara.workflow.service.IWfNodeConfigService; - -import java.util.Collection; -import java.util.List; - -/** - * 节点配置Service业务层处理 - * - * @author may - * @date 2024-03-30 - */ -@RequiredArgsConstructor -@Service -public class WfNodeConfigServiceImpl implements IWfNodeConfigService { - - private final WfNodeConfigMapper baseMapper; - private final IWfFormManageService wfFormManageService; - - /** - * 查询节点配置 - */ - @Override - public WfNodeConfigVo queryById(Long id) { - return baseMapper.selectVoById(id); - } - - /** - * 保存节点配置 - */ - @Override - public Boolean saveOrUpdate(List list) { - return baseMapper.insertOrUpdateBatch(list); - } - - /** - * 批量删除节点配置 - */ - @Override - public Boolean deleteByIds(Collection ids) { - return baseMapper.deleteByIds(ids) > 0; - } - - - - @Override - public Boolean deleteByDefIds(Collection ids) { - return baseMapper.delete(new LambdaQueryWrapper().in(WfNodeConfig::getDefinitionId, ids)) > 0; - } - - @Override - public List selectByDefIds(Collection ids) { - List wfNodeConfigVos = baseMapper.selectVoList(new LambdaQueryWrapper().in(WfNodeConfig::getDefinitionId, ids)); - if (CollUtil.isNotEmpty(wfNodeConfigVos)) { - List formIds = StreamUtils.toList(wfNodeConfigVos, WfNodeConfigVo::getFormId); - List wfFormManageVos = wfFormManageService.queryByIds(formIds); - for (WfNodeConfigVo wfNodeConfigVo : wfNodeConfigVos) { - wfFormManageVos.stream().filter(e -> ObjectUtil.equals(e.getId(), wfNodeConfigVo.getFormId())).findFirst().ifPresent(wfNodeConfigVo::setWfFormManageVo); - } - } - return wfNodeConfigVos; - } -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WfTaskBackNodeServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WfTaskBackNodeServiceImpl.java deleted file mode 100644 index 6c255d3b0..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WfTaskBackNodeServiceImpl.java +++ /dev/null @@ -1,144 +0,0 @@ -package org.dromara.workflow.service.impl; - -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.util.ObjectUtil; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.dromara.common.core.exception.ServiceException; -import org.dromara.common.core.utils.StreamUtils; -import org.dromara.common.core.utils.StringUtils; -import org.dromara.common.satoken.utils.LoginHelper; -import org.dromara.workflow.domain.WfTaskBackNode; -import org.dromara.workflow.domain.vo.MultiInstanceVo; -import org.dromara.workflow.mapper.WfTaskBackNodeMapper; -import org.dromara.workflow.service.IWfTaskBackNodeService; -import org.dromara.workflow.utils.WorkflowUtils; -import org.flowable.task.api.Task; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.util.ArrayList; -import java.util.List; - -import static org.dromara.workflow.common.constant.FlowConstant.MULTI_INSTANCE; -import static org.dromara.workflow.common.constant.FlowConstant.USER_TASK; - - -/** - * 节点驳回记录Service业务层处理 - * - * @author may - * @date 2024-03-13 - */ -@Slf4j -@RequiredArgsConstructor -@Service -public class WfTaskBackNodeServiceImpl implements IWfTaskBackNodeService { - - private final WfTaskBackNodeMapper wfTaskBackNodeMapper; - - @Override - @Transactional(rollbackFor = Exception.class) - public void recordExecuteNode(Task task) { - List list = getListByInstanceId(task.getProcessInstanceId()); - WfTaskBackNode wfTaskBackNode = new WfTaskBackNode(); - wfTaskBackNode.setNodeId(task.getTaskDefinitionKey()); - wfTaskBackNode.setNodeName(task.getName()); - wfTaskBackNode.setInstanceId(task.getProcessInstanceId()); - wfTaskBackNode.setAssignee(String.valueOf(LoginHelper.getUserId())); - MultiInstanceVo multiInstance = WorkflowUtils.isMultiInstance(task.getProcessDefinitionId(), task.getTaskDefinitionKey()); - if (ObjectUtil.isNotEmpty(multiInstance)) { - wfTaskBackNode.setTaskType(MULTI_INSTANCE); - } else { - wfTaskBackNode.setTaskType(USER_TASK); - } - if (CollUtil.isEmpty(list)) { - wfTaskBackNode.setOrderNo(0); - wfTaskBackNodeMapper.insert(wfTaskBackNode); - } else { - WfTaskBackNode taskNode = StreamUtils.findFirst(list, e -> e.getNodeId().equals(wfTaskBackNode.getNodeId()) && e.getOrderNo() == 0); - if (ObjectUtil.isEmpty(taskNode)) { - wfTaskBackNode.setOrderNo(list.get(0).getOrderNo() + 1); - WfTaskBackNode node = getListByInstanceIdAndNodeId(wfTaskBackNode.getInstanceId(), wfTaskBackNode.getNodeId()); - if (ObjectUtil.isNotEmpty(node)) { - node.setAssignee(node.getAssignee() + StringUtils.SEPARATOR + LoginHelper.getUserId()); - wfTaskBackNodeMapper.updateById(node); - } else { - wfTaskBackNodeMapper.insert(wfTaskBackNode); - } - } - } - } - - @Override - public List getListByInstanceId(String processInstanceId) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(WfTaskBackNode::getInstanceId, processInstanceId); - wrapper.orderByDesc(WfTaskBackNode::getOrderNo); - return wfTaskBackNodeMapper.selectList(wrapper); - } - - @Override - public WfTaskBackNode getListByInstanceIdAndNodeId(String processInstanceId, String nodeId) { - LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); - queryWrapper.eq(WfTaskBackNode::getInstanceId, processInstanceId); - queryWrapper.eq(WfTaskBackNode::getNodeId, nodeId); - return wfTaskBackNodeMapper.selectOne(queryWrapper); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public boolean deleteBackTaskNode(String processInstanceId, String targetActivityId) { - try { - LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); - queryWrapper.eq(WfTaskBackNode::getInstanceId, processInstanceId); - queryWrapper.eq(WfTaskBackNode::getNodeId, targetActivityId); - WfTaskBackNode actTaskNode = wfTaskBackNodeMapper.selectOne(queryWrapper); - if (ObjectUtil.isNotNull(actTaskNode)) { - Integer orderNo = actTaskNode.getOrderNo(); - List taskNodeList = getListByInstanceId(processInstanceId); - List ids = new ArrayList<>(); - if (CollUtil.isNotEmpty(taskNodeList)) { - for (WfTaskBackNode taskNode : taskNodeList) { - if (taskNode.getOrderNo() >= orderNo) { - ids.add(taskNode.getId()); - } - } - } - if (CollUtil.isNotEmpty(ids)) { - wfTaskBackNodeMapper.deleteByIds(ids); - } - } - return true; - } catch (Exception e) { - log.error(e.getMessage(), e); - throw new ServiceException("删除失败"); - } - } - - @Override - @Transactional(rollbackFor = Exception.class) - public boolean deleteByInstanceId(String processInstanceId) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(WfTaskBackNode::getInstanceId, processInstanceId); - List list = wfTaskBackNodeMapper.selectList(wrapper); - int delete = wfTaskBackNodeMapper.delete(wrapper); - if (list.size() != delete) { - throw new ServiceException("删除失败"); - } - return true; - } - - @Override - public boolean deleteByInstanceIds(List processInstanceIds) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.in(WfTaskBackNode::getInstanceId, processInstanceIds); - List list = wfTaskBackNodeMapper.selectList(wrapper); - int delete = wfTaskBackNodeMapper.delete(wrapper); - if (list.size() != delete) { - throw new ServiceException("删除失败"); - } - return true; - } -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WorkflowServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WorkflowServiceImpl.java index b03658444..6be20c4cf 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WorkflowServiceImpl.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WorkflowServiceImpl.java @@ -1,14 +1,19 @@ package org.dromara.workflow.service.impl; -import cn.hutool.core.util.StrUtil; +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.util.ObjectUtil; import lombok.RequiredArgsConstructor; +import org.dromara.common.core.domain.dto.CompleteTaskDTO; +import org.dromara.common.core.domain.dto.StartProcessDTO; import org.dromara.common.core.service.WorkflowService; -import org.dromara.workflow.domain.ActHiProcinst; -import org.dromara.workflow.service.IActHiProcinstService; -import org.dromara.workflow.service.IActProcessInstanceService; -import org.dromara.workflow.utils.WorkflowUtils; -import org.flowable.engine.TaskService; -import org.springframework.beans.factory.annotation.Autowired; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.warm.flow.orm.entity.FlowInstance; +import org.dromara.workflow.common.ConditionalOnEnable; +import org.dromara.workflow.domain.bo.CompleteTaskBo; +import org.dromara.workflow.domain.bo.StartProcessBo; +import org.dromara.workflow.service.IFlwDefinitionService; +import org.dromara.workflow.service.IFlwInstanceService; +import org.dromara.workflow.service.IFlwTaskService; import org.springframework.stereotype.Service; import java.util.List; @@ -19,23 +24,24 @@ import java.util.Map; * * @author may */ +@ConditionalOnEnable @RequiredArgsConstructor @Service public class WorkflowServiceImpl implements WorkflowService { - @Autowired(required = false) - private TaskService taskService; - private final IActProcessInstanceService actProcessInstanceService; - private final IActHiProcinstService actHiProcinstService; + private final IFlwInstanceService flwInstanceService; + private final IFlwDefinitionService flwDefinitionService; + private final IFlwTaskService flwTaskService; + /** - * 运行中的实例 删除程实例,删除历史记录,删除业务与流程关联信息 + * 删除流程实例 * - * @param businessKeys 业务id + * @param businessIds 业务id * @return 结果 */ @Override - public boolean deleteRunAndHisInstance(List businessKeys) { - return actProcessInstanceService.deleteRunAndHisInstance(businessKeys); + public boolean deleteInstance(List businessIds) { + return flwInstanceService.deleteByBusinessIds(businessIds); } /** @@ -44,78 +50,72 @@ public class WorkflowServiceImpl implements WorkflowService { * @param taskId 任务id */ @Override - public String getBusinessStatusByTaskId(String taskId) { - return WorkflowUtils.getBusinessStatusByTaskId(taskId); + public String getBusinessStatusByTaskId(Long taskId) { + FlowInstance flowInstance = flwInstanceService.selectByTaskId(taskId); + return ObjectUtil.isNotNull(flowInstance) ? flowInstance.getFlowStatus() : StringUtils.EMPTY; } /** * 获取当前流程状态 * - * @param businessKey 业务id + * @param businessId 业务id */ @Override - public String getBusinessStatus(String businessKey) { - return WorkflowUtils.getBusinessStatus(businessKey); + public String getBusinessStatus(String businessId) { + FlowInstance flowInstance = flwInstanceService.selectInstByBusinessId(businessId); + return ObjectUtil.isNotNull(flowInstance) ? flowInstance.getFlowStatus() : StringUtils.EMPTY; } /** - * 设置流程变量(全局变量) + * 设置流程变量 * - * @param taskId 任务id - * @param variableName 变量名称 - * @param value 变量值 + * @param instanceId 流程实例id + * @param variables 流程变量 */ @Override - public void setVariable(String taskId, String variableName, Object value) { - taskService.setVariable(taskId, variableName, value); - } - - /** - * 设置流程变量(全局变量) - * - * @param taskId 任务id - * @param variables 流程变量 - */ - @Override - public void setVariables(String taskId, Map variables) { - taskService.setVariables(taskId, variables); - } - - /** - * 设置流程变量(本地变量,非全局变量) - * - * @param taskId 任务id - * @param variableName 变量名称 - * @param value 变量值 - */ - @Override - public void setVariableLocal(String taskId, String variableName, Object value) { - taskService.setVariableLocal(taskId, variableName, value); - } - - /** - * 设置流程变量(本地变量,非全局变量) - * - * @param taskId 任务id - * @param variables 流程变量 - */ - @Override - public void setVariablesLocal(String taskId, Map variables) { - taskService.setVariablesLocal(taskId, variables); + public void setVariable(Long instanceId, Map variables) { + flwInstanceService.setVariable(instanceId, variables); } /** * 按照业务id查询流程实例id * - * @param businessKey 业务id + * @param businessId 业务id * @return 结果 */ @Override - public String getInstanceIdByBusinessKey(String businessKey) { - ActHiProcinst actHiProcinst = actHiProcinstService.selectByBusinessKey(businessKey); - if (actHiProcinst == null) { - return StrUtil.EMPTY; - } - return actHiProcinst.getId(); + public Long getInstanceIdByBusinessId(String businessId) { + FlowInstance flowInstance = flwInstanceService.selectInstByBusinessId(businessId); + return ObjectUtil.isNotNull(flowInstance) ? flowInstance.getId() : null; + } + + /** + * 新增租户流程定义 + * + * @param tenantId 租户id + */ + @Override + public void syncDef(String tenantId) { + flwDefinitionService.syncDef(tenantId); + } + + /** + * 启动流程 + * + * @param startProcess 参数 + */ + @Override + public Map startWorkFlow(StartProcessDTO startProcess) { + return flwTaskService.startWorkFlow(BeanUtil.toBean(startProcess, StartProcessBo.class)); + } + + /** + * 办理任务 + * + * @param completeTask 参数 + */ + @Override + public boolean completeTask(CompleteTaskDTO completeTask) { + return flwTaskService.completeTask(BeanUtil.toBean(completeTask, CompleteTaskBo.class)); } } diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/utils/ModelUtils.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/utils/ModelUtils.java deleted file mode 100644 index 7c5377ed7..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/utils/ModelUtils.java +++ /dev/null @@ -1,289 +0,0 @@ -package org.dromara.workflow.utils; - -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.collection.CollectionUtil; -import cn.hutool.core.io.IoUtil; -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.core.util.StrUtil; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; -import org.dromara.common.core.utils.SpringUtils; -import org.dromara.common.core.utils.StreamUtils; -import org.dromara.common.core.utils.StringUtils; -import org.dromara.common.json.utils.JsonUtils; -import org.dromara.workflow.domain.vo.MultiInstanceVo; -import org.flowable.bpmn.converter.BpmnXMLConverter; -import org.flowable.bpmn.model.*; -import org.flowable.bpmn.model.Process; -import org.flowable.editor.language.json.converter.BpmnJsonConverter; -import org.flowable.engine.ProcessEngine; - -import javax.xml.stream.XMLInputFactory; -import javax.xml.stream.XMLStreamException; -import javax.xml.stream.XMLStreamReader; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.rmi.ServerException; -import java.util.*; -import java.util.stream.Collectors; - -/** - * 模型工具 - * - * @author may - */ -@NoArgsConstructor(access = AccessLevel.PRIVATE) -public class ModelUtils { - - private static final ProcessEngine PROCESS_ENGINE = SpringUtils.getBean(ProcessEngine.class); - - public static BpmnModel xmlToBpmnModel(String xml) throws IOException { - if (xml == null) { - throw new ServerException("xml不能为空"); - } - try { - InputStream inputStream = new ByteArrayInputStream(StrUtil.utf8Bytes(xml)); - XMLInputFactory factory = XMLInputFactory.newInstance(); - XMLStreamReader reader = factory.createXMLStreamReader(inputStream); - return new BpmnXMLConverter().convertToBpmnModel(reader); - } catch (XMLStreamException e) { - throw new ServerException(e.getMessage()); - } - } - - /** - * bpmnModel转为xml - * - * @param jsonBytes json - */ - public static byte[] bpmnJsonToXmlBytes(byte[] jsonBytes) throws IOException { - if (jsonBytes == null) { - return new byte[0]; - } - // 1. json字节码转成 BpmnModel 对象 - ObjectMapper objectMapper = JsonUtils.getObjectMapper(); - JsonNode jsonNode = objectMapper.readTree(jsonBytes); - BpmnModel bpmnModel = new BpmnJsonConverter().convertToBpmnModel(jsonNode); - - if (bpmnModel.getProcesses().isEmpty()) { - return new byte[0]; - } - // 2.将bpmnModel转为xml - return new BpmnXMLConverter().convertToXML(bpmnModel); - } - - /** - * xml转为bpmnModel - * - * @param xmlBytes xml - */ - public static BpmnModel xmlToBpmnModel(byte[] xmlBytes) throws XMLStreamException { - ByteArrayInputStream byteArrayInputStream = IoUtil.toStream(xmlBytes); - XMLInputFactory xif = XMLInputFactory.newInstance(); - XMLStreamReader xtr = xif.createXMLStreamReader(byteArrayInputStream); - return new BpmnXMLConverter().convertToBpmnModel(xtr); - } - - /** - * 校验模型 - * - * @param bpmnModel bpmn模型 - */ - public static void checkBpmnModel(BpmnModel bpmnModel) throws ServerException { - Collection flowElements = bpmnModel.getMainProcess().getFlowElements(); - - checkBpmnNode(flowElements, false); - - List subProcessList = flowElements.stream().filter(SubProcess.class::isInstance).map(SubProcess.class::cast).collect(Collectors.toList()); - if (!CollUtil.isEmpty(subProcessList)) { - for (SubProcess subProcess : subProcessList) { - Collection subProcessFlowElements = subProcess.getFlowElements(); - checkBpmnNode(subProcessFlowElements, true); - } - } - List multiInstanceVoList = new ArrayList<>(); - for (FlowElement flowElement : flowElements) { - if (flowElement instanceof UserTask && ObjectUtil.isNotEmpty(((UserTask) flowElement).getLoopCharacteristics()) && StringUtils.isNotBlank(((UserTask) flowElement).getLoopCharacteristics().getInputDataItem())) { - MultiInstanceVo multiInstanceVo = new MultiInstanceVo(); - multiInstanceVo.setAssigneeList(((UserTask) flowElement).getLoopCharacteristics().getInputDataItem()); - multiInstanceVoList.add(multiInstanceVo); - } - } - - if (CollectionUtil.isNotEmpty(multiInstanceVoList) && multiInstanceVoList.size() > 1) { - Map> assigneeListGroup = StreamUtils.groupByKey(multiInstanceVoList, MultiInstanceVo::getAssigneeList); - for (Map.Entry> entry : assigneeListGroup.entrySet()) { - List value = entry.getValue(); - if (CollectionUtil.isNotEmpty(value) && value.size() > 1) { - String key = entry.getKey(); - throw new ServerException("会签人员集合【" + key + "】重复,请重新设置集合KEY"); - } - } - } - } - - /** - * 校验bpmn节点是否合法 - * - * @param flowElements 节点集合 - * @param subtask 是否子流程 - */ - private static void checkBpmnNode(Collection flowElements, boolean subtask) throws ServerException { - - if (CollUtil.isEmpty(flowElements)) { - throw new ServerException(subtask ? "子流程必须存在节点" : "必须存在节点!"); - } - - List startEventList = flowElements.stream().filter(StartEvent.class::isInstance).map(StartEvent.class::cast).collect(Collectors.toList()); - if (CollUtil.isEmpty(startEventList)) { - throw new ServerException(subtask ? "子流程必须存在开始节点" : "必须存在开始节点!"); - } - - if (startEventList.size() > 1) { - throw new ServerException(subtask ? "子流程只能存在一个开始节点" : "只能存在一个开始节点!"); - } - - StartEvent startEvent = startEventList.get(0); - List outgoingFlows = startEvent.getOutgoingFlows(); - if (CollUtil.isEmpty(outgoingFlows)) { - throw new ServerException(subtask ? "子流程流程节点为空,请至少设计一条主线流程!" : "流程节点为空,请至少设计一条主线流程!"); - } - - FlowElement targetFlowElement = outgoingFlows.get(0).getTargetFlowElement(); - if (!(targetFlowElement instanceof UserTask) && !subtask) { - throw new ServerException("开始节点后第一个节点必须是用户任务!"); - } - //开始节点后第一个节点申请人节点 - if ((targetFlowElement instanceof UserTask) && !subtask) { - UserTask userTask = (UserTask) targetFlowElement; - if (StringUtils.isBlank(userTask.getFormKey())) { - throw new ServerException("申请人节点必须选择表单!"); - } - } - List endEventList = flowElements.stream().filter(EndEvent.class::isInstance).map(EndEvent.class::cast).collect(Collectors.toList()); - if (CollUtil.isEmpty(endEventList)) { - throw new ServerException(subtask ? "子流程必须存在结束节点!" : "必须存在结束节点!"); - } - } - - /** - * 获取流程全部用户节点 - * - * @param processDefinitionId 流程定义id - */ - public static List getUserTaskFlowElements(String processDefinitionId) { - BpmnModel bpmnModel = PROCESS_ENGINE.getRepositoryService().getBpmnModel(processDefinitionId); - List list = new ArrayList<>(); - List processes = bpmnModel.getProcesses(); - Collection flowElements = processes.get(0).getFlowElements(); - buildUserTaskFlowElements(flowElements, list); - return list; - } - - /** - * 递归获取所有节点 - * - * @param flowElements 节点信息 - * @param list 集合 - */ - private static void buildUserTaskFlowElements(Collection flowElements, List list) { - for (FlowElement flowElement : flowElements) { - if (flowElement instanceof SubProcess) { - Collection subFlowElements = ((SubProcess) flowElement).getFlowElements(); - buildUserTaskFlowElements(subFlowElements, list); - } else if (flowElement instanceof UserTask) { - list.add((UserTask) flowElement); - } - } - } - - /** - * 获取流程全部节点 - * - * @param processDefinitionId 流程定义id - */ - public static List getFlowElements(String processDefinitionId) { - BpmnModel bpmnModel = PROCESS_ENGINE.getRepositoryService().getBpmnModel(processDefinitionId); - List list = new ArrayList<>(); - List processes = bpmnModel.getProcesses(); - Collection flowElements = processes.get(0).getFlowElements(); - buildFlowElements(flowElements, list); - return list; - } - - /** - * 递归获取所有节点 - * - * @param flowElements 节点信息 - * @param list 集合 - */ - private static void buildFlowElements(Collection flowElements, List list) { - for (FlowElement flowElement : flowElements) { - list.add(flowElement); - if (flowElement instanceof SubProcess) { - Collection subFlowElements = ((SubProcess) flowElement).getFlowElements(); - buildFlowElements(subFlowElements, list); - } - } - } - - /** - * 获取全部扩展信息 - * - * @param processDefinitionId 流程定义id - */ - public static Map> getExtensionElements(String processDefinitionId) { - Map> map = new HashMap<>(); - List flowElements = getFlowElements(processDefinitionId); - for (FlowElement flowElement : flowElements) { - if (flowElement instanceof UserTask && CollUtil.isNotEmpty(flowElement.getExtensionElements())) { - map.putAll(flowElement.getExtensionElements()); - } - } - return map; - } - - /** - * 获取某个节点的扩展信息 - * - * @param processDefinitionId 流程定义id - * @param flowElementId 节点id - */ - public static Map> getExtensionElement(String processDefinitionId, String flowElementId) { - BpmnModel bpmnModel = PROCESS_ENGINE.getRepositoryService().getBpmnModel(processDefinitionId); - Process process = bpmnModel.getMainProcess(); - FlowElement flowElement = process.getFlowElement(flowElementId); - return flowElement.getExtensionElements(); - } - - /** - * 判断当前节点是否为用户任务 - * - * @param processDefinitionId 流程定义id - * @param taskDefinitionKey 流程定义id - */ - public static boolean isUserTask(String processDefinitionId, String taskDefinitionKey) { - BpmnModel bpmnModel = PROCESS_ENGINE.getRepositoryService().getBpmnModel(processDefinitionId); - FlowNode flowNode = (FlowNode) bpmnModel.getFlowElement(taskDefinitionKey); - return flowNode instanceof UserTask; - } - - /** - * 获取申请人节点 - * - * @param processDefinitionId 流程定义id - * @return 结果 - */ - public static UserTask getApplyUserTask(String processDefinitionId) { - BpmnModel bpmnModel = PROCESS_ENGINE.getRepositoryService().getBpmnModel(processDefinitionId); - Collection flowElements = bpmnModel.getMainProcess().getFlowElements(); - List startEventList = flowElements.stream().filter(StartEvent.class::isInstance).map(StartEvent.class::cast).collect(Collectors.toList()); - StartEvent startEvent = startEventList.get(0); - List outgoingFlows = startEvent.getOutgoingFlows(); - FlowElement targetFlowElement = outgoingFlows.get(0).getTargetFlowElement(); - return (UserTask) targetFlowElement; - } -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/utils/QueryUtils.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/utils/QueryUtils.java deleted file mode 100644 index df928dc72..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/utils/QueryUtils.java +++ /dev/null @@ -1,169 +0,0 @@ -package org.dromara.workflow.utils; - -import cn.hutool.core.bean.BeanUtil; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; -import org.dromara.common.core.utils.SpringUtils; -import org.dromara.common.tenant.helper.TenantHelper; -import org.dromara.workflow.domain.vo.TaskVo; -import org.flowable.engine.ProcessEngine; -import org.flowable.engine.history.HistoricActivityInstanceQuery; -import org.flowable.engine.history.HistoricProcessInstanceQuery; -import org.flowable.engine.repository.DeploymentQuery; -import org.flowable.engine.repository.ModelQuery; -import org.flowable.engine.repository.ProcessDefinitionQuery; -import org.flowable.engine.runtime.ProcessInstance; -import org.flowable.engine.runtime.ProcessInstanceQuery; -import org.flowable.task.api.Task; -import org.flowable.task.api.TaskQuery; -import org.flowable.task.api.history.HistoricTaskInstanceQuery; - -import java.util.Collection; -import java.util.List; -import java.util.Set; - -/** - * 查询工具 - * - * @author Lion Li - */ -@NoArgsConstructor(access = AccessLevel.PRIVATE) -public class QueryUtils { - - private static final ProcessEngine PROCESS_ENGINE = SpringUtils.getBean(ProcessEngine.class); - - public static ModelQuery modelQuery() { - ModelQuery query = PROCESS_ENGINE.getRepositoryService().createModelQuery(); - if (TenantHelper.isEnable()) { - query.modelTenantId(TenantHelper.getTenantId()); - } - return query; - } - - public static ProcessDefinitionQuery definitionQuery() { - ProcessDefinitionQuery query = PROCESS_ENGINE.getRepositoryService().createProcessDefinitionQuery(); - if (TenantHelper.isEnable()) { - query.processDefinitionTenantId(TenantHelper.getTenantId()); - } - return query; - } - - public static DeploymentQuery deploymentQuery() { - DeploymentQuery query = PROCESS_ENGINE.getRepositoryService().createDeploymentQuery(); - if (TenantHelper.isEnable()) { - query.deploymentTenantId(TenantHelper.getTenantId()); - } - return query; - } - - public static DeploymentQuery deploymentQuery(String deploymentId) { - return deploymentQuery().deploymentId(deploymentId); - } - - public static DeploymentQuery deploymentQuery(List deploymentIds) { - return deploymentQuery().deploymentIds(deploymentIds); - } - - public static HistoricTaskInstanceQuery hisTaskInstanceQuery() { - HistoricTaskInstanceQuery query = PROCESS_ENGINE.getHistoryService().createHistoricTaskInstanceQuery(); - if (TenantHelper.isEnable()) { - query.taskTenantId(TenantHelper.getTenantId()); - } - return query; - } - - public static HistoricTaskInstanceQuery hisTaskInstanceQuery(String processInstanceId) { - return hisTaskInstanceQuery().processInstanceId(processInstanceId); - } - - public static HistoricTaskInstanceQuery hisTaskBusinessKeyQuery(String businessKey) { - return hisTaskInstanceQuery().processInstanceBusinessKey(businessKey); - } - - public static ProcessInstanceQuery instanceQuery() { - ProcessInstanceQuery query = PROCESS_ENGINE.getRuntimeService().createProcessInstanceQuery(); - if (TenantHelper.isEnable()) { - query.processInstanceTenantId(TenantHelper.getTenantId()); - } - return query; - } - - public static ProcessInstanceQuery instanceQuery(String processInstanceId) { - return instanceQuery().processInstanceId(processInstanceId); - } - - public static ProcessInstanceQuery businessKeyQuery(String businessKey) { - return instanceQuery().processInstanceBusinessKey(businessKey); - } - - public static ProcessInstanceQuery instanceQuery(Set processInstanceIds) { - return instanceQuery().processInstanceIds(processInstanceIds); - } - - public static HistoricProcessInstanceQuery hisInstanceQuery() { - HistoricProcessInstanceQuery query = PROCESS_ENGINE.getHistoryService().createHistoricProcessInstanceQuery(); - if (TenantHelper.isEnable()) { - query.processInstanceTenantId(TenantHelper.getTenantId()); - } - return query; - } - - public static HistoricProcessInstanceQuery hisInstanceQuery(String processInstanceId) { - return hisInstanceQuery().processInstanceId(processInstanceId); - } - - public static HistoricProcessInstanceQuery hisBusinessKeyQuery(String businessKey) { - return hisInstanceQuery().processInstanceBusinessKey(businessKey); - } - - public static HistoricProcessInstanceQuery hisInstanceQuery(Set processInstanceIds) { - return hisInstanceQuery().processInstanceIds(processInstanceIds); - } - - public static HistoricActivityInstanceQuery hisActivityInstanceQuery() { - HistoricActivityInstanceQuery query = PROCESS_ENGINE.getHistoryService().createHistoricActivityInstanceQuery(); - if (TenantHelper.isEnable()) { - query.activityTenantId(TenantHelper.getTenantId()); - } - return query; - } - - public static HistoricActivityInstanceQuery hisActivityInstanceQuery(String processInstanceId) { - return hisActivityInstanceQuery().processInstanceId(processInstanceId); - } - - public static TaskQuery taskQuery() { - TaskQuery query = PROCESS_ENGINE.getTaskService().createTaskQuery(); - if (TenantHelper.isEnable()) { - query.taskTenantId(TenantHelper.getTenantId()); - } - return query; - } - - public static TaskQuery taskQuery(String processInstanceId) { - return taskQuery().processInstanceId(processInstanceId); - } - - public static TaskQuery taskQuery(Collection processInstanceIds) { - return taskQuery().processInstanceIdIn(processInstanceIds); - } - - /** - * 按照任务id查询当前任务 - * - * @param taskId 任务id - */ - public static TaskVo getTask(String taskId) { - Task task = PROCESS_ENGINE.getTaskService().createTaskQuery().taskId(taskId).singleResult(); - if (task == null) { - return null; - } - ProcessInstance processInstance = QueryUtils.instanceQuery(task.getProcessInstanceId()).singleResult(); - TaskVo taskVo = BeanUtil.toBean(task, TaskVo.class); - taskVo.setBusinessKey(processInstance.getBusinessKey()); - taskVo.setMultiInstance(WorkflowUtils.isMultiInstance(task.getProcessDefinitionId(), task.getTaskDefinitionKey()) != null); - String businessStatus = WorkflowUtils.getBusinessStatus(taskVo.getBusinessKey()); - taskVo.setBusinessStatus(businessStatus); - return taskVo; - } -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/utils/WorkflowUtils.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/utils/WorkflowUtils.java index d7c44723b..e48ffc820 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/utils/WorkflowUtils.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/utils/WorkflowUtils.java @@ -2,43 +2,42 @@ package org.dromara.workflow.utils; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; -import cn.hutool.core.util.StrUtil; -import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import lombok.AccessLevel; import lombok.NoArgsConstructor; -import org.dromara.common.core.domain.dto.RoleDTO; import org.dromara.common.core.domain.dto.UserDTO; -import org.dromara.common.core.service.UserService; import org.dromara.common.core.utils.SpringUtils; import org.dromara.common.core.utils.StreamUtils; import org.dromara.common.core.utils.StringUtils; import org.dromara.common.mail.utils.MailUtils; -import org.dromara.common.satoken.utils.LoginHelper; -import org.dromara.common.tenant.helper.TenantHelper; -import org.dromara.common.websocket.dto.WebSocketMessageDto; -import org.dromara.common.websocket.utils.WebSocketUtils; -import org.dromara.workflow.common.constant.FlowConstant; +import org.dromara.common.sse.dto.SseMessageDto; +import org.dromara.common.sse.utils.SseMessageUtils; +import org.dromara.warm.flow.core.constant.ExceptionCons; +import org.dromara.warm.flow.core.dto.FlowParams; +import org.dromara.warm.flow.core.entity.Node; +import org.dromara.warm.flow.core.entity.Task; +import org.dromara.warm.flow.core.entity.User; +import org.dromara.warm.flow.core.enums.NodeType; +import org.dromara.warm.flow.core.enums.SkipType; +import org.dromara.warm.flow.core.service.NodeService; +import org.dromara.warm.flow.core.service.TaskService; +import org.dromara.warm.flow.core.service.UserService; +import org.dromara.warm.flow.core.utils.AssertUtil; +import org.dromara.warm.flow.orm.entity.FlowNode; +import org.dromara.warm.flow.orm.entity.FlowTask; +import org.dromara.warm.flow.orm.entity.FlowUser; +import org.dromara.warm.flow.orm.mapper.FlowNodeMapper; +import org.dromara.warm.flow.orm.mapper.FlowTaskMapper; import org.dromara.workflow.common.enums.MessageTypeEnum; -import org.dromara.workflow.common.enums.TaskStatusEnum; -import org.dromara.workflow.domain.ActHiTaskinst; -import org.dromara.workflow.domain.vo.MultiInstanceVo; -import org.dromara.workflow.domain.vo.ParticipantVo; -import org.dromara.workflow.flowable.cmd.UpdateHiTaskInstCmd; -import org.dromara.workflow.mapper.ActHiTaskinstMapper; -import org.flowable.bpmn.model.BpmnModel; -import org.flowable.bpmn.model.FlowNode; -import org.flowable.common.engine.api.delegate.Expression; -import org.flowable.engine.ProcessEngine; -import org.flowable.engine.history.HistoricProcessInstance; -import org.flowable.engine.impl.bpmn.behavior.ParallelMultiInstanceBehavior; -import org.flowable.engine.impl.bpmn.behavior.SequentialMultiInstanceBehavior; -import org.flowable.identitylink.api.history.HistoricIdentityLink; -import org.flowable.task.api.Task; -import org.flowable.task.api.TaskQuery; -import org.flowable.task.api.history.HistoricTaskInstance; -import org.flowable.task.service.impl.persistence.entity.TaskEntity; +import org.dromara.workflow.service.IFlwTaskAssigneeService; +import org.dromara.workflow.service.IFlwTaskService; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; -import java.util.*; /** * 工作流工具 @@ -48,220 +47,84 @@ import java.util.*; @NoArgsConstructor(access = AccessLevel.PRIVATE) public class WorkflowUtils { - private static final ProcessEngine PROCESS_ENGINE = SpringUtils.getBean(ProcessEngine.class); - private static final ActHiTaskinstMapper ACT_HI_TASKINST_MAPPER = SpringUtils.getBean(ActHiTaskinstMapper.class); + private static final IFlwTaskAssigneeService TASK_ASSIGNEE_SERVICE = SpringUtils.getBean(IFlwTaskAssigneeService.class); + private static final IFlwTaskService FLW_TASK_SERVICE = SpringUtils.getBean(IFlwTaskService.class); + private static final FlowNodeMapper FLOW_NODE_MAPPER = SpringUtils.getBean(FlowNodeMapper.class); + private static final FlowTaskMapper FLOW_TASK_MAPPER = SpringUtils.getBean(FlowTaskMapper.class); + private static final UserService USER_SERVICE = SpringUtils.getBean(UserService.class); + private static final TaskService TASK_SERVICE = SpringUtils.getBean(TaskService.class); + private static final NodeService NODE_SERVICE = SpringUtils.getBean(NodeService.class); /** - * 创建一个新任务 - * - * @param currentTask 参数 + * 获取工作流用户service */ - public static TaskEntity createNewTask(Task currentTask) { - TaskEntity task = null; - if (ObjectUtil.isNotEmpty(currentTask)) { - task = (TaskEntity) PROCESS_ENGINE.getTaskService().newTask(); - task.setCategory(currentTask.getCategory()); - task.setDescription(currentTask.getDescription()); - task.setAssignee(currentTask.getAssignee()); - task.setName(currentTask.getName()); - task.setProcessDefinitionId(currentTask.getProcessDefinitionId()); - task.setProcessInstanceId(currentTask.getProcessInstanceId()); - task.setTaskDefinitionKey(currentTask.getTaskDefinitionKey()); - task.setPriority(currentTask.getPriority()); - task.setCreateTime(new Date()); - task.setTenantId(TenantHelper.getTenantId()); - PROCESS_ENGINE.getTaskService().saveTask(task); - } - if (ObjectUtil.isNotNull(task)) { - UpdateHiTaskInstCmd updateHiTaskInstCmd = new UpdateHiTaskInstCmd(Collections.singletonList(task.getId()), task.getProcessDefinitionId(), task.getProcessInstanceId()); - PROCESS_ENGINE.getManagementService().executeCommand(updateHiTaskInstCmd); - } - return task; + public static UserService getFlowUserService() { + return USER_SERVICE; } /** - * 抄送任务 + * 构建工作流用户 * - * @param parentTaskList 父级任务 - * @param userIds 人员id + * @param userList 办理用户 + * @param taskId 任务ID + * @return 用户 */ - public static void createCopyTask(List parentTaskList, List userIds) { - List list = new ArrayList<>(); - String tenantId = TenantHelper.getTenantId(); - for (Task parentTask : parentTaskList) { - for (Long userId : userIds) { - TaskEntity newTask = (TaskEntity) PROCESS_ENGINE.getTaskService().newTask(); - newTask.setParentTaskId(parentTask.getId()); - newTask.setAssignee(userId.toString()); - newTask.setName("【抄送】-" + parentTask.getName()); - newTask.setProcessDefinitionId(parentTask.getProcessDefinitionId()); - newTask.setProcessInstanceId(parentTask.getProcessInstanceId()); - newTask.setTaskDefinitionKey(parentTask.getTaskDefinitionKey()); - newTask.setTenantId(tenantId); - list.add(newTask); + public static Set buildUser(List userList, Long taskId) { + if (CollUtil.isEmpty(userList)) { + return Set.of(); + } + Set list = new HashSet<>(); + Set processedBySet = new HashSet<>(); + for (User user : userList) { + // 根据 processedBy 前缀判断处理人类型,分别获取用户列表 + List users = TASK_ASSIGNEE_SERVICE.fetchUsersByStorageId(user.getProcessedBy()); + // 转换为 FlowUser 并添加到结果集合 + if (CollUtil.isNotEmpty(users)) { + users.forEach(dto -> { + String processedBy = String.valueOf(dto.getUserId()); + if (!processedBySet.contains(processedBy)) { + FlowUser flowUser = new FlowUser(); + flowUser.setType(user.getType()); + flowUser.setProcessedBy(processedBy); + flowUser.setAssociated(taskId); + list.add(flowUser); + processedBySet.add(processedBy); + } + }); } } - PROCESS_ENGINE.getTaskService().bulkSaveTasks(list); - if (CollUtil.isNotEmpty(list) && CollUtil.isNotEmpty(parentTaskList)) { - String processInstanceId = parentTaskList.get(0).getProcessInstanceId(); - String processDefinitionId = parentTaskList.get(0).getProcessDefinitionId(); - List taskIds = StreamUtils.toList(list, Task::getId); - ActHiTaskinst actHiTaskinst = new ActHiTaskinst(); - actHiTaskinst.setProcDefId(processDefinitionId); - actHiTaskinst.setProcInstId(processInstanceId); - actHiTaskinst.setScopeType(TaskStatusEnum.COPY.getStatus()); - actHiTaskinst.setTenantId(tenantId); - LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); - updateWrapper.in(ActHiTaskinst::getId, taskIds); - ACT_HI_TASKINST_MAPPER.update(actHiTaskinst, updateWrapper); - for (Task task : list) { - PROCESS_ENGINE.getTaskService().addComment(task.getId(), task.getProcessInstanceId(), TaskStatusEnum.COPY.getStatus(), StrUtil.EMPTY); - } - } - } - - /** - * 获取当前任务参与者 - * - * @param taskId 任务id - */ - public static ParticipantVo getCurrentTaskParticipant(String taskId, UserService userService) { - ParticipantVo participantVo = new ParticipantVo(); - List linksForTask = PROCESS_ENGINE.getHistoryService().getHistoricIdentityLinksForTask(taskId); - Task task = QueryUtils.taskQuery().taskId(taskId).singleResult(); - if (task != null && CollUtil.isNotEmpty(linksForTask)) { - List groupList = StreamUtils.filter(linksForTask, e -> StringUtils.isNotBlank(e.getGroupId())); - if (CollUtil.isNotEmpty(groupList)) { - List groupIds = StreamUtils.toList(groupList, e -> Long.valueOf(e.getGroupId())); - List userIds = userService.selectUserIdsByRoleIds(groupIds); - if (CollUtil.isNotEmpty(userIds)) { - participantVo.setGroupIds(groupIds); - List userList = userService.selectListByIds(userIds); - if (CollUtil.isNotEmpty(userList)) { - List userIdList = StreamUtils.toList(userList, UserDTO::getUserId); - List nickNames = StreamUtils.toList(userList, UserDTO::getNickName); - participantVo.setCandidate(userIdList); - participantVo.setCandidateName(nickNames); - participantVo.setClaim(!StringUtils.isBlank(task.getAssignee())); - } - } - } else { - List candidateList = StreamUtils.filter(linksForTask, e -> FlowConstant.CANDIDATE.equals(e.getType())); - List userIdList = new ArrayList<>(); - for (HistoricIdentityLink historicIdentityLink : linksForTask) { - try { - userIdList.add(Long.valueOf(historicIdentityLink.getUserId())); - } catch (NumberFormatException ignored) { - - } - } - List userList = userService.selectListByIds(userIdList); - if (CollUtil.isNotEmpty(userList)) { - List userIds = StreamUtils.toList(userList, UserDTO::getUserId); - List nickNames = StreamUtils.toList(userList, UserDTO::getNickName); - participantVo.setCandidate(userIds); - participantVo.setCandidateName(nickNames); - // 判断当前任务是否具有多个办理人 - if (CollUtil.isNotEmpty(candidateList) && candidateList.size() > 1) { - // 如果 assignee 存在,则设置当前任务已经被认领 - participantVo.setClaim(StringUtils.isNotBlank(task.getAssignee())); - } - } - } - } - return participantVo; - } - - /** - * 判断当前节点是否为会签节点 - * - * @param processDefinitionId 流程定义id - * @param taskDefinitionKey 流程定义id - */ - public static MultiInstanceVo isMultiInstance(String processDefinitionId, String taskDefinitionKey) { - BpmnModel bpmnModel = PROCESS_ENGINE.getRepositoryService().getBpmnModel(processDefinitionId); - FlowNode flowNode = (FlowNode) bpmnModel.getFlowElement(taskDefinitionKey); - MultiInstanceVo multiInstanceVo = new MultiInstanceVo(); - //判断是否为并行会签节点 - if (flowNode.getBehavior() instanceof ParallelMultiInstanceBehavior behavior && behavior.getCollectionExpression() != null) { - Expression collectionExpression = behavior.getCollectionExpression(); - String assigneeList = collectionExpression.getExpressionText(); - String assignee = behavior.getCollectionElementVariable(); - multiInstanceVo.setType(behavior); - multiInstanceVo.setAssignee(assignee); - multiInstanceVo.setAssigneeList(assigneeList); - return multiInstanceVo; - //判断是否为串行会签节点 - } else if (flowNode.getBehavior() instanceof SequentialMultiInstanceBehavior behavior && behavior.getCollectionExpression() != null) { - Expression collectionExpression = behavior.getCollectionExpression(); - String assigneeList = collectionExpression.getExpressionText(); - String assignee = behavior.getCollectionElementVariable(); - multiInstanceVo.setType(behavior); - multiInstanceVo.setAssignee(assignee); - multiInstanceVo.setAssigneeList(assigneeList); - return multiInstanceVo; - } - return null; - } - - /** - * 获取当前流程状态 - * - * @param taskId 任务id - */ - public static String getBusinessStatusByTaskId(String taskId) { - HistoricTaskInstance historicTaskInstance = QueryUtils.hisTaskInstanceQuery().taskId(taskId).singleResult(); - HistoricProcessInstance historicProcessInstance = QueryUtils.hisInstanceQuery(historicTaskInstance.getProcessInstanceId()).singleResult(); - return historicProcessInstance.getBusinessStatus(); - } - - /** - * 获取当前流程状态 - * - * @param businessKey 业务id - */ - public static String getBusinessStatus(String businessKey) { - HistoricProcessInstance historicProcessInstance = QueryUtils.hisBusinessKeyQuery(businessKey).singleResult(); - return historicProcessInstance.getBusinessStatus(); + return list; } /** * 发送消息 * - * @param list 任务 - * @param name 流程名称 + * @param flowName 流程定义名称 * @param messageType 消息类型 * @param message 消息内容,为空则发送默认配置的消息内容 */ - public static void sendMessage(List list, String name, List messageType, String message, UserService userService) { - Set userIds = new HashSet<>(); + public static void sendMessage(String flowName, Long instId, List messageType, String message) { + List userList = new ArrayList<>(); + List list = FLW_TASK_SERVICE.selectByInstId(instId); if (StringUtils.isBlank(message)) { - message = "有新的【" + name + "】单据已经提交至您的待办,请您及时处理。"; + message = "有新的【" + flowName + "】单据已经提交至您,请您及时处理。"; } - for (Task t : list) { - ParticipantVo taskParticipant = WorkflowUtils.getCurrentTaskParticipant(t.getId(), userService); - if (CollUtil.isNotEmpty(taskParticipant.getGroupIds())) { - List userIdList = userService.selectUserIdsByRoleIds(taskParticipant.getGroupIds()); - if (CollUtil.isNotEmpty(userIdList)) { - userIds.addAll(userIdList); - } - } - List candidate = taskParticipant.getCandidate(); - if (CollUtil.isNotEmpty(candidate)) { - userIds.addAll(candidate); + for (Task task : list) { + List users = FLW_TASK_SERVICE.currentTaskAllUser(task.getId()); + if (CollUtil.isNotEmpty(users)) { + userList.addAll(users); } } - if (CollUtil.isNotEmpty(userIds)) { - List userList = userService.selectListByIds(new ArrayList<>(userIds)); + if (CollUtil.isNotEmpty(userList)) { for (String code : messageType) { MessageTypeEnum messageTypeEnum = MessageTypeEnum.getByCode(code); if (ObjectUtil.isNotEmpty(messageTypeEnum)) { switch (messageTypeEnum) { case SYSTEM_MESSAGE: - WebSocketMessageDto dto = new WebSocketMessageDto(); - dto.setSessionKeys(new ArrayList<>(userIds)); + SseMessageDto dto = new SseMessageDto(); + dto.setUserIds(StreamUtils.toList(userList, UserDTO::getUserId).stream().distinct().collect(Collectors.toList())); dto.setMessage(message); - WebSocketUtils.publishMessage(dto); + SseMessageUtils.publishMessage(dto); break; case EMAIL_MESSAGE: MailUtils.sendText(StreamUtils.join(userList, UserDTO::getEmail), "单据审批提醒", message); @@ -269,6 +132,8 @@ public class WorkflowUtils { case SMS_MESSAGE: //todo 短信发送 break; + default: + throw new IllegalStateException("Unexpected value: " + messageTypeEnum); } } } @@ -276,20 +141,66 @@ public class WorkflowUtils { } /** - * 根据任务id查询 当前用户的任务,检查 当前人员 是否是该 taskId 的办理人 + * 驳回 * - * @param taskId 任务id - * @return 结果 + * @param message 审批意见 + * @param instanceId 流程实例id + * @param targetNodeCode 目标节点 + * @param flowStatus 流程状态 + * @param flowHisStatus 节点操作状态 */ - public static Task getTaskByCurrentUser(String taskId) { - TaskQuery taskQuery = QueryUtils.taskQuery(); - taskQuery.taskId(taskId).taskCandidateOrAssigned(String.valueOf(LoginHelper.getUserId())); - - List roles = LoginHelper.getLoginUser().getRoles(); - if (CollUtil.isNotEmpty(roles)) { - List groupIds = StreamUtils.toList(roles, e -> String.valueOf(e.getRoleId())); - taskQuery.taskCandidateGroupIn(groupIds); + public static void backTask(String message, Long instanceId, String targetNodeCode, String flowStatus, String flowHisStatus) { + List list = FLW_TASK_SERVICE.selectByInstId(instanceId); + if (CollUtil.isNotEmpty(list)) { + List tasks = StreamUtils.filter(list, e -> e.getNodeCode().equals(targetNodeCode)); + if (list.size() == tasks.size()) { + return; + } } - return taskQuery.singleResult(); + for (FlowTask task : list) { + List userList = FLW_TASK_SERVICE.currentTaskAllUser(task.getId()); + FlowParams flowParams = FlowParams.build(); + flowParams.nodeCode(targetNodeCode); + flowParams.message(message); + flowParams.skipType(SkipType.PASS.getKey()); + flowParams.flowStatus(flowStatus).hisStatus(flowHisStatus); + flowParams.ignore(true); + //解决会签没权限问题 + if (CollUtil.isNotEmpty(userList)) { + flowParams.handler(userList.get(0).getUserId().toString()); + } + TASK_SERVICE.skip(task.getId(), flowParams); + } + //解决会签多人审批问题 + backTask(message, instanceId, targetNodeCode, flowStatus, flowHisStatus); + } + + /** + * 申请人节点编码 + * + * @param definitionId 流程定义id + * @return 申请人节点编码 + */ + public static String applyNodeCode(Long definitionId) { + //获取已发布的流程节点 + List flowNodes = FLOW_NODE_MAPPER.selectList(new LambdaQueryWrapper().eq(FlowNode::getDefinitionId, definitionId)); + AssertUtil.isTrue(CollUtil.isEmpty(flowNodes), ExceptionCons.NOT_PUBLISH_NODE); + Node startNode = flowNodes.stream().filter(t -> NodeType.isStart(t.getNodeType())).findFirst().orElse(null); + AssertUtil.isNull(startNode, ExceptionCons.LOST_START_NODE); + Node nextNode = NODE_SERVICE.getNextNode(definitionId, startNode.getNodeCode(), null, SkipType.PASS.getKey()); + return nextNode.getNodeCode(); + } + + /** + * 删除运行中的任务 + * + * @param taskIds 任务id + */ + public static void deleteRunTask(List taskIds) { + if (CollUtil.isEmpty(taskIds)) { + return; + } + USER_SERVICE.deleteByTaskIds(taskIds); + FLOW_TASK_MAPPER.deleteByIds(taskIds); } } diff --git a/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/ActHiProcinstMapper.xml b/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/ActHiProcinstMapper.xml deleted file mode 100644 index dd0578576..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/ActHiProcinstMapper.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/ActHiTaskinstMapper.xml b/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/ActHiTaskinstMapper.xml deleted file mode 100644 index 7e73b603f..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/ActHiTaskinstMapper.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/ActTaskMapper.xml b/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/ActTaskMapper.xml deleted file mode 100644 index 36419009a..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/ActTaskMapper.xml +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/FlwCategoryMapper.xml b/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/FlwCategoryMapper.xml new file mode 100644 index 000000000..e9918f1f2 --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/FlwCategoryMapper.xml @@ -0,0 +1,11 @@ + + + + + + + diff --git a/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/FlwInstanceMapper.xml b/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/FlwInstanceMapper.xml new file mode 100644 index 000000000..30e2267dc --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/FlwInstanceMapper.xml @@ -0,0 +1,36 @@ + + + + + + + + + diff --git a/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/FlwTaskMapper.xml b/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/FlwTaskMapper.xml new file mode 100644 index 000000000..73e4ec789 --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/FlwTaskMapper.xml @@ -0,0 +1,115 @@ + + + + + + + + + + + + + + diff --git a/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/WfCategoryMapper.xml b/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/WfCategoryMapper.xml deleted file mode 100644 index 4375cb2dd..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/WfCategoryMapper.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/WfDefinitionConfigMapper.xml b/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/WfDefinitionConfigMapper.xml deleted file mode 100644 index 8d579f705..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/WfDefinitionConfigMapper.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/WfFormManageMapper.xml b/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/WfFormManageMapper.xml deleted file mode 100644 index 59221f82d..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/WfFormManageMapper.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/WfNodeConfigMapper.xml b/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/WfNodeConfigMapper.xml deleted file mode 100644 index b65194f8b..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/WfNodeConfigMapper.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/WfTaskBackNodeMapper.xml b/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/WfTaskBackNodeMapper.xml deleted file mode 100644 index 4a9179b62..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/WfTaskBackNodeMapper.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/script/bpmn/模型.zip b/script/bpmn/模型.zip deleted file mode 100644 index 6f30952ab..000000000 Binary files a/script/bpmn/模型.zip and /dev/null differ diff --git a/script/docker/database.yml b/script/docker/database.yml index 0368fd27d..6034b39c4 100644 --- a/script/docker/database.yml +++ b/script/docker/database.yml @@ -1,5 +1,3 @@ -version: '3' - services: # 此镜像仅用于测试 正式环境需自行安装数据库 # SID: XE user: system password: oracle diff --git a/script/docker/docker-compose.yml b/script/docker/docker-compose.yml index 0839e74e1..8b6befcad 100644 --- a/script/docker/docker-compose.yml +++ b/script/docker/docker-compose.yml @@ -1,5 +1,3 @@ -version: '3' - services: mysql: image: mysql:8.0.33 @@ -100,7 +98,7 @@ services: network_mode: "host" ruoyi-server1: - image: ruoyi/ruoyi-server:5.2.3 + image: ruoyi/ruoyi-server:5.3.0-BETA container_name: ruoyi-server1 environment: # 时区上海 @@ -115,7 +113,7 @@ services: network_mode: "host" ruoyi-server2: - image: ruoyi/ruoyi-server:5.2.3 + image: ruoyi/ruoyi-server:5.3.0-BETA container_name: ruoyi-server2 environment: # 时区上海 @@ -130,7 +128,7 @@ services: network_mode: "host" ruoyi-monitor-admin: - image: ruoyi/ruoyi-monitor-admin:5.2.3 + image: ruoyi/ruoyi-monitor-admin:5.3.0-BETA container_name: ruoyi-monitor-admin environment: # 时区上海 @@ -142,7 +140,7 @@ services: network_mode: "host" ruoyi-snailjob-server: - image: ruoyi/ruoyi-snailjob-server:5.2.3 + image: ruoyi/ruoyi-snailjob-server:5.3.0-BETA container_name: ruoyi-snailjob-server environment: # 时区上海 diff --git a/script/docker/nginx/conf/nginx.conf b/script/docker/nginx/conf/nginx.conf index 3c79d97f6..3df4a722c 100644 --- a/script/docker/nginx/conf/nginx.conf +++ b/script/docker/nginx/conf/nginx.conf @@ -96,7 +96,7 @@ http { proxy_set_header X-Real-IP $remote_addr; proxy_set_header REMOTE-HOST $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_pass http://monitor-admin/admin/; + proxy_pass http://monitor-admin/; } location /snail-job/ { diff --git a/script/leave/leave1.json b/script/leave/leave1.json new file mode 100644 index 000000000..0cf67bc46 --- /dev/null +++ b/script/leave/leave1.json @@ -0,0 +1,75 @@ +{ + "flowCode" : "leave1", + "flowName" : "请假申请-普通", + "category" : "1", + "version" : "1", + "formCustom" : "N", + "formPath" : "/workflow/leaveEdit/index", + "nodeList" : [ { + "nodeType" : 0, + "nodeCode" : "d5ee3ddf-3968-4379-a86f-9ceabde5faac", + "nodeName" : "开始", + "nodeRatio" : 0.000, + "coordinate" : "200,200|200,200", + "skipAnyNode" : "N", + "formCustom" : "N", + "skipList" : [ { + "nowNodeCode" : "d5ee3ddf-3968-4379-a86f-9ceabde5faac", + "nextNodeCode" : "dd515cdd-59f6-446f-94ca-25ca062afb42", + "skipType" : "PASS", + "coordinate" : "220,200;310,200" + } ] + }, { + "nodeType" : 1, + "nodeCode" : "dd515cdd-59f6-446f-94ca-25ca062afb42", + "nodeName" : "申请人", + "nodeRatio" : 0.000, + "coordinate" : "360,200|360,200", + "skipAnyNode" : "N", + "formCustom" : "N", + "skipList" : [ { + "nowNodeCode" : "dd515cdd-59f6-446f-94ca-25ca062afb42", + "nextNodeCode" : "78fa8e5b-e809-44ed-978a-41092409ebcf", + "skipType" : "PASS", + "coordinate" : "410,200;490,200" + } ] + }, { + "nodeType" : 1, + "nodeCode" : "78fa8e5b-e809-44ed-978a-41092409ebcf", + "nodeName" : "组长", + "permissionFlag" : "role:1", + "nodeRatio" : 0.000, + "coordinate" : "540,200|540,200", + "skipAnyNode" : "N", + "formCustom" : "N", + "skipList" : [ { + "nowNodeCode" : "78fa8e5b-e809-44ed-978a-41092409ebcf", + "nextNodeCode" : "a8abf15f-b83e-428a-86cc-033555ea9bbe", + "skipType" : "PASS", + "coordinate" : "590,200;670,200" + } ] + }, { + "nodeType" : 1, + "nodeCode" : "a8abf15f-b83e-428a-86cc-033555ea9bbe", + "nodeName" : "部门主管", + "permissionFlag" : "role:3,role:4", + "nodeRatio" : 0.000, + "coordinate" : "720,200|720,200", + "skipAnyNode" : "N", + "formCustom" : "N", + "skipList" : [ { + "nowNodeCode" : "a8abf15f-b83e-428a-86cc-033555ea9bbe", + "nextNodeCode" : "8b82b7d7-8660-455e-b880-d6d22ea3eb6d", + "skipType" : "PASS", + "coordinate" : "770,200;880,200" + } ] + }, { + "nodeType" : 2, + "nodeCode" : "8b82b7d7-8660-455e-b880-d6d22ea3eb6d", + "nodeName" : "结束", + "nodeRatio" : 0.000, + "coordinate" : "900,200|900,200", + "skipAnyNode" : "N", + "formCustom" : "N" + } ] +} \ No newline at end of file diff --git a/script/leave/leave2.json b/script/leave/leave2.json new file mode 100644 index 000000000..9fce8ffd2 --- /dev/null +++ b/script/leave/leave2.json @@ -0,0 +1,111 @@ +{ + "flowCode" : "leave2", + "flowName" : "请假申请-排他网关", + "category" : "1", + "version" : "1", + "formCustom" : "N", + "formPath" : "/workflow/leaveEdit/index", + "nodeList" : [ { + "nodeType" : 0, + "nodeCode" : "cef3895c-f7d8-4598-8bf3-8ec2ef6ce84a", + "nodeName" : "开始", + "nodeRatio" : 0.000, + "coordinate" : "300,240|300,240", + "skipAnyNode" : "N", + "formCustom" : "N", + "skipList" : [ { + "nowNodeCode" : "cef3895c-f7d8-4598-8bf3-8ec2ef6ce84a", + "nextNodeCode" : "fdcae93b-b69c-498a-b231-09255e74bcbd", + "skipType" : "PASS", + "coordinate" : "320,240;390,240" + } ] + }, { + "nodeType" : 1, + "nodeCode" : "fdcae93b-b69c-498a-b231-09255e74bcbd", + "nodeName" : "申请人", + "nodeRatio" : 0.000, + "coordinate" : "440,240|440,240", + "skipAnyNode" : "N", + "formCustom" : "N", + "skipList" : [ { + "nowNodeCode" : "fdcae93b-b69c-498a-b231-09255e74bcbd", + "nextNodeCode" : "7b8c7ead-7dc8-4951-a7f3-f0c41995909e", + "skipType" : "PASS", + "coordinate" : "490,240;535,240" + } ] + }, { + "nodeType" : 3, + "nodeCode" : "7b8c7ead-7dc8-4951-a7f3-f0c41995909e", + "nodeRatio" : 0.000, + "coordinate" : "560,240", + "skipAnyNode" : "N", + "formCustom" : "N", + "skipList" : [ { + "nowNodeCode" : "7b8c7ead-7dc8-4951-a7f3-f0c41995909e", + "nextNodeCode" : "b3528155-dcb7-4445-bbdf-3d00e3499e86", + "skipType" : "PASS", + "skipCondition" : "le@@leaveDays|2", + "coordinate" : "560,265;560,320;670,320" + }, { + "nowNodeCode" : "7b8c7ead-7dc8-4951-a7f3-f0c41995909e", + "nextNodeCode" : "5ed2362b-fc0c-4d52-831f-95208b830605", + "skipName" : "大于两天", + "skipType" : "PASS", + "skipCondition" : "gt@@leaveDays|2", + "coordinate" : "560,215;560,160;670,160|560,187" + } ] + }, { + "nodeType" : 1, + "nodeCode" : "b3528155-dcb7-4445-bbdf-3d00e3499e86", + "nodeName" : "组长", + "permissionFlag" : "3,4", + "nodeRatio" : 0.000, + "coordinate" : "720,320|720,320", + "skipAnyNode" : "N", + "formCustom" : "N", + "skipList" : [ { + "nowNodeCode" : "b3528155-dcb7-4445-bbdf-3d00e3499e86", + "nextNodeCode" : "c9fa6d7d-2a74-4e78-b947-0cad8a6af869", + "skipType" : "PASS", + "coordinate" : "770,320;860,320;860,280" + } ] + }, { + "nodeType" : 1, + "nodeCode" : "c9fa6d7d-2a74-4e78-b947-0cad8a6af869", + "nodeName" : "总经理", + "permissionFlag" : "role:1", + "nodeRatio" : 0.000, + "coordinate" : "860,240|860,240", + "skipAnyNode" : "N", + "formCustom" : "N", + "skipList" : [ { + "nowNodeCode" : "c9fa6d7d-2a74-4e78-b947-0cad8a6af869", + "nextNodeCode" : "40aa65fd-0712-4d23-b6f7-d0432b920fd1", + "skipType" : "PASS", + "coordinate" : "910,240;980,240" + } ] + }, { + "nodeType" : 2, + "nodeCode" : "40aa65fd-0712-4d23-b6f7-d0432b920fd1", + "nodeName" : "结束", + "nodeRatio" : 0.000, + "coordinate" : "1000,240|1000,240", + "skipAnyNode" : "N", + "formCustom" : "N" + }, { + "nodeType" : 1, + "nodeCode" : "5ed2362b-fc0c-4d52-831f-95208b830605", + "nodeName" : "部门领导", + "permissionFlag" : "role:1", + "nodeRatio" : 0.000, + "coordinate" : "720,160|720,160", + "skipAnyNode" : "N", + "formCustom" : "N", + "skipList" : [ { + "nowNodeCode" : "5ed2362b-fc0c-4d52-831f-95208b830605", + "nextNodeCode" : "c9fa6d7d-2a74-4e78-b947-0cad8a6af869", + "skipType" : "PASS", + "coordinate" : "770,160;860,160;860,200" + } ] + } ] +} diff --git a/script/leave/leave3.json b/script/leave/leave3.json new file mode 100644 index 000000000..08daae4bf --- /dev/null +++ b/script/leave/leave3.json @@ -0,0 +1,121 @@ +{ + "flowCode" : "leave3", + "flowName" : "请假申请-并行网关", + "category" : "1", + "version" : "1", + "formCustom" : "N", + "formPath" : "/workflow/leaveEdit/index", + "nodeList" : [ { + "nodeType" : 0, + "nodeCode" : "a80ecf9f-f465-4ae5-a429-e30ec5d0f957", + "nodeName" : "开始", + "nodeRatio" : 0.000, + "coordinate" : "380,220|380,220", + "skipAnyNode" : "N", + "formCustom" : "N", + "skipList" : [ { + "nowNodeCode" : "a80ecf9f-f465-4ae5-a429-e30ec5d0f957", + "nextNodeCode" : "b7bbb571-06de-455c-8083-f83c07bf0b99", + "skipType" : "PASS", + "coordinate" : "400,220;470,220" + } ] + }, { + "nodeType" : 1, + "nodeCode" : "b7bbb571-06de-455c-8083-f83c07bf0b99", + "nodeName" : "申请人", + "nodeRatio" : 0.000, + "coordinate" : "520,220|520,220", + "skipAnyNode" : "N", + "formCustom" : "N", + "skipList" : [ { + "nowNodeCode" : "b7bbb571-06de-455c-8083-f83c07bf0b99", + "nextNodeCode" : "84d7ed24-bb44-4ba1-bf1f-e6f5092d3f0a", + "skipType" : "PASS", + "coordinate" : "570,220;655,220" + } ] + }, { + "nodeType" : 4, + "nodeCode" : "84d7ed24-bb44-4ba1-bf1f-e6f5092d3f0a", + "nodeRatio" : 0.000, + "coordinate" : "680,220", + "skipAnyNode" : "N", + "formCustom" : "N", + "skipList" : [ { + "nowNodeCode" : "84d7ed24-bb44-4ba1-bf1f-e6f5092d3f0a", + "nextNodeCode" : "4b7743cd-940c-431b-926f-e7b614fbf1fe", + "skipType" : "PASS", + "coordinate" : "680,195;680,140;750,140" + }, { + "nowNodeCode" : "84d7ed24-bb44-4ba1-bf1f-e6f5092d3f0a", + "nextNodeCode" : "762cb975-37d8-4276-b6db-79a4c3606394", + "skipType" : "PASS", + "coordinate" : "680,245;680,300;750,300" + } ] + }, { + "nodeType" : 1, + "nodeCode" : "4b7743cd-940c-431b-926f-e7b614fbf1fe", + "nodeName" : "市场部", + "permissionFlag" : "role:1", + "nodeRatio" : 0.000, + "coordinate" : "800,140|800,140", + "skipAnyNode" : "N", + "formCustom" : "N", + "skipList" : [ { + "nowNodeCode" : "4b7743cd-940c-431b-926f-e7b614fbf1fe", + "nextNodeCode" : "b66b6563-f9fe-41cc-a782-f7837bb6f3d2", + "skipType" : "PASS", + "coordinate" : "850,140;920,140;920,195" + } ] + }, { + "nodeType" : 4, + "nodeCode" : "b66b6563-f9fe-41cc-a782-f7837bb6f3d2", + "nodeRatio" : 0.000, + "coordinate" : "920,220", + "skipAnyNode" : "N", + "formCustom" : "N", + "skipList" : [ { + "nowNodeCode" : "b66b6563-f9fe-41cc-a782-f7837bb6f3d2", + "nextNodeCode" : "23e7429e-2b47-4431-b93e-40db7c431ce6", + "skipType" : "PASS", + "coordinate" : "945,220;975,220;975,220;960,220;960,220;990,220" + } ] + }, { + "nodeType" : 1, + "nodeCode" : "23e7429e-2b47-4431-b93e-40db7c431ce6", + "nodeName" : "CEO", + "permissionFlag" : "1", + "nodeRatio" : 0.000, + "coordinate" : "1040,220|1040,220", + "skipAnyNode" : "N", + "formCustom" : "N", + "skipList" : [ { + "nowNodeCode" : "23e7429e-2b47-4431-b93e-40db7c431ce6", + "nextNodeCode" : "f5ace37f-5a5e-4e64-a6f6-913ab9a71cd1", + "skipType" : "PASS", + "coordinate" : "1090,220;1140,220" + } ] + }, { + "nodeType" : 2, + "nodeCode" : "f5ace37f-5a5e-4e64-a6f6-913ab9a71cd1", + "nodeName" : "结束", + "nodeRatio" : 0.000, + "coordinate" : "1160,220|1160,220", + "skipAnyNode" : "N", + "formCustom" : "N" + }, { + "nodeType" : 1, + "nodeCode" : "762cb975-37d8-4276-b6db-79a4c3606394", + "nodeName" : "综合部", + "permissionFlag" : "role:3,role:4", + "nodeRatio" : 0.000, + "coordinate" : "800,300|800,300", + "skipAnyNode" : "N", + "formCustom" : "N", + "skipList" : [ { + "nowNodeCode" : "762cb975-37d8-4276-b6db-79a4c3606394", + "nextNodeCode" : "b66b6563-f9fe-41cc-a782-f7837bb6f3d2", + "skipType" : "PASS", + "coordinate" : "850,300;920,300;920,245" + } ] + } ] +} \ No newline at end of file diff --git a/script/leave/leave4.json b/script/leave/leave4.json new file mode 100644 index 000000000..f8f440812 --- /dev/null +++ b/script/leave/leave4.json @@ -0,0 +1,90 @@ +{ + "flowCode" : "leave4", + "flowName" : "请假申请-会签", + "category" : "1", + "version" : "1", + "formCustom" : "N", + "formPath" : "/workflow/leaveEdit/index", + "nodeList" : [ { + "nodeType" : 0, + "nodeCode" : "9ce8bf00-f25b-4fc6-91b8-827082fc4876", + "nodeName" : "开始", + "nodeRatio" : 0.000, + "coordinate" : "320,240|320,240", + "skipAnyNode" : "N", + "formCustom" : "N", + "skipList" : [ { + "nowNodeCode" : "9ce8bf00-f25b-4fc6-91b8-827082fc4876", + "nextNodeCode" : "e90b98ef-35b4-410c-a663-bae8b7624b9f", + "skipType" : "PASS", + "coordinate" : "340,240;410,240" + } ] + }, { + "nodeType" : 1, + "nodeCode" : "e90b98ef-35b4-410c-a663-bae8b7624b9f", + "nodeName" : "申请人", + "nodeRatio" : 0.000, + "coordinate" : "460,240|460,240", + "skipAnyNode" : "N", + "formCustom" : "N", + "skipList" : [ { + "nowNodeCode" : "e90b98ef-35b4-410c-a663-bae8b7624b9f", + "nextNodeCode" : "768b5b1a-6726-4d67-8853-4cc70d5b1045", + "skipType" : "PASS", + "coordinate" : "510,240;590,240" + } ] + }, { + "nodeType" : 1, + "nodeCode" : "768b5b1a-6726-4d67-8853-4cc70d5b1045", + "nodeName" : "百分之60通过", + "permissionFlag" : "${userList}", + "nodeRatio" : 60.000, + "coordinate" : "640,240|640,240", + "skipAnyNode" : "N", + "formCustom" : "N", + "skipList" : [ { + "nowNodeCode" : "768b5b1a-6726-4d67-8853-4cc70d5b1045", + "nextNodeCode" : "2f9f2e21-9bcf-42a3-a07c-13037aad22d1", + "skipType" : "PASS", + "coordinate" : "690,240;770,240" + } ] + }, { + "nodeType" : 1, + "nodeCode" : "2f9f2e21-9bcf-42a3-a07c-13037aad22d1", + "nodeName" : "全部审批通过", + "permissionFlag" : "role:1,role:3", + "nodeRatio" : 100.000, + "coordinate" : "820,240|820,240", + "skipAnyNode" : "N", + "formCustom" : "N", + "skipList" : [ { + "nowNodeCode" : "2f9f2e21-9bcf-42a3-a07c-13037aad22d1", + "nextNodeCode" : "27461e01-3d9f-4530-8fe3-bd5ec7f9571f", + "skipType" : "PASS", + "coordinate" : "870,240;950,240" + } ] + }, { + "nodeType" : 1, + "nodeCode" : "27461e01-3d9f-4530-8fe3-bd5ec7f9571f", + "nodeName" : "CEO", + "permissionFlag" : "1", + "nodeRatio" : 0.000, + "coordinate" : "1000,240|1000,240", + "skipAnyNode" : "N", + "formCustom" : "N", + "skipList" : [ { + "nowNodeCode" : "27461e01-3d9f-4530-8fe3-bd5ec7f9571f", + "nextNodeCode" : "b62b88c3-8d8d-4969-911e-2aaea219e7fc", + "skipType" : "PASS", + "coordinate" : "1050,240;1080,240;1080,240;1070,240;1070,240;1100,240" + } ] + }, { + "nodeType" : 2, + "nodeCode" : "b62b88c3-8d8d-4969-911e-2aaea219e7fc", + "nodeName" : "结束", + "nodeRatio" : 0.000, + "coordinate" : "1120,240|1120,240", + "skipAnyNode" : "N", + "formCustom" : "N" + } ] +} \ No newline at end of file diff --git a/script/leave/leave5.json b/script/leave/leave5.json new file mode 100644 index 000000000..dc99494a5 --- /dev/null +++ b/script/leave/leave5.json @@ -0,0 +1,121 @@ +{ + "flowCode" : "leave5", + "flowName" : "请假申请-并行会签网关", + "category" : "1", + "version" : "1", + "formCustom" : "N", + "formPath" : "/workflow/leaveEdit/index", + "nodeList" : [ { + "nodeType" : 0, + "nodeCode" : "ebebaf26-9cb6-497e-8119-4c9fed4c597c", + "nodeName" : "开始", + "nodeRatio" : 0.000, + "coordinate" : "300,220|300,220", + "skipAnyNode" : "N", + "formCustom" : "N", + "skipList" : [ { + "nowNodeCode" : "ebebaf26-9cb6-497e-8119-4c9fed4c597c", + "nextNodeCode" : "e1b04e96-dc81-4858-a309-2fe945d2f374", + "skipType" : "PASS", + "coordinate" : "320,220;350,220;350,220;340,220;340,220;370,220" + } ] + }, { + "nodeType" : 1, + "nodeCode" : "e1b04e96-dc81-4858-a309-2fe945d2f374", + "nodeName" : "申请人", + "nodeRatio" : 0.000, + "coordinate" : "420,220|420,220", + "skipAnyNode" : "N", + "formCustom" : "N", + "skipList" : [ { + "nowNodeCode" : "e1b04e96-dc81-4858-a309-2fe945d2f374", + "nextNodeCode" : "3e743f4f-51ca-41d4-8e94-21f5dd9b59c9", + "skipType" : "PASS", + "coordinate" : "470,220;535,220" + } ] + }, { + "nodeType" : 4, + "nodeCode" : "3e743f4f-51ca-41d4-8e94-21f5dd9b59c9", + "nodeRatio" : 0.000, + "coordinate" : "560,220", + "skipAnyNode" : "N", + "formCustom" : "N", + "skipList" : [ { + "nowNodeCode" : "3e743f4f-51ca-41d4-8e94-21f5dd9b59c9", + "nextNodeCode" : "c80f273e-1f17-4bd8-9ad1-04a4a94ea862", + "skipType" : "PASS", + "coordinate" : "560,245;560,320;650,320" + }, { + "nowNodeCode" : "3e743f4f-51ca-41d4-8e94-21f5dd9b59c9", + "nextNodeCode" : "1e3e8d3b-18ae-4d6c-a814-ce0d724adfa4", + "skipType" : "PASS", + "coordinate" : "560,195;560,120;650,120" + } ] + }, { + "nodeType" : 1, + "nodeCode" : "c80f273e-1f17-4bd8-9ad1-04a4a94ea862", + "nodeName" : "会签", + "permissionFlag" : "role:1,role:3", + "nodeRatio" : 100.000, + "coordinate" : "700,320|700,320", + "skipAnyNode" : "N", + "formCustom" : "N", + "skipList" : [ { + "nowNodeCode" : "c80f273e-1f17-4bd8-9ad1-04a4a94ea862", + "nextNodeCode" : "1a20169e-3d82-4926-a151-e2daad28de1b", + "skipType" : "PASS", + "coordinate" : "750,320;860,320;860,245" + } ] + }, { + "nodeType" : 4, + "nodeCode" : "1a20169e-3d82-4926-a151-e2daad28de1b", + "nodeRatio" : 0.000, + "coordinate" : "860,220", + "skipAnyNode" : "N", + "formCustom" : "N", + "skipList" : [ { + "nowNodeCode" : "1a20169e-3d82-4926-a151-e2daad28de1b", + "nextNodeCode" : "7a8f0473-e409-442e-a843-5c2b813d00e9", + "skipType" : "PASS", + "coordinate" : "885,220;950,220" + } ] + }, { + "nodeType" : 1, + "nodeCode" : "7a8f0473-e409-442e-a843-5c2b813d00e9", + "nodeName" : "CEO", + "permissionFlag" : "1", + "nodeRatio" : 0.000, + "coordinate" : "1000,220|1000,220", + "skipAnyNode" : "N", + "formCustom" : "N", + "skipList" : [ { + "nowNodeCode" : "7a8f0473-e409-442e-a843-5c2b813d00e9", + "nextNodeCode" : "03c4d2bc-58b5-4408-a2e4-65afb046f169", + "skipType" : "PASS", + "coordinate" : "1050,220;1120,220" + } ] + }, { + "nodeType" : 2, + "nodeCode" : "03c4d2bc-58b5-4408-a2e4-65afb046f169", + "nodeName" : "结束", + "nodeRatio" : 0.000, + "coordinate" : "1140,220|1140,220", + "skipAnyNode" : "N", + "formCustom" : "N" + }, { + "nodeType" : 1, + "nodeCode" : "1e3e8d3b-18ae-4d6c-a814-ce0d724adfa4", + "nodeName" : "百分之60票签", + "permissionFlag" : "${userList}", + "nodeRatio" : 60.000, + "coordinate" : "700,120|700,120", + "skipAnyNode" : "N", + "formCustom" : "N", + "skipList" : [ { + "nowNodeCode" : "1e3e8d3b-18ae-4d6c-a814-ce0d724adfa4", + "nextNodeCode" : "1a20169e-3d82-4926-a151-e2daad28de1b", + "skipType" : "PASS", + "coordinate" : "750,120;860,120;860,195" + } ] + } ] +} \ No newline at end of file diff --git a/script/sql/oracle/oracle_ry_job.sql b/script/sql/oracle/oracle_ry_job.sql index da65dbbf6..c2dbbfa52 100644 --- a/script/sql/oracle/oracle_ry_job.sql +++ b/script/sql/oracle/oracle_ry_job.sql @@ -2,7 +2,7 @@ SnailJob Database Transfer Tool Source Server Type : MySQL Target Server Type : Oracle - Date: 2024-07-06 12:49:36 + Date: 2024-12-27 22:22:15 */ @@ -82,7 +82,7 @@ CREATE TABLE sj_notify_config id number GENERATED ALWAYS AS IDENTITY, namespace_id varchar2(64) DEFAULT '764d604ec6fc45f68cd92514c40e9e1a' NULL, group_name varchar2(64) NULL, - business_id varchar2(64) NULL, + notify_name varchar2(64) DEFAULT '' NULL, system_task_type smallint DEFAULT 3 NOT NULL, notify_status smallint DEFAULT 0 NOT NULL, recipient_ids varchar2(128) NULL, @@ -98,12 +98,12 @@ CREATE TABLE sj_notify_config ALTER TABLE sj_notify_config ADD CONSTRAINT pk_sj_notify_config PRIMARY KEY (id); -CREATE INDEX idx_sj_notify_config_01 ON sj_notify_config (namespace_id, group_name, business_id); +CREATE INDEX idx_sj_notify_config_01 ON sj_notify_config (namespace_id, group_name); COMMENT ON COLUMN sj_notify_config.id IS '主键'; COMMENT ON COLUMN sj_notify_config.namespace_id IS '命名空间id'; COMMENT ON COLUMN sj_notify_config.group_name IS '组名称'; -COMMENT ON COLUMN sj_notify_config.business_id IS '业务id ( job_id或workflow_id或scene_name ) '; +COMMENT ON COLUMN sj_notify_config.notify_name IS '通知名称'; COMMENT ON COLUMN sj_notify_config.system_task_type IS '任务类型 1. 重试任务 2. 重试回调 3、JOB任务 4、WORKFLOW任务'; COMMENT ON COLUMN sj_notify_config.notify_status IS '通知状态 0、未启用 1、启用'; COMMENT ON COLUMN sj_notify_config.recipient_ids IS '接收人id列表'; @@ -321,6 +321,7 @@ CREATE TABLE sj_retry_scene_config max_retry_count number DEFAULT 5 NOT NULL, back_off smallint DEFAULT 1 NOT NULL, trigger_interval varchar2(16) DEFAULT '' NULL, + notify_ids varchar2(128) DEFAULT '' NULL, deadline_request number DEFAULT 60000 NOT NULL, executor_timeout number DEFAULT 5 NOT NULL, route_key smallint DEFAULT 4 NOT NULL, @@ -342,6 +343,7 @@ COMMENT ON COLUMN sj_retry_scene_config.scene_status IS '组状态 0、未启用 COMMENT ON COLUMN sj_retry_scene_config.max_retry_count IS '最大重试次数'; COMMENT ON COLUMN sj_retry_scene_config.back_off IS '1、默认等级 2、固定间隔时间 3、CRON 表达式'; COMMENT ON COLUMN sj_retry_scene_config.trigger_interval IS '间隔时长'; +COMMENT ON COLUMN sj_retry_scene_config.notify_ids IS '通知告警场景配置id列表'; COMMENT ON COLUMN sj_retry_scene_config.deadline_request IS 'Deadline Request 调用链超时 单位毫秒'; COMMENT ON COLUMN sj_retry_scene_config.executor_timeout IS '任务执行超时时间,单位秒'; COMMENT ON COLUMN sj_retry_scene_config.route_key IS '路由策略'; @@ -506,6 +508,8 @@ CREATE TABLE sj_job retry_interval number DEFAULT 0 NOT NULL, bucket_index number DEFAULT 0 NOT NULL, resident smallint DEFAULT 0 NOT NULL, + notify_ids varchar2(128) DEFAULT '' NULL, + owner_id number NULL, description varchar2(256) DEFAULT '' NULL, ext_attrs varchar2(256) DEFAULT '' NULL, deleted smallint DEFAULT 0 NOT NULL, @@ -541,6 +545,8 @@ COMMENT ON COLUMN sj_job.parallel_num IS '并行数'; COMMENT ON COLUMN sj_job.retry_interval IS '重试间隔 ( s ) '; COMMENT ON COLUMN sj_job.bucket_index IS 'bucket'; COMMENT ON COLUMN sj_job.resident IS '是否是常驻任务'; +COMMENT ON COLUMN sj_job.notify_ids IS '通知告警场景配置id列表'; +COMMENT ON COLUMN sj_job.owner_id IS '负责人id'; COMMENT ON COLUMN sj_job.description IS '描述'; COMMENT ON COLUMN sj_job.ext_attrs IS '扩展字段'; COMMENT ON COLUMN sj_job.deleted IS '逻辑删除 1、删除'; @@ -548,7 +554,7 @@ COMMENT ON COLUMN sj_job.create_dt IS '创建时间'; COMMENT ON COLUMN sj_job.update_dt IS '修改时间'; COMMENT ON TABLE sj_job IS '任务信息'; -INSERT INTO sj_job(namespace_id, group_name, job_name, args_str, args_type, next_trigger_at, job_status, task_type, route_key, executor_type, executor_info, trigger_type, trigger_interval, block_strategy,executor_timeout, max_retry_times, parallel_num, retry_interval, bucket_index, resident, description, ext_attrs, deleted, create_dt, update_dt) VALUES ('dev', 'ruoyi_group', 'demo-job', NULL, 1, 1710344035622, 1, 1, 4, 1, 'testJobExecutor', 2, '60', 1, 60, 3, 1, 1, 116, 0, '', '', 0, sysdate, sysdate); +INSERT INTO sj_job(namespace_id, group_name, job_name, args_str, args_type, next_trigger_at, job_status, task_type, route_key, executor_type, executor_info, trigger_type, trigger_interval, block_strategy,executor_timeout, max_retry_times, parallel_num, retry_interval, bucket_index, resident, notify_ids, owner_id, description, ext_attrs, deleted, create_dt, update_dt) VALUES ('dev', 'ruoyi_group', 'demo-job', NULL, 1, 1710344035622, 1, 1, 4, 1, 'testJobExecutor', 2, '60', 1, 60, 3, 1, 1, 116, 0, '', 1,'', '', 0, sysdate, sysdate); -- sj_job_log_message CREATE TABLE sj_job_log_message @@ -781,6 +787,7 @@ CREATE TABLE sj_workflow description varchar2(256) DEFAULT '' NULL, flow_info clob DEFAULT NULL NULL, wf_context clob DEFAULT NULL NULL, + notify_ids varchar2(128) DEFAULT '' NULL, bucket_index number DEFAULT 0 NOT NULL, version number NOT NULL, ext_attrs varchar2(256) DEFAULT '' NULL, @@ -808,6 +815,7 @@ COMMENT ON COLUMN sj_workflow.executor_timeout IS '任务执行超时时间, COMMENT ON COLUMN sj_workflow.description IS '描述'; COMMENT ON COLUMN sj_workflow.flow_info IS '流程信息'; COMMENT ON COLUMN sj_workflow.wf_context IS '上下文'; +COMMENT ON COLUMN sj_workflow.notify_ids IS '通知告警场景配置id列表'; COMMENT ON COLUMN sj_workflow.bucket_index IS 'bucket'; COMMENT ON COLUMN sj_workflow.version IS '版本号'; COMMENT ON COLUMN sj_workflow.ext_attrs IS '扩展字段'; diff --git a/script/sql/oracle/oracle_ry_vue_5.X.sql b/script/sql/oracle/oracle_ry_vue_5.X.sql index 0aed89d74..2dd8198ff 100644 --- a/script/sql/oracle/oracle_ry_vue_5.X.sql +++ b/script/sql/oracle/oracle_ry_vue_5.X.sql @@ -5,7 +5,7 @@ create table sys_social ( id number(20) not null, user_id number(20) not null, - tenant_id varchar2(20) default null, + tenant_id varchar2(20) default '000000', auth_id varchar2(255) not null, source varchar2(255) not null, open_id varchar2(255) default null, @@ -65,7 +65,7 @@ comment on column sys_social.create_by is '创建者'; comment on column sys_social.create_time is '创建时间'; comment on column sys_social.update_by is '更新者'; comment on column sys_social.update_time is '更新时间'; -comment on column sys_social.del_flag is '删除标志(0代表存在 2代表删除)'; +comment on column sys_social.del_flag is '删除标志(0代表存在 1代表删除)'; -- ---------------------------- -- 租户表 @@ -108,7 +108,7 @@ comment on column sys_tenant.package_id is '租户套餐编号'; comment on column sys_tenant.expire_time is '过期时间'; comment on column sys_tenant.account_count is '用户数量(-1不限制)'; comment on column sys_tenant.status is '租户状态(0正常 1停用)'; -comment on column sys_tenant.del_flag is '删除标志(0代表存在 2代表删除)'; +comment on column sys_tenant.del_flag is '删除标志(0代表存在 1代表删除)'; comment on column sys_tenant.create_dept is '创建部门'; comment on column sys_tenant.create_by is '创建者'; comment on column sys_tenant.create_time is '创建时间'; @@ -148,7 +148,7 @@ comment on column sys_tenant_package.package_name is '套餐名称'; comment on column sys_tenant_package.menu_ids is '关联菜单id'; comment on column sys_tenant_package.remark is '备注'; comment on column sys_tenant_package.status is '状态(0正常 1停用)'; -comment on column sys_tenant_package.del_flag is '删除标志(0代表存在 2代表删除)'; +comment on column sys_tenant_package.del_flag is '删除标志(0代表存在 1代表删除)'; comment on column sys_tenant_package.create_dept is '创建部门'; comment on column sys_tenant_package.create_by is '创建者'; comment on column sys_tenant_package.create_time is '创建时间'; @@ -193,7 +193,7 @@ comment on column sys_dept.leader is '负责人'; comment on column sys_dept.phone is '联系电话'; comment on column sys_dept.email is '邮箱'; comment on column sys_dept.status is '部门状态(0正常 1停用)'; -comment on column sys_dept.del_flag is '删除标志(0代表存在 2代表删除)'; +comment on column sys_dept.del_flag is '删除标志(0代表存在 1代表删除)'; comment on column sys_dept.create_dept is '创建部门'; comment on column sys_dept.create_by is '创建者'; comment on column sys_dept.create_time is '创建时间'; @@ -258,7 +258,7 @@ comment on column sys_user.sex is '用户性别(0男 1女 2未知)' comment on column sys_user.avatar is '头像路径'; comment on column sys_user.password is '密码'; comment on column sys_user.status is '帐号状态(0正常 1停用)'; -comment on column sys_user.del_flag is '删除标志(0代表存在 2代表删除)'; +comment on column sys_user.del_flag is '删除标志(0代表存在 1代表删除)'; comment on column sys_user.login_ip is '最后登录IP'; comment on column sys_user.login_date is '最后登录时间'; comment on column sys_user.create_dept is '创建部门'; @@ -356,7 +356,7 @@ comment on column sys_role.data_scope is '数据范围(1:全部 comment on column sys_role.menu_check_strictly is '菜单树选择项是否关联显示'; comment on column sys_role.dept_check_strictly is '部门树选择项是否关联显示'; comment on column sys_role.status is '角色状态(0正常 1停用)'; -comment on column sys_role.del_flag is '删除标志(0代表存在 2代表删除)'; +comment on column sys_role.del_flag is '删除标志(0代表存在 1代表删除)'; comment on column sys_role.create_dept is '创建部门'; comment on column sys_role.create_by is '创建者'; comment on column sys_role.create_time is '创建时间'; @@ -738,10 +738,10 @@ create table sys_oper_log ( oper_url varchar2(255) default '', oper_ip varchar2(128) default '', oper_location varchar2(255) default '', - oper_param varchar2(2100) default '', - json_result varchar2(2100) default '', + oper_param varchar2(4000) default '', + json_result varchar2(4000) default '', status number(1) default 0, - error_msg varchar2(2100) default '', + error_msg varchar2(4000) default '', oper_time date, cost_time number(20) default 0 ); @@ -1245,7 +1245,7 @@ comment on column sys_client.device_type is '设备类型'; comment on column sys_client.active_timeout is 'token活跃超时时间'; comment on column sys_client.timeout is 'token固定超时'; comment on column sys_client.status is '状态(0正常 1停用)'; -comment on column sys_client.del_flag is '删除标志(0代表存在 2代表删除)'; +comment on column sys_client.del_flag is '删除标志(0代表存在 1代表删除)'; comment on column sys_client.create_dept is '创建部门'; comment on column sys_client.create_by is '创建者'; comment on column sys_client.create_time is '创建时间'; diff --git a/script/sql/oracle/oracle_ry_workflow.sql b/script/sql/oracle/oracle_ry_workflow.sql index 65474f45f..b515b78ff 100644 --- a/script/sql/oracle/oracle_ry_workflow.sql +++ b/script/sql/oracle/oracle_ry_workflow.sql @@ -1,261 +1,414 @@ -insert into sys_menu values('11616', '工作流' , '0', '6', 'workflow', '', '', '1', '0', 'M', '0', '0', '', 'workflow', 103, 1, sysdate, NULL, NULL, ''); -insert into sys_menu values('11617', '模型管理', '11616', '2', 'model', 'workflow/model/index', '', '1', '1', 'C', '0', '0', 'workflow:model:list', 'model', 103, 1, sysdate, NULL, NULL, ''); -insert into sys_menu values('11618', '我的任务', '0', '7', 'task', '', '', '1', '0', 'M', '0', '0', '', 'my-task', 103, 1, sysdate, NULL, NULL, ''); -insert into sys_menu values('11619', '我的待办', '11618', '2', 'taskWaiting', 'workflow/task/taskWaiting', '', '1', '1', 'C', '0', '0', '', 'waiting', 103, 1, sysdate, NULL, NULL, ''); -insert into sys_menu values('11632', '我的已办', '11618', '3', 'taskFinish', 'workflow/task/taskFinish', '', '1', '1', 'C', '0', '0', '', 'finish', 103, 1, sysdate, NULL, NULL, ''); -insert into sys_menu values('11633', '我的抄送', '11618', '4', 'taskCopyList', 'workflow/task/taskCopyList', '', '1', '1', 'C', '0', '0', '', 'my-copy', 103, 1, sysdate, NULL, NULL, ''); -insert into sys_menu values('11620', '流程定义', '11616', '3', 'processDefinition', 'workflow/processDefinition/index', '', '1', '1', 'C', '0', '0', '', 'process-definition', 103, 1, sysdate, NULL, NULL, ''); -insert into sys_menu values('11621', '流程实例', '11630', '1', 'processInstance', 'workflow/processInstance/index', '', '1', '1', 'C', '0', '0', '', 'tree-table', 103, 1, sysdate, NULL, NULL, ''); -insert into sys_menu values('11622', '流程分类', '11616', '1', 'category', 'workflow/category/index', '', '1', '0', 'C', '0', '0', 'workflow:category:list', 'category', 103, 1, sysdate, NULL, NULL, ''); -insert into sys_menu values('11629', '我发起的', '11618', '1', 'myDocument', 'workflow/task/myDocument', '', '1', '1', 'C', '0', '0', '', 'guide', 103, 1, sysdate, NULL, NULL, ''); -insert into sys_menu values('11630', '流程监控', '11616', '4', 'monitor', '', '', '1', '0', 'M', '0', '0', '', 'monitor', 103, 1, sysdate, NULL, NULL, ''); -insert into sys_menu values('11631', '待办任务', '11630', '2', 'allTaskWaiting', 'workflow/task/allTaskWaiting', '', '1', '1', 'C', '0', '0', '', 'waiting', 103, 1, sysdate, NULL, NULL, ''); - - --- 流程分类管理相关按钮 -insert into sys_menu values ('11623', '流程分类查询', '11622', '1', '#', '', '', 1, 0, 'F', '0', '0', 'workflow:category:query', '#', 103, 1, sysdate, null, null, ''); -insert into sys_menu values ('11624', '流程分类新增', '11622', '2', '#', '', '', 1, 0, 'F', '0', '0', 'workflow:category:add', '#', 103, 1, sysdate, null, null, ''); -insert into sys_menu values ('11625', '流程分类修改', '11622', '3', '#', '', '', 1, 0, 'F', '0', '0', 'workflow:category:edit', '#', 103, 1, sysdate, null, null, ''); -insert into sys_menu values ('11626', '流程分类删除', '11622', '4', '#', '', '', 1, 0, 'F', '0', '0', 'workflow:category:remove','#', 103, 1, sysdate, null, null, ''); -insert into sys_menu values ('11627', '流程分类导出', '11622', '5', '#', '', '', 1, 0, 'F', '0', '0', 'workflow:category:export','#', 103, 1, sysdate, null, null, ''); - --- 请假单信息 -create table TEST_LEAVE +create table FLOW_DEFINITION ( - ID NUMBER(20) not null - constraint PK_TEST_LEAVE - primary key, - LEAVE_TYPE VARCHAR2(255), - START_DATE DATE, - END_DATE DATE, - LEAVE_DAYS NUMBER(10), - REMARK VARCHAR2(255), - STATUS VARCHAR2(255), - CREATE_DEPT NUMBER(20), - CREATE_BY NUMBER(20), - CREATE_TIME DATE, - UPDATE_BY NUMBER(20), - UPDATE_TIME DATE, - TENANT_ID VARCHAR2(20) + ID NUMBER(20) not null, + FLOW_CODE VARCHAR2(40) not null, + FLOW_NAME VARCHAR2(100) not null, + CATEGORY VARCHAR2(100), + VERSION VARCHAR2(20) not null, + IS_PUBLISH NUMBER(1) default 0 not null, + FORM_CUSTOM VARCHAR2(1) default 'N', + FORM_PATH VARCHAR2(100), + ACTIVITY_STATUS NUMBER(1) default 1, + LISTENER_TYPE VARCHAR2(100), + LISTENER_PATH VARCHAR2(500), + EXT VARCHAR2(500), + CREATE_TIME DATE, + UPDATE_TIME DATE, + DEL_FLAG VARCHAR2(1) default '0', + TENANT_ID VARCHAR2(40) ); -comment on table TEST_LEAVE is '请假申请表'; -comment on column TEST_LEAVE.ID is '主键'; -comment on column TEST_LEAVE.LEAVE_TYPE is '请假类型'; -comment on column TEST_LEAVE.START_DATE is '开始时间'; -comment on column TEST_LEAVE.END_DATE is '结束时间'; -comment on column TEST_LEAVE.LEAVE_DAYS is '请假天数'; -comment on column TEST_LEAVE.REMARK is '请假原因'; -comment on column TEST_LEAVE.STATUS is '状态'; -comment on column TEST_LEAVE.CREATE_DEPT is '创建部门'; -comment on column TEST_LEAVE.CREATE_BY is '创建者'; -comment on column TEST_LEAVE.CREATE_TIME is '创建时间'; -comment on column TEST_LEAVE.UPDATE_BY is '更新者'; -comment on column TEST_LEAVE.UPDATE_TIME is '更新时间'; -comment on column TEST_LEAVE.TENANT_ID is '租户编号'; +alter table FLOW_DEFINITION add constraint PK_FLOW_DEFINITION primary key (ID); --- 流程分类信息表 -create table WF_CATEGORY +comment on table FLOW_DEFINITION is '流程定义表'; +comment on column FLOW_DEFINITION.ID is '主键id'; +comment on column FLOW_DEFINITION.FLOW_CODE is '流程编码'; +comment on column FLOW_DEFINITION.FLOW_NAME is '流程名称'; +comment on column FLOW_DEFINITION.CATEGORY is '流程类别'; +comment on column FLOW_DEFINITION.VERSION is '流程版本'; +comment on column FLOW_DEFINITION.IS_PUBLISH is '是否发布 (0未发布 1已发布 9失效)'; +comment on column FLOW_DEFINITION.FORM_CUSTOM is '审批表单是否自定义 (Y是 N否)'; +comment on column FLOW_DEFINITION.FORM_PATH is '审批表单路径'; +comment on column FLOW_DEFINITION.ACTIVITY_STATUS is '流程激活状态(0挂起 1激活)'; +comment on column FLOW_DEFINITION.LISTENER_TYPE is '监听器类型'; +comment on column FLOW_DEFINITION.LISTENER_PATH is '监听器路径'; +comment on column FLOW_DEFINITION.EXT is '扩展字段,预留给业务系统使用'; +comment on column FLOW_DEFINITION.CREATE_TIME is '创建时间'; +comment on column FLOW_DEFINITION.UPDATE_TIME is '更新时间'; +comment on column FLOW_DEFINITION.DEL_FLAG is '删除标志'; +comment on column FLOW_DEFINITION.TENANT_ID is '租户id'; + +create table FLOW_NODE ( - ID NUMBER(20) not null - constraint PK_WF_CATEGORY - primary key, - CATEGORY_NAME VARCHAR2(255), - CATEGORY_CODE VARCHAR2(255) - constraint UNI_CATEGORY_CODE - unique, - PARENT_ID NUMBER(20), - SORT_NUM NUMBER(10), - TENANT_ID VARCHAR2(20), - CREATE_DEPT NUMBER(20), - CREATE_BY NUMBER(20), - CREATE_TIME DATE, - UPDATE_BY NUMBER(20), - UPDATE_TIME DATE + ID NUMBER(20) not null, + NODE_TYPE NUMBER(1) not null, + DEFINITION_ID NUMBER(20) not null, + NODE_CODE VARCHAR2(100) not null, + NODE_NAME VARCHAR2(100), + NODE_RATIO NUMBER(6, 3), + COORDINATE VARCHAR2(100), + SKIP_ANY_NODE VARCHAR2(100) default 'N', + ANY_NODE_SKIP VARCHAR2(100), + LISTENER_TYPE VARCHAR2(100), + LISTENER_PATH VARCHAR2(500), + HANDLER_TYPE VARCHAR2(100), + HANDLER_PATH VARCHAR2(400), + FORM_CUSTOM VARCHAR2(1) default 'N', + FORM_PATH VARCHAR2(100), + VERSION VARCHAR2(20), + CREATE_TIME DATE, + UPDATE_TIME DATE, + DEL_FLAG VARCHAR2(1) default '0', + TENANT_ID VARCHAR2(40), + PERMISSION_FLAG VARCHAR2(200) ); -comment on table WF_CATEGORY is '流程分类'; -comment on column WF_CATEGORY.ID is '主键'; -comment on column WF_CATEGORY.CATEGORY_NAME is '分类名称'; -comment on column WF_CATEGORY.CATEGORY_CODE is '分类编码'; -comment on column WF_CATEGORY.PARENT_ID is '父级id'; -comment on column WF_CATEGORY.SORT_NUM is '排序'; -comment on column WF_CATEGORY.TENANT_ID is '租户编号'; -comment on column WF_CATEGORY.CREATE_DEPT is '创建部门'; -comment on column WF_CATEGORY.CREATE_BY is '创建者'; -comment on column WF_CATEGORY.CREATE_TIME is '创建时间'; -comment on column WF_CATEGORY.UPDATE_BY is '更新者'; -comment on column WF_CATEGORY.UPDATE_TIME is '更新时间'; -INSERT INTO wf_category values (1, 'OA', 'OA', 0, 0, '000000', 103, 1, sysdate, 1, sysdate); +alter table FLOW_NODE add constraint PK_FLOW_NODE primary key (ID); -create table WF_TASK_BACK_NODE +comment on table FLOW_NODE is '流程节点表'; +comment on column FLOW_NODE.ID is '主键id'; +comment on column FLOW_NODE.NODE_TYPE is '节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)'; +comment on column FLOW_NODE.DEFINITION_ID is '对应flow_definition表的id'; +comment on column FLOW_NODE.NODE_CODE is '流程节点编码'; +comment on column FLOW_NODE.NODE_NAME is '流程节点名称'; +comment on column FLOW_NODE.NODE_RATIO is '流程签署比例值'; +comment on column FLOW_NODE.COORDINATE is '坐标'; +comment on column FLOW_NODE.SKIP_ANY_NODE is '是否可以退回任意节点(Y是 N否)即将删除'; +comment on column FLOW_NODE.ANY_NODE_SKIP is '任意结点跳转'; +comment on column FLOW_NODE.LISTENER_TYPE is '监听器类型'; +comment on column FLOW_NODE.LISTENER_PATH is '监听器路径'; +comment on column FLOW_NODE.HANDLER_TYPE is '处理器类型'; +comment on column FLOW_NODE.HANDLER_PATH is '处理器路径'; +comment on column FLOW_NODE.FORM_CUSTOM is '审批表单是否自定义 (Y是 N否)'; +comment on column FLOW_NODE.FORM_PATH is '审批表单路径'; +comment on column FLOW_NODE.VERSION is '版本'; +comment on column FLOW_NODE.CREATE_TIME is '创建时间'; +comment on column FLOW_NODE.UPDATE_TIME is '更新时间'; +comment on column FLOW_NODE.DEL_FLAG is '删除标志'; +comment on column FLOW_NODE.TENANT_ID is '租户id'; +comment on column FLOW_NODE.PERMISSION_FLAG is '权限标识(权限类型:权限标识,可以多个,用逗号隔开)'; + +create table FLOW_SKIP ( - ID NUMBER(20) not null - constraint PK_WF_TASK_BACK_NODE - primary key, - NODE_ID VARCHAR2(255) not null, - NODE_NAME VARCHAR2(255) not null, - ORDER_NO NUMBER(20) not null, - INSTANCE_ID VARCHAR2(255) not null, - TASK_TYPE VARCHAR2(255) not null, - ASSIGNEE VARCHAR2(2000) not null, - TENANT_ID VARCHAR2(20), - CREATE_DEPT NUMBER(20), - CREATE_BY NUMBER(20), - CREATE_TIME DATE, - UPDATE_BY NUMBER(20), - UPDATE_TIME DATE + ID NUMBER(20) not null, + DEFINITION_ID NUMBER(20) not null, + NOW_NODE_CODE VARCHAR2(100) not null, + NOW_NODE_TYPE NUMBER(1), + NEXT_NODE_CODE VARCHAR2(100) not null, + NEXT_NODE_TYPE NUMBER(1), + SKIP_NAME VARCHAR2(100), + SKIP_TYPE VARCHAR2(40), + SKIP_CONDITION VARCHAR2(200), + COORDINATE VARCHAR2(100), + CREATE_TIME DATE, + UPDATE_TIME DATE, + DEL_FLAG VARCHAR2(1) default '0', + TENANT_ID VARCHAR2(40) ); -comment on table WF_TASK_BACK_NODE is '节点审批记录'; -comment on column WF_TASK_BACK_NODE.ID is '主键'; -comment on column WF_TASK_BACK_NODE.NODE_ID is '节点id'; -comment on column WF_TASK_BACK_NODE.NODE_NAME is '节点名称'; -comment on column WF_TASK_BACK_NODE.ORDER_NO is '排序'; -comment on column WF_TASK_BACK_NODE.INSTANCE_ID is '流程实例id'; -comment on column WF_TASK_BACK_NODE.TASK_TYPE is '节点类型'; -comment on column WF_TASK_BACK_NODE.ASSIGNEE is '审批人'; -comment on column WF_TASK_BACK_NODE.TENANT_ID is '租户编号'; -comment on column WF_TASK_BACK_NODE.CREATE_DEPT is '创建部门'; -comment on column WF_TASK_BACK_NODE.CREATE_BY is '创建者'; -comment on column WF_TASK_BACK_NODE.CREATE_TIME is '创建时间'; -comment on column WF_TASK_BACK_NODE.UPDATE_BY is '更新者'; -comment on column WF_TASK_BACK_NODE.UPDATE_TIME is '更新时间'; -create table WF_DEFINITION_CONFIG +alter table FLOW_SKIP add constraint PK_FLOW_SKIP primary key (ID); + +comment on table FLOW_SKIP is '节点跳转关联表'; +comment on column FLOW_SKIP.ID is '主键id'; +comment on column FLOW_SKIP.DEFINITION_ID is '流程定义id'; +comment on column FLOW_SKIP.NOW_NODE_CODE is '当前流程节点类型 (0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)'; +comment on column FLOW_SKIP.NOW_NODE_TYPE is '下一个流程节点类型 (0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)'; +comment on column FLOW_SKIP.NEXT_NODE_CODE is '下一个流程节点编码'; +comment on column FLOW_SKIP.NEXT_NODE_TYPE is '下一个流程节点类型 (0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)'; +comment on column FLOW_SKIP.SKIP_NAME is '跳转名称'; +comment on column FLOW_SKIP.SKIP_TYPE is '跳转类型 (PASS审批通过 REJECT退回)'; +comment on column FLOW_SKIP.SKIP_CONDITION is '跳转条件'; +comment on column FLOW_SKIP.COORDINATE is '坐标'; +comment on column FLOW_SKIP.CREATE_TIME is '创建时间'; +comment on column FLOW_SKIP.UPDATE_TIME is '更新时间'; +comment on column FLOW_SKIP.DEL_FLAG is '删除标志'; +comment on column FLOW_SKIP.TENANT_ID is '租户id'; + +create table FLOW_INSTANCE ( - ID NUMBER(20) NOT NULL - CONSTRAINT PK_WF_DEFINITION_CONFIG - PRIMARY KEY, - TABLE_NAME VARCHAR2(255) NOT NULL, - DEFINITION_ID VARCHAR2(255) NOT NULL, - PROCESS_KEY VARCHAR2(255) NOT NULL, - VERSION NUMBER(10) NOT NULL, - REMARK VARCHAR2(500), - TENANT_ID VARCHAR2(20), - CREATE_DEPT NUMBER(20), - CREATE_BY NUMBER(20), + ID NUMBER not null, + DEFINITION_ID NUMBER not null, + BUSINESS_ID VARCHAR2(40) not null, + NODE_TYPE NUMBER(1), + NODE_CODE VARCHAR2(100), + NODE_NAME VARCHAR2(100), + VARIABLE CLOB, + FLOW_STATUS VARCHAR2(20), + ACTIVITY_STATUS NUMBER(1) default 1, + DEF_JSON CLOB, + CREATE_BY VARCHAR2(64) default '', + CREATE_TIME DATE, + UPDATE_TIME DATE, + EXT VARCHAR2(500), + DEL_FLAG VARCHAR2(1) default '0', + TENANT_ID VARCHAR2(40) +); + +alter table FLOW_INSTANCE add constraint PK_FLOW_INSTANCE primary key (ID); + +comment on table FLOW_INSTANCE is '流程实例表'; +comment on column FLOW_INSTANCE.ID is '主键id'; +comment on column FLOW_INSTANCE.DEFINITION_ID is '对应flow_definition表的id'; +comment on column FLOW_INSTANCE.BUSINESS_ID is '业务id'; +comment on column FLOW_INSTANCE.NODE_TYPE is '开始节点类型 (0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)'; +comment on column FLOW_INSTANCE.NODE_CODE is '开始节点编码'; +comment on column FLOW_INSTANCE.NODE_NAME is '开始节点名称'; +comment on column FLOW_INSTANCE.VARIABLE is '任务变量'; +comment on column FLOW_INSTANCE.FLOW_STATUS is '流程状态(0待提交 1审批中 2 审批通过 3自动通过 4终止 5作废 6撤销 7取回 8已完成 9已退回 10失效)'; +comment on column FLOW_INSTANCE.ACTIVITY_STATUS is '流程激活状态(0挂起 1激活)'; +comment on column FLOW_INSTANCE.DEF_JSON is '流程定义json'; +comment on column FLOW_INSTANCE.CREATE_BY is '创建者'; +comment on column FLOW_INSTANCE.CREATE_TIME is '创建时间'; +comment on column FLOW_INSTANCE.UPDATE_TIME is '更新时间'; +comment on column FLOW_INSTANCE.EXT is '扩展字段,预留给业务系统使用'; +comment on column FLOW_INSTANCE.DEL_FLAG is '删除标志'; +comment on column FLOW_INSTANCE.TENANT_ID is '租户id'; + +create table FLOW_TASK +( + ID NUMBER(20) not null, + DEFINITION_ID NUMBER(20) not null, + INSTANCE_ID NUMBER(20) not null, + NODE_CODE VARCHAR2(100), + NODE_NAME VARCHAR2(100), + NODE_TYPE NUMBER(1), + FORM_CUSTOM VARCHAR2(1) default 'N', + FORM_PATH VARCHAR2(100), CREATE_TIME DATE, - UPDATE_BY NUMBER(20), UPDATE_TIME DATE, - constraint uni_definition_id - unique (definition_id) -); -comment on table WF_DEFINITION_CONFIG is '流程定义配置'; -comment on column WF_DEFINITION_CONFIG.ID is '主键'; -comment on column WF_DEFINITION_CONFIG.TABLE_NAME is '表名'; -comment on column WF_DEFINITION_CONFIG.DEFINITION_ID is '流程定义ID'; -comment on column WF_DEFINITION_CONFIG.PROCESS_KEY is '流程KEY'; -comment on column WF_DEFINITION_CONFIG.VERSION is '流程版本'; -comment on column WF_DEFINITION_CONFIG.TENANT_ID is '租户编号'; -comment on column WF_DEFINITION_CONFIG.REMARK is '备注'; -comment on column WF_DEFINITION_CONFIG.CREATE_DEPT is '创建部门'; -comment on column WF_DEFINITION_CONFIG.CREATE_BY is '创建者'; -comment on column WF_DEFINITION_CONFIG.CREATE_TIME is '创建时间'; -comment on column WF_DEFINITION_CONFIG.UPDATE_BY is '更新者'; -comment on column WF_DEFINITION_CONFIG.UPDATE_TIME is '更新时间'; - -create table WF_FORM_MANAGE -( - ID NUMBER(20) NOT NULL - CONSTRAINT PK_WF_FORM_MANAGE - PRIMARY KEY, - FORM_NAME VARCHAR2(255) NOT NULL, - FORM_TYPE VARCHAR2(255) NOT NULL, - ROUTER VARCHAR2(255) NOT NULL, - REMARK VARCHAR2(500), - TENANT_ID VARCHAR2(20), - CREATE_DEPT NUMBER(20), - CREATE_BY NUMBER(20), - CREATE_TIME DATE, - UPDATE_BY NUMBER(20), - UPDATE_TIME DATE + DEL_FLAG VARCHAR2(1) default '0', + TENANT_ID VARCHAR2(40) ); -comment on table WF_FORM_MANAGE is '表单管理'; -comment on column WF_FORM_MANAGE.ID is '主键'; -comment on column WF_FORM_MANAGE.FORM_NAME is '表单名称'; -comment on column WF_FORM_MANAGE.FORM_TYPE is '表单类型'; -comment on column WF_FORM_MANAGE.ROUTER is '路由地址/表单ID'; -comment on column WF_FORM_MANAGE.REMARK is '备注'; -comment on column WF_FORM_MANAGE.TENANT_ID is '租户编号'; -comment on column WF_FORM_MANAGE.CREATE_DEPT is '创建部门'; -comment on column WF_FORM_MANAGE.CREATE_BY is '创建者'; -comment on column WF_FORM_MANAGE.CREATE_TIME is '创建时间'; -comment on column WF_FORM_MANAGE.UPDATE_BY is '更新者'; -comment on column WF_FORM_MANAGE.UPDATE_TIME is '更新时间'; +alter table FLOW_TASK add constraint PK_FLOW_TASK primary key (ID); -insert into wf_form_manage(id, form_name, form_type, router, remark, tenant_id, create_dept, create_by, create_time, update_by, update_time) VALUES (1, '请假申请', 'static', '/workflow/leaveEdit/index', NULL, '000000', 103, 1, sysdate, 1, sysdate); +comment on table FLOW_TASK is '待办任务表'; +comment on column FLOW_TASK.ID is '主键id'; +comment on column FLOW_TASK.DEFINITION_ID is '对应flow_definition表的id'; +comment on column FLOW_TASK.INSTANCE_ID is '对应flow_instance表的id'; +comment on column FLOW_TASK.NODE_CODE is '节点编码'; +comment on column FLOW_TASK.NODE_NAME is '节点名称'; +comment on column FLOW_TASK.NODE_TYPE is '节点类型 (0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)'; +comment on column FLOW_TASK.FORM_CUSTOM is '审批表单是否自定义 (Y是 N否)'; +comment on column FLOW_TASK.FORM_PATH is '审批表单路径'; +comment on column FLOW_TASK.CREATE_TIME is '创建时间'; +comment on column FLOW_TASK.UPDATE_TIME is '更新时间'; +comment on column FLOW_TASK.DEL_FLAG is '删除标志'; +comment on column FLOW_TASK.TENANT_ID is '租户id'; -create table WF_NODE_CONFIG +create table FLOW_HIS_TASK ( - ID NUMBER(20) NOT NULL - CONSTRAINT PK_WF_NODE_CONFIG - PRIMARY KEY, - FORM_ID NUMBER(20), - FORM_TYPE VARCHAR2(255), - NODE_NAME VARCHAR2(255) NOT NULL, - NODE_ID VARCHAR2(255) NOT NULL, - DEFINITION_ID VARCHAR2(255) NOT NULL, - APPLY_USER_TASK CHAR(1) DEFAULT '0', - TENANT_ID VARCHAR2(20), - CREATE_DEPT NUMBER(20), - CREATE_BY NUMBER(20), + ID NUMBER(20) not null, + DEFINITION_ID NUMBER(20) not null, + INSTANCE_ID NUMBER(20) not null, + TASK_ID NUMBER(20) not null, + NODE_CODE VARCHAR2(100), + NODE_NAME VARCHAR2(100), + NODE_TYPE NUMBER(1), + TARGET_NODE_CODE VARCHAR2(200), + TARGET_NODE_NAME VARCHAR2(200), + APPROVER VARCHAR2(40), + COOPERATE_TYPE NUMBER(1) default 0, + COLLABORATOR VARCHAR2(40), + SKIP_TYPE VARCHAR2(10), + FLOW_STATUS VARCHAR2(20), + FORM_CUSTOM VARCHAR2(1) default 'N', + FORM_PATH VARCHAR2(100), + MESSAGE VARCHAR2(500), + VARIABLE CLOB, + EXT VARCHAR2(500), CREATE_TIME DATE, - UPDATE_BY NUMBER(20), - UPDATE_TIME DATE + UPDATE_TIME DATE, + DEL_FLAG VARCHAR2(1) default '0', + TENANT_ID VARCHAR2(40) + ); -comment on table WF_NODE_CONFIG is '节点配置'; -comment on column WF_NODE_CONFIG.ID is '主键'; -comment on column WF_NODE_CONFIG.FORM_ID is '表单id'; -comment on column WF_NODE_CONFIG.FORM_TYPE is '表单类型'; -comment on column WF_NODE_CONFIG.NODE_ID is '节点id'; -comment on column WF_NODE_CONFIG.NODE_NAME is '节点名称'; -comment on column WF_NODE_CONFIG.DEFINITION_ID is '流程定义id'; -comment on column WF_NODE_CONFIG.APPLY_USER_TASK is '是否为申请人节点 (0是 1否)'; -comment on column WF_NODE_CONFIG.TENANT_ID is '租户编号'; -comment on column WF_NODE_CONFIG.CREATE_DEPT is '创建部门'; -comment on column WF_NODE_CONFIG.CREATE_BY is '创建者'; -comment on column WF_NODE_CONFIG.CREATE_TIME is '创建时间'; -comment on column WF_NODE_CONFIG.UPDATE_BY is '更新者'; -comment on column WF_NODE_CONFIG.UPDATE_TIME is '更新时间'; +alter table FLOW_HIS_TASK add constraint PK_FLOW_HIS_TASK primary key (ID); -INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11638, '请假申请', 5, 1, 'leave', 'workflow/leave/index', 1, 0, 'C', '0', '0', 'workflow:leave:list', '#', 103, 1, sysdate, NULL, NULL, '请假申请菜单'); -INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11639, '请假申请查询', 11638, 1, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:query', '#', 103, 1, sysdate, NULL, NULL, ''); -INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11640, '请假申请新增', 11638, 2, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:add', '#', 103, 1, sysdate, NULL, NULL, ''); -INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11641, '请假申请修改', 11638, 3, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:edit', '#', 103, 1, sysdate, NULL, NULL, ''); -INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11642, '请假申请删除', 11638, 4, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:remove', '#', 103, 1, sysdate, NULL, NULL, ''); -INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11643, '请假申请导出', 11638, 5, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:export', '#', 103, 1, sysdate, NULL, NULL, ''); +comment on table FLOW_HIS_TASK is '历史任务记录表'; +comment on column FLOW_HIS_TASK.ID is '主键id'; +comment on column FLOW_HIS_TASK.DEFINITION_ID is '对应flow_definition表的id'; +comment on column FLOW_HIS_TASK.INSTANCE_ID is '对应flow_instance表的id'; +comment on column FLOW_HIS_TASK.TASK_ID is '对应flow_task表的id'; +comment on column FLOW_HIS_TASK.NODE_CODE is '开始节点编码'; +comment on column FLOW_HIS_TASK.NODE_NAME is '开始节点名称'; +comment on column FLOW_HIS_TASK.NODE_TYPE is '开始节点类型 (0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)'; +comment on column FLOW_HIS_TASK.TARGET_NODE_CODE is '目标节点编码'; +comment on column FLOW_HIS_TASK.TARGET_NODE_NAME is '目标节点名称'; +comment on column FLOW_HIS_TASK.SKIP_TYPE is '流转类型(PASS通过 REJECT退回 NONE无动作)'; +comment on column FLOW_HIS_TASK.FLOW_STATUS is '流程状态(1审批中 2 审批通过 9已退回 10失效)'; +comment on column FLOW_HIS_TASK.FORM_CUSTOM is '审批表单是否自定义 (Y是 N否)'; +comment on column FLOW_HIS_TASK.FORM_PATH is '审批表单路径'; +comment on column FLOW_HIS_TASK.MESSAGE is '审批意见'; +comment on column FLOW_HIS_TASK.VARIABLE is '任务变量'; +comment on column FLOW_HIS_TASK.EXT is '扩展字段,预留给业务系统使用'; +comment on column FLOW_HIS_TASK.CREATE_TIME is '任务开始时间'; +comment on column FLOW_HIS_TASK.UPDATE_TIME is '审批完成时间'; +comment on column FLOW_HIS_TASK.DEL_FLAG is '删除标志'; +comment on column FLOW_HIS_TASK.TENANT_ID is '租户id'; +comment on column FLOW_HIS_TASK.APPROVER is '审批者'; +comment on column FLOW_HIS_TASK.COOPERATE_TYPE is '协作方式(1审批 2转办 3委派 4会签 5票签 6加签 7减签)'; +comment on column FLOW_HIS_TASK.COLLABORATOR is '协作人'; -INSERT INTO sys_dict_type(dict_id, tenant_id, dict_name, dict_type, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (13, '000000', '业务状态', 'wf_business_status', 103, 1, sysdate, NULL, NULL, '业务状态列表'); -INSERT INTO sys_dict_type(dict_id, tenant_id, dict_name, dict_type, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (14, '000000', '表单类型', 'wf_form_type', 103, 1, sysdate, NULL, NULL, '表单类型列表'); +create table FLOW_USER +( + ID NUMBER(20) not null, + TYPE VARCHAR2(1) not null, + PROCESSED_BY VARCHAR2(80), + ASSOCIATED NUMBER(20) not null, + CREATE_TIME DATE, + CREATE_BY VARCHAR2(80), + UPDATE_TIME DATE, + DEL_FLAG VARCHAR2(1) default '0', + TENANT_ID VARCHAR2(40) +); -INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (39, '000000', 1, '已撤销', 'cancel', 'wf_business_status', '', 'danger', 'N', 103, 1, sysdate, NULL, NULL, '已撤销'); -INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (40, '000000', 2, '草稿', 'draft', 'wf_business_status', '', 'info', 'N', 103, 1, sysdate, NULL, NULL, '草稿'); -INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (41, '000000', 3, '待审核', 'waiting', 'wf_business_status', '', 'primary', 'N', 103, 1,sysdate, NULL, NULL, '待审核'); -INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (42, '000000', 4, '已完成', 'finish', 'wf_business_status', '', 'success', 'N', 103, 1, sysdate, NULL, NULL, '已完成'); -INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (43, '000000', 5, '已作废', 'invalid', 'wf_business_status', '', 'danger', 'N', 103, 1, sysdate, NULL, NULL, '已作废'); -INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (44, '000000', 6, '已退回', 'back', 'wf_business_status', '', 'danger', 'N', 103, 1, sysdate, NULL, NULL, '已退回'); -INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (45, '000000', 7, '已终止', 'termination', 'wf_business_status', '', 'danger', 'N', 103, 1,sysdate, NULL, NULL, '已终止'); -INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (46, '000000', 1, '自定义表单', 'static', 'wf_form_type', '', 'success', 'N', 103, 1, sysdate, NULL, NULL, '自定义表单'); -INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (47, '000000', 2, '动态表单', 'dynamic', 'wf_form_type', '', 'primary', 'N', 103, 1, sysdate, NULL, NULL, '动态表单'); +alter table FLOW_USER add constraint PK_FLOW_USER primary key (ID); --- 表单管理 SQL -insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) -values(11628, '表单管理', '11616', '5', 'formManage', 'workflow/formManage/index', 1, 0, 'C', '0', '0', 'workflow:formManage:list', 'tree-table', 103, 1, sysdate, null, null, '表单管理菜单'); +comment on table FLOW_USER is '待办任务表'; +comment on column FLOW_USER.ID is '主键id'; +comment on column FLOW_USER.TYPE is '人员类型(1待办任务的审批人权限 2待办任务的转办人权限 3待办任务的委托人权限)'; +comment on column FLOW_USER.PROCESSED_BY is '权限人)'; +comment on column FLOW_USER.ASSOCIATED is '任务表id'; +comment on column FLOW_USER.CREATE_TIME is '创建时间'; +comment on column FLOW_USER.CREATE_BY is '节点名称'; +comment on column FLOW_USER.UPDATE_TIME is '更新时间'; +comment on column FLOW_USER.DEL_FLAG is '删除标志'; +comment on column FLOW_USER.TENANT_ID is '租户id'; --- 表单管理按钮 SQL -insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) -values(11644, '表单管理查询', 11628, '1', '#', '', 1, 0, 'F', '0', '0', 'workflow:formManage:query', '', 103, 1, sysdate, null, null, ''); +create index USER_PROCESSED_TYPE on FLOW_USER (PROCESSED_BY, TYPE); -insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) -values(11645, '表单管理新增', 11628, '2', '#', '', 1, 0, 'F', '0', '0', 'workflow:formManage:add', '', 103, 1, sysdate, null, null, ''); +-- ---------------------------- +-- 流程分类表 +-- ---------------------------- +CREATE TABLE flow_category +( + category_id NUMBER (20) NOT NULL, + tenant_id VARCHAR2 (20) DEFAULT '000000', + parent_id NUMBER (20) DEFAULT 0, + ancestors VARCHAR2 (500) DEFAULT '', + category_name VARCHAR2 (30) NOT NULL, + order_num NUMBER (4) DEFAULT 0, + del_flag CHAR(1) DEFAULT '0', + create_dept NUMBER (20), + create_by NUMBER (20), + create_time DATE, + update_by NUMBER (20), + update_time DATE +); -insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) -values(11646, '表单管理修改', 11628, '3', '#', '', 1, 0, 'F', '0', '0', 'workflow:formManage:edit', '', 103, 1, sysdate, null, null, ''); +alter table flow_category add constraint pk_flow_category primary key (category_id); -insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) -values(11647, '表单管理删除', 11628, '4', '#', '', 1, 0, 'F', '0', '0', 'workflow:formManage:remove', '', 103, 1, sysdate, null, null, ''); +COMMENT ON TABLE flow_category IS '流程分类'; +COMMENT ON COLUMN flow_category.category_id IS '流程分类ID'; +COMMENT ON COLUMN flow_category.tenant_id IS '租户编号'; +COMMENT ON COLUMN flow_category.parent_id IS '父流程分类id'; +COMMENT ON COLUMN flow_category.ancestors IS '祖级列表'; +COMMENT ON COLUMN flow_category.category_name IS '流程分类名称'; +COMMENT ON COLUMN flow_category.order_num IS '显示顺序'; +COMMENT ON COLUMN flow_category.del_flag IS '删除标志(0代表存在 1代表删除)'; +COMMENT ON COLUMN flow_category.create_dept IS '创建部门'; +COMMENT ON COLUMN flow_category.create_by IS '创建者'; +COMMENT ON COLUMN flow_category.create_time IS '创建时间'; +COMMENT ON COLUMN flow_category.update_by IS '更新者'; +COMMENT ON COLUMN flow_category.update_time IS '更新时间'; -insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) -values(11648, '表单管理导出', 11628, '5', '#', '', 1, 0, 'F', '0', '0', 'workflow:formManage:export', 'tree-table', 103, 1, sysdate, null, null, ''); +INSERT INTO flow_category VALUES (100, '000000', 0, '0', 'OA审批', 0, '0', 103, 1, SYSDATE, NULL, NULL); +INSERT INTO flow_category VALUES (101, '000000', 100, '0,100', '假勤管理', 0, '0', 103, 1, SYSDATE, NULL, NULL); +INSERT INTO flow_category VALUES (102, '000000', 100, '0,100', '人事管理', 1, '0', 103, 1, SYSDATE, NULL, NULL); +INSERT INTO flow_category VALUES (103, '000000', 101, '0,100,101', '请假', 0, '0', 103, 1, SYSDATE, NULL, NULL); +INSERT INTO flow_category VALUES (104, '000000', 101, '0,100,101', '出差', 1, '0', 103, 1, SYSDATE, NULL, NULL); +INSERT INTO flow_category VALUES (105, '000000', 101, '0,100,101', '加班', 2, '0', 103, 1, SYSDATE, NULL, NULL); +INSERT INTO flow_category VALUES (106, '000000', 101, '0,100,101', '换班', 3, '0', 103, 1, SYSDATE, NULL, NULL); +INSERT INTO flow_category VALUES (107, '000000', 101, '0,100,101', '外出', 4, '0', 103, 1, SYSDATE, NULL, NULL); +INSERT INTO flow_category VALUES (108, '000000', 102, '0,100,102', '转正', 1, '0', 103, 1, SYSDATE, NULL, NULL); +INSERT INTO flow_category VALUES (109, '000000', 102, '0,100,102', '离职', 2, '0', 103, 1, SYSDATE, NULL, NULL); + + +-- ---------------------------- +-- 请假单信息 +-- ---------------------------- +CREATE TABLE test_leave +( + id NUMBER (20) NOT NULL, + tenant_id VARCHAR2 (20) DEFAULT '000000', + leave_type VARCHAR2 (255) NOT NULL, + start_date DATE NOT NULL, + end_date DATE NOT NULL, + leave_days NUMBER (10) NOT NULL, + remark VARCHAR2 (255), + status VARCHAR2 (255), + create_dept NUMBER (20), + create_by NUMBER (20), + create_time DATE, + update_by NUMBER (20), + update_time DATE +); + +alter table test_leave add constraint pk_test_leave primary key (id); + +COMMENT ON TABLE test_leave IS '请假申请表'; +COMMENT ON COLUMN test_leave.id IS 'ID'; +COMMENT ON COLUMN test_leave.tenant_id IS '租户编号'; +COMMENT ON COLUMN test_leave.leave_type IS '请假类型'; +COMMENT ON COLUMN test_leave.start_date IS '开始时间'; +COMMENT ON COLUMN test_leave.end_date IS '结束时间'; +COMMENT ON COLUMN test_leave.leave_days IS '请假天数'; +COMMENT ON COLUMN test_leave.remark IS '请假原因'; +COMMENT ON COLUMN test_leave.status IS '状态'; +COMMENT ON COLUMN test_leave.create_dept IS '创建部门'; +COMMENT ON COLUMN test_leave.create_by IS '创建者'; +COMMENT ON COLUMN test_leave.create_time IS '创建时间'; +COMMENT ON COLUMN test_leave.update_by IS '更新者'; +COMMENT ON COLUMN test_leave.update_time IS '更新时间'; + +INSERT INTO sys_menu VALUES ('11616', '工作流', '0', '6', 'workflow', '', '', '1', '0', 'M', '0', '0', '', 'workflow', 103, 1, SYSDATE, NULL, NULL, ''); +INSERT INTO sys_menu VALUES ('11618', '我的任务', '0', '7', 'task', '', '', '1', '0', 'M', '0', '0', '', 'my-task', 103, 1, SYSDATE, NULL, NULL, ''); +INSERT INTO sys_menu VALUES ('11619', '我的待办', '11618', '2', 'taskWaiting', 'workflow/task/taskWaiting', '', '1', '1', 'C', '0', '0', '', 'waiting', 103, 1, SYSDATE, NULL, NULL, ''); +INSERT INTO sys_menu VALUES ('11632', '我的已办', '11618', '3', 'taskFinish', 'workflow/task/taskFinish', '', '1', '1', 'C', '0', '0', '', 'finish', 103, 1, SYSDATE, NULL, NULL, ''); +INSERT INTO sys_menu VALUES ('11633', '我的抄送', '11618', '4', 'taskCopyList', 'workflow/task/taskCopyList', '', '1', '1', 'C', '0', '0', '', 'my-copy', 103, 1, SYSDATE, NULL, NULL, ''); +INSERT INTO sys_menu VALUES ('11620', '流程定义', '11616', '3', 'processDefinition', 'workflow/processDefinition/index', '', '1', '1', 'C', '0', '0', '', 'process-definition', 103, 1, SYSDATE, NULL, NULL, ''); +INSERT INTO sys_menu VALUES ('11621', '流程实例', '11630', '1', 'processInstance', 'workflow/processInstance/index', '', '1', '1', 'C', '0', '0', '', 'tree-table', 103, 1, SYSDATE, NULL, NULL, ''); +INSERT INTO sys_menu VALUES ('11622', '流程分类', '11616', '1', 'category', 'workflow/category/index', '', '1', '0', 'C', '0', '0', 'workflow:category:list', 'category', 103, 1, SYSDATE, NULL, NULL, ''); +INSERT INTO sys_menu VALUES ('11629', '我发起的', '11618', '1', 'myDocument', 'workflow/task/myDocument', '', '1', '1', 'C', '0', '0', '', 'guide', 103, 1, SYSDATE, NULL, NULL, ''); +INSERT INTO sys_menu VALUES ('11630', '流程监控', '11616', '4', 'monitor', '', '', '1', '0', 'M', '0', '0', '', 'monitor', 103, 1, SYSDATE, NULL, NULL, ''); +INSERT INTO sys_menu VALUES ('11631', '待办任务', '11630', '2', 'allTaskWaiting', 'workflow/task/allTaskWaiting', '', '1', '1', 'C', '0', '0', '', 'waiting', 103, 1, SYSDATE, NULL, NULL, ''); + +INSERT INTO sys_menu VALUES ('11623', '流程分类查询', '11622', '1', '#', '', '', '1', '0', 'F', '0', '0', 'workflow:category:query', '#', 103, 1, SYSDATE, NULL, NULL, ''); +INSERT INTO sys_menu VALUES ('11624', '流程分类新增', '11622', '2', '#', '', '', '1', '0', 'F', '0', '0', 'workflow:category:add', '#', 103, 1, SYSDATE, NULL, NULL, ''); +INSERT INTO sys_menu VALUES ('11625', '流程分类修改', '11622', '3', '#', '', '', '1', '0', 'F', '0', '0', 'workflow:category:edit', '#', 103, 1, SYSDATE, NULL, NULL, ''); +INSERT INTO sys_menu VALUES ('11626', '流程分类删除', '11622', '4', '#', '', '', '1', '0', 'F', '0', '0', 'workflow:category:remove', '#', 103, 1, SYSDATE, NULL, NULL, ''); +INSERT INTO sys_menu VALUES ('11627', '流程分类导出', '11622', '5', '#', '', '', '1', '0', 'F', '0', '0', 'workflow:category:export', '#', 103, 1, SYSDATE, NULL, NULL, ''); + +INSERT INTO sys_menu VALUES ('11638', '请假申请', '5', '1', 'leave', 'workflow/leave/index', '', '1', '0', 'C', '0', '0', 'workflow:leave:list', '#', 103, 1, SYSDATE, NULL, NULL, '请假申请菜单'); +INSERT INTO sys_menu VALUES ('11639', '请假申请查询', '11638', '1', '#', '', '', '1', '0', 'F', '0', '0', 'workflow:leave:query', '#', 103, 1, SYSDATE, NULL, NULL, ''); +INSERT INTO sys_menu VALUES ('11640', '请假申请新增', '11638', '2', '#', '', '', '1', '0', 'F', '0', '0', 'workflow:leave:add', '#', 103, 1, SYSDATE, NULL, NULL, ''); +INSERT INTO sys_menu VALUES ('11641', '请假申请修改', '11638', '3', '#', '', '', '1', '0', 'F', '0', '0', 'workflow:leave:edit', '#', 103, 1, SYSDATE, NULL, NULL, ''); +INSERT INTO sys_menu VALUES ('11642', '请假申请删除', '11638', '4', '#', '', '', '1', '0', 'F', '0', '0', 'workflow:leave:remove', '#', 103, 1, SYSDATE, NULL, NULL, ''); +INSERT INTO sys_menu VALUES ('11643', '请假申请导出', '11638', '5', '#', '', '', '1', '0', 'F', '0', '0', 'workflow:leave:export', '#', 103, 1, SYSDATE, NULL, NULL, ''); + +INSERT INTO sys_dict_type VALUES (13, '000000', '业务状态', 'wf_business_status', 103, 1, SYSDATE, NULL, NULL, '业务状态列表'); +INSERT INTO sys_dict_type VALUES (14, '000000', '表单类型', 'wf_form_type', 103, 1, SYSDATE, NULL, NULL, '表单类型列表'); +INSERT INTO sys_dict_type VALUES (15, '000000', '任务状态', 'wf_task_status', 103, 1, SYSDATE, NULL, NULL, '任务状态'); +INSERT INTO sys_dict_data VALUES (39, '000000', 1, '已撤销', 'cancel', 'wf_business_status', '', 'danger', 'N', 103, 1, SYSDATE, NULL, NULL, '已撤销'); +INSERT INTO sys_dict_data VALUES (40, '000000', 2, '草稿', 'draft', 'wf_business_status', '', 'info', 'N', 103, 1, SYSDATE, NULL, NULL, '草稿'); +INSERT INTO sys_dict_data VALUES (41, '000000', 3, '待审核', 'waiting', 'wf_business_status', '', 'primary', 'N', 103, 1, SYSDATE, NULL, NULL, '待审核'); +INSERT INTO sys_dict_data VALUES (42, '000000', 4, '已完成', 'finish', 'wf_business_status', '', 'success', 'N', 103, 1, SYSDATE, NULL, NULL, '已完成'); +INSERT INTO sys_dict_data VALUES (43, '000000', 5, '已作废', 'invalid', 'wf_business_status', '', 'danger', 'N', 103, 1, SYSDATE, NULL, NULL, '已作废'); +INSERT INTO sys_dict_data VALUES (44, '000000', 6, '已退回', 'back', 'wf_business_status', '', 'danger', 'N', 103, 1, SYSDATE, NULL, NULL, '已退回'); +INSERT INTO sys_dict_data VALUES (45, '000000', 7, '已终止', 'termination', 'wf_business_status', '', 'danger', 'N', 103, 1, SYSDATE, NULL, NULL, '已终止'); +INSERT INTO sys_dict_data VALUES (46, '000000', 1, '自定义表单', 'static', 'wf_form_type', '', 'success', 'N', 103, 1, SYSDATE, NULL, NULL, '自定义表单'); +INSERT INTO sys_dict_data VALUES (47, '000000', 2, '动态表单', 'dynamic', 'wf_form_type', '', 'primary', 'N', 103, 1, SYSDATE, NULL, NULL, '动态表单'); +INSERT INTO sys_dict_data VALUES (48, '000000', 1, '撤销', 'cancel', 'wf_task_status', '', 'danger', 'N', 103, 1, SYSDATE, NULL, NULL, '撤销'); +INSERT INTO sys_dict_data VALUES (49, '000000', 2, '通过', 'pass', 'wf_task_status', '', 'success', 'N', 103, 1, SYSDATE, NULL, NULL, '通过'); +INSERT INTO sys_dict_data VALUES (50, '000000', 3, '待审核', 'waiting', 'wf_task_status', '', 'primary', 'N', 103, 1, SYSDATE, NULL, NULL, '待审核'); +INSERT INTO sys_dict_data VALUES (51, '000000', 4, '作废', 'invalid', 'wf_task_status', '', 'danger', 'N', 103, 1, SYSDATE, NULL, NULL, '作废'); +INSERT INTO sys_dict_data VALUES (52, '000000', 5, '退回', 'back', 'wf_task_status', '', 'danger', 'N', 103, 1, SYSDATE, NULL, NULL, '退回'); +INSERT INTO sys_dict_data VALUES (53, '000000', 6, '终止', 'termination', 'wf_task_status', '', 'danger', 'N', 103, 1, SYSDATE, NULL, NULL, '终止'); +INSERT INTO sys_dict_data VALUES (54, '000000', 7, '转办', 'transfer', 'wf_task_status', '', 'primary', 'N', 103, 1, SYSDATE, NULL, NULL, '转办'); +INSERT INTO sys_dict_data VALUES (55, '000000', 8, '委托', 'depute', 'wf_task_status', '', 'primary', 'N', 103, 1, SYSDATE, NULL, NULL, '委托'); +INSERT INTO sys_dict_data VALUES (56, '000000', 9, '抄送', 'copy', 'wf_task_status', '', 'primary', 'N', 103, 1, SYSDATE, NULL, NULL, '抄送'); +INSERT INTO sys_dict_data VALUES (57, '000000', 10, '加签', 'sign', 'wf_task_status', '', 'primary', 'N', 103, 1, SYSDATE, NULL, NULL, '加签'); +INSERT INTO sys_dict_data VALUES (58, '000000', 11, '减签', 'sign_off', 'wf_task_status', '', 'danger', 'N', 103, 1, SYSDATE, NULL, NULL, '减签'); +INSERT INTO sys_dict_data VALUES (59, '000000', 11, '超时', 'timeout', 'wf_task_status', '', 'danger', 'N', 103, 1, SYSDATE, NULL, NULL, '超时'); diff --git a/script/sql/postgres/postgres_ry_job.sql b/script/sql/postgres/postgres_ry_job.sql index 546db3cc8..1a08a9990 100644 --- a/script/sql/postgres/postgres_ry_job.sql +++ b/script/sql/postgres/postgres_ry_job.sql @@ -2,7 +2,7 @@ SnailJob Database Transfer Tool Source Server Type : MySQL Target Server Type : PostgreSQL - Date: 2024-07-06 11:45:40 + Date: 2024-12-27 22:13:49 */ @@ -76,7 +76,7 @@ CREATE TABLE sj_notify_config id bigserial PRIMARY KEY, namespace_id varchar(64) NOT NULL DEFAULT '764d604ec6fc45f68cd92514c40e9e1a', group_name varchar(64) NOT NULL, - business_id varchar(64) NOT NULL, + notify_name varchar(64) NOT NULL DEFAULT '', system_task_type smallint NOT NULL DEFAULT 3, notify_status smallint NOT NULL DEFAULT 0, recipient_ids varchar(128) NOT NULL, @@ -89,12 +89,12 @@ CREATE TABLE sj_notify_config update_dt timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ); -CREATE INDEX idx_sj_notify_config_01 ON sj_notify_config (namespace_id, group_name, business_id); +CREATE INDEX idx_sj_notify_config_01 ON sj_notify_config (namespace_id, group_name); COMMENT ON COLUMN sj_notify_config.id IS '主键'; COMMENT ON COLUMN sj_notify_config.namespace_id IS '命名空间id'; COMMENT ON COLUMN sj_notify_config.group_name IS '组名称'; -COMMENT ON COLUMN sj_notify_config.business_id IS '业务id ( job_id或workflow_id或scene_name ) '; +COMMENT ON COLUMN sj_notify_config.notify_name IS '通知名称'; COMMENT ON COLUMN sj_notify_config.system_task_type IS '任务类型 1. 重试任务 2. 重试回调 3、JOB任务 4、WORKFLOW任务'; COMMENT ON COLUMN sj_notify_config.notify_status IS '通知状态 0、未启用 1、启用'; COMMENT ON COLUMN sj_notify_config.recipient_ids IS '接收人id列表'; @@ -297,6 +297,7 @@ CREATE TABLE sj_retry_scene_config max_retry_count int NOT NULL DEFAULT 5, back_off smallint NOT NULL DEFAULT 1, trigger_interval varchar(16) NOT NULL DEFAULT '', + notify_ids varchar(128) NOT NULL DEFAULT '', deadline_request bigint NOT NULL DEFAULT 60000, executor_timeout int NOT NULL DEFAULT 5, route_key smallint NOT NULL DEFAULT 4, @@ -315,6 +316,7 @@ COMMENT ON COLUMN sj_retry_scene_config.scene_status IS '组状态 0、未启用 COMMENT ON COLUMN sj_retry_scene_config.max_retry_count IS '最大重试次数'; COMMENT ON COLUMN sj_retry_scene_config.back_off IS '1、默认等级 2、固定间隔时间 3、CRON 表达式'; COMMENT ON COLUMN sj_retry_scene_config.trigger_interval IS '间隔时长'; +COMMENT ON COLUMN sj_retry_scene_config.notify_ids IS '通知告警场景配置id列表'; COMMENT ON COLUMN sj_retry_scene_config.deadline_request IS 'Deadline Request 调用链超时 单位毫秒'; COMMENT ON COLUMN sj_retry_scene_config.executor_timeout IS '任务执行超时时间,单位秒'; COMMENT ON COLUMN sj_retry_scene_config.route_key IS '路由策略'; @@ -464,6 +466,8 @@ CREATE TABLE sj_job retry_interval int NOT NULL DEFAULT 0, bucket_index int NOT NULL DEFAULT 0, resident smallint NOT NULL DEFAULT 0, + notify_ids varchar(128) NOT NULL DEFAULT '', + owner_id bigint NULL, description varchar(256) NOT NULL DEFAULT '', ext_attrs varchar(256) NULL DEFAULT '', deleted smallint NOT NULL DEFAULT 0, @@ -496,6 +500,8 @@ COMMENT ON COLUMN sj_job.parallel_num IS '并行数'; COMMENT ON COLUMN sj_job.retry_interval IS '重试间隔 ( s ) '; COMMENT ON COLUMN sj_job.bucket_index IS 'bucket'; COMMENT ON COLUMN sj_job.resident IS '是否是常驻任务'; +COMMENT ON COLUMN sj_job.notify_ids IS '通知告警场景配置id列表'; +COMMENT ON COLUMN sj_job.owner_id IS '负责人id'; COMMENT ON COLUMN sj_job.description IS '描述'; COMMENT ON COLUMN sj_job.ext_attrs IS '扩展字段'; COMMENT ON COLUMN sj_job.deleted IS '逻辑删除 1、删除'; @@ -503,7 +509,7 @@ COMMENT ON COLUMN sj_job.create_dt IS '创建时间'; COMMENT ON COLUMN sj_job.update_dt IS '修改时间'; COMMENT ON TABLE sj_job IS '任务信息'; -INSERT INTO sj_job VALUES (1, 'dev', 'ruoyi_group', 'demo-job', null, 1, 1710344035622, 1, 1, 4, 1, 'testJobExecutor', 2, '60', 1, 60, 3, 1, 1, 116, 0, '', '', 0, now(), now()); +INSERT INTO sj_job VALUES (1, 'dev', 'ruoyi_group', 'demo-job', null, 1, 1710344035622, 1, 1, 4, 1, 'testJobExecutor', 2, '60', 1, 60, 3, 1, 1, 116, 0, '', 1, '', '', 0, now(), now()); -- sj_job_log_message CREATE TABLE sj_job_log_message @@ -721,6 +727,7 @@ CREATE TABLE sj_workflow description varchar(256) NOT NULL DEFAULT '', flow_info text NULL DEFAULT NULL, wf_context text NULL DEFAULT NULL, + notify_ids varchar(128) NOT NULL DEFAULT '', bucket_index int NOT NULL DEFAULT 0, version int NOT NULL, ext_attrs varchar(256) NULL DEFAULT '', @@ -745,6 +752,7 @@ COMMENT ON COLUMN sj_workflow.executor_timeout IS '任务执行超时时间, COMMENT ON COLUMN sj_workflow.description IS '描述'; COMMENT ON COLUMN sj_workflow.flow_info IS '流程信息'; COMMENT ON COLUMN sj_workflow.wf_context IS '上下文'; +COMMENT ON COLUMN sj_workflow.notify_ids IS '通知告警场景配置id列表'; COMMENT ON COLUMN sj_workflow.bucket_index IS 'bucket'; COMMENT ON COLUMN sj_workflow.version IS '版本号'; COMMENT ON COLUMN sj_workflow.ext_attrs IS '扩展字段'; diff --git a/script/sql/postgres/postgres_ry_vue_5.X.sql b/script/sql/postgres/postgres_ry_vue_5.X.sql index fabea6048..b3499e89f 100644 --- a/script/sql/postgres/postgres_ry_vue_5.X.sql +++ b/script/sql/postgres/postgres_ry_vue_5.X.sql @@ -5,7 +5,7 @@ create table sys_social ( id int8 not null, user_id int8 not null, - tenant_id varchar(20) default null::varchar, + tenant_id varchar(20) default '000000'::varchar, auth_id varchar(255) not null, source varchar(255) not null, open_id varchar(255) default null::varchar, @@ -64,7 +64,7 @@ comment on column sys_social.create_by is '创建者'; comment on column sys_social.create_time is '创建时间'; comment on column sys_social.update_by is '更新者'; comment on column sys_social.update_time is '更新时间'; -comment on column sys_social.del_flag is '删除标志(0代表存在 2代表删除)'; +comment on column sys_social.del_flag is '删除标志(0代表存在 1代表删除)'; -- ---------------------------- -- 租户表 @@ -109,7 +109,7 @@ comment on column sys_tenant.package_id is '租户套餐编号'; comment on column sys_tenant.expire_time is '过期时间'; comment on column sys_tenant.account_count is '用户数量(-1不限制)'; comment on column sys_tenant.status is '租户状态(0正常 1停用)'; -comment on column sys_tenant.del_flag is '删除标志(0代表存在 2代表删除)'; +comment on column sys_tenant.del_flag is '删除标志(0代表存在 1代表删除)'; comment on column sys_tenant.create_dept is '创建部门'; comment on column sys_tenant.create_by is '创建者'; comment on column sys_tenant.create_time is '创建时间'; @@ -151,7 +151,7 @@ comment on column sys_tenant_package.package_name is '套餐名称'; comment on column sys_tenant_package.menu_ids is '关联菜单id'; comment on column sys_tenant_package.remark is '备注'; comment on column sys_tenant_package.status is '状态(0正常 1停用)'; -comment on column sys_tenant_package.del_flag is '删除标志(0代表存在 2代表删除)'; +comment on column sys_tenant_package.del_flag is '删除标志(0代表存在 1代表删除)'; comment on column sys_tenant_package.create_dept is '创建部门'; comment on column sys_tenant_package.create_by is '创建者'; comment on column sys_tenant_package.create_time is '创建时间'; @@ -196,7 +196,7 @@ comment on column sys_dept.leader is '负责人'; comment on column sys_dept.phone is '联系电话'; comment on column sys_dept.email is '邮箱'; comment on column sys_dept.status is '部门状态(0正常 1停用)'; -comment on column sys_dept.del_flag is '删除标志(0代表存在 2代表删除)'; +comment on column sys_dept.del_flag is '删除标志(0代表存在 1代表删除)'; comment on column sys_dept.create_dept is '创建部门'; comment on column sys_dept.create_by is '创建者'; comment on column sys_dept.create_time is '创建时间'; @@ -259,7 +259,7 @@ comment on column sys_user.sex is '用户性别(0男 1女 2未知)' comment on column sys_user.avatar is '头像地址'; comment on column sys_user.password is '密码'; comment on column sys_user.status is '帐号状态(0正常 1停用)'; -comment on column sys_user.del_flag is '删除标志(0代表存在 2代表删除)'; +comment on column sys_user.del_flag is '删除标志(0代表存在 1代表删除)'; comment on column sys_user.login_ip is '最后登陆IP'; comment on column sys_user.login_date is '最后登陆时间'; comment on column sys_user.create_dept is '创建部门'; @@ -357,7 +357,7 @@ comment on column sys_role.data_scope is '数据范围(1:全部数 comment on column sys_role.menu_check_strictly is '菜单树选择项是否关联显示'; comment on column sys_role.dept_check_strictly is '部门树选择项是否关联显示'; comment on column sys_role.status is '角色状态(0正常 1停用)'; -comment on column sys_role.del_flag is '删除标志(0代表存在 2代表删除)'; +comment on column sys_role.del_flag is '删除标志(0代表存在 1代表删除)'; comment on column sys_role.create_dept is '创建部门'; comment on column sys_role.create_by is '创建者'; comment on column sys_role.create_time is '创建时间'; @@ -741,10 +741,10 @@ create table if not exists sys_oper_log oper_url varchar(255) default ''::varchar, oper_ip varchar(128) default ''::varchar, oper_location varchar(255) default ''::varchar, - oper_param varchar(2000) default ''::varchar, - json_result varchar(2000) default ''::varchar, + oper_param varchar(4000) default ''::varchar, + json_result varchar(4000) default ''::varchar, status int4 default 0, - error_msg varchar(2000) default ''::varchar, + error_msg varchar(4000) default ''::varchar, oper_time timestamp, cost_time int8 default 0, constraint sys_oper_log_pk primary key (oper_id) @@ -1209,7 +1209,7 @@ comment on column sys_oss_config.remark is '备注'; insert into sys_oss_config values (1, '000000', 'minio', 'ruoyi', 'ruoyi123', 'ruoyi', '', '127.0.0.1:9000', '','N', '', '1', '0', '', 103, 1, now(), 1, now(), null); insert into sys_oss_config values (2, '000000', 'qiniu', 'XXXXXXXXXXXXXXX', 'XXXXXXXXXXXXXXX', 'ruoyi', '', 's3-cn-north-1.qiniucs.com', '','N', '', '1', '1', '', 103, 1, now(), 1, now(), null); insert into sys_oss_config values (3, '000000', 'aliyun', 'XXXXXXXXXXXXXXX', 'XXXXXXXXXXXXXXX', 'ruoyi', '', 'oss-cn-beijing.aliyuncs.com', '','N', '', '1', '1', '', 103, 1, now(), 1, now(), null); -insert into sys_oss_config values (4, '000000', 'qcloud', 'XXXXXXXXXXXXXXX', 'XXXXXXXXXXXXXXX', 'ruoyi-1250000000', '', 'cos.ap-beijing.myqcloud.com', '','N', 'ap-beijing', '1', '1', '', 103, 1, now(), 1, now(), null); +insert into sys_oss_config values (4, '000000', 'qcloud', 'XXXXXXXXXXXXXXX', 'XXXXXXXXXXXXXXX', 'ruoyi-1240000000', '', 'cos.ap-beijing.myqcloud.com', '','N', 'ap-beijing', '1', '1', '', 103, 1, now(), 1, now(), null); insert into sys_oss_config values (5, '000000', 'image', 'ruoyi', 'ruoyi123', 'ruoyi', 'image', '127.0.0.1:9000', '','N', '', '1', '1', '', 103, 1, now(), 1, now(), NULL); -- ---------------------------- @@ -1244,7 +1244,7 @@ comment on column sys_client.device_type is '设备类型'; comment on column sys_client.active_timeout is 'token活跃超时时间'; comment on column sys_client.timeout is 'token固定超时'; comment on column sys_client.status is '状态(0正常 1停用)'; -comment on column sys_client.del_flag is '删除标志(0代表存在 2代表删除)'; +comment on column sys_client.del_flag is '删除标志(0代表存在 1代表删除)'; comment on column sys_client.create_dept is '创建部门'; comment on column sys_client.create_by is '创建者'; comment on column sys_client.create_time is '创建时间'; diff --git a/script/sql/postgres/postgres_ry_workflow.sql b/script/sql/postgres/postgres_ry_workflow.sql index 8a6078d07..9bcf2cf17 100644 --- a/script/sql/postgres/postgres_ry_workflow.sql +++ b/script/sql/postgres/postgres_ry_workflow.sql @@ -1,275 +1,403 @@ -insert into sys_menu values('11616', '工作流' , '0', '6', 'workflow', '', '', '1', '0', 'M', '0', '0', '', 'workflow', 103, 1, now(), NULL, NULL, ''); -insert into sys_menu values('11617', '模型管理', '11616', '2', 'model', 'workflow/model/index', '', '1', '1', 'C', '0', '0', 'workflow:model:list', 'model', 103, 1, now(), NULL, NULL, ''); -insert into sys_menu values('11618', '我的任务', '0', '7', 'task', '', '', '1', '0', 'M', '0', '0', '', 'my-task', 103, 1, now(), NULL, NULL, ''); -insert into sys_menu values('11619', '我的待办', '11618', '2', 'taskWaiting', 'workflow/task/taskWaiting', '', '1', '1', 'C', '0', '0', '', 'waiting', 103, 1, now(), NULL, NULL, ''); -insert into sys_menu values('11632', '我的已办', '11618', '3', 'taskFinish', 'workflow/task/taskFinish', '', '1', '1', 'C', '0', '0', '', 'finish', 103, 1, now(), NULL, NULL, ''); -insert into sys_menu values('11633', '我的抄送', '11618', '4', 'taskCopyList', 'workflow/task/taskCopyList', '', '1', '1', 'C', '0', '0', '', 'my-copy', 103, 1, now(), NULL, NULL, ''); -insert into sys_menu values('11620', '流程定义', '11616', '3', 'processDefinition', 'workflow/processDefinition/index', '', '1', '1', 'C', '0', '0', '', 'process-definition', 103, 1, now(), NULL, NULL, ''); -insert into sys_menu values('11621', '流程实例', '11630', '1', 'processInstance', 'workflow/processInstance/index', '', '1', '1', 'C', '0', '0', '', 'tree-table', 103, 1, now(), NULL, NULL, ''); -insert into sys_menu values('11622', '流程分类', '11616', '1', 'category', 'workflow/category/index', '', '1', '0', 'C', '0', '0', 'workflow:category:list', 'category', 103, 1, now(), NULL, NULL, ''); -insert into sys_menu values('11629', '我发起的', '11618', '1', 'myDocument', 'workflow/task/myDocument', '', '1', '1', 'C', '0', '0', '', 'guide', 103, 1, now(), NULL, NULL, ''); -insert into sys_menu values('11630', '流程监控', '11616', '4', 'monitor', '', '', '1', '0', 'M', '0', '0', '', 'monitor', 103, 1, now(), NULL, NULL, ''); -insert into sys_menu values('11631', '待办任务', '11630', '2', 'allTaskWaiting', 'workflow/task/allTaskWaiting', '', '1', '1', 'C', '0', '0', '', 'waiting', 103, 1, now(), NULL, NULL, ''); +-- ---------------------------- +-- 0、warm-flow-all.sql,地址:https://gitee.com/dromara/warm-flow/blob/master/sql/postgresql/postgresql-warm-flow-all.sql +-- ---------------------------- +CREATE TABLE flow_definition +( + id int8 NOT NULL, -- 主键id + flow_code varchar(40) NOT NULL, -- 流程编码 + flow_name varchar(100) NOT NULL, -- 流程名称 + category varchar(100) NULL, -- 流程类别 + "version" varchar(20) NOT NULL, -- 流程版本 + is_publish int2 NOT NULL DEFAULT 0, -- 是否发布(0未发布 1已发布 9失效) + form_custom bpchar(1) NULL DEFAULT 'N':: character varying, -- 审批表单是否自定义(Y是 N否) + form_path varchar(100) NULL, -- 审批表单路径 + activity_status int2 NOT NULL DEFAULT 1, -- 流程激活状态(0挂起 1激活) + listener_type varchar(100) NULL, -- 监听器类型 + listener_path varchar(400) NULL, -- 监听器路径 + ext varchar(500) NULL, -- 扩展字段,预留给业务系统使用 + create_time timestamp NULL, -- 创建时间 + update_time timestamp NULL, -- 更新时间 + del_flag bpchar(1) NULL DEFAULT '0':: character varying, -- 删除标志 + tenant_id varchar(40) NULL, -- 租户id + CONSTRAINT flow_definition_pkey PRIMARY KEY (id) +); +COMMENT ON TABLE flow_definition IS '流程定义表'; + +COMMENT ON COLUMN flow_definition.id IS '主键id'; +COMMENT ON COLUMN flow_definition.flow_code IS '流程编码'; +COMMENT ON COLUMN flow_definition.flow_name IS '流程名称'; +COMMENT ON COLUMN flow_definition.category IS '流程类别'; +COMMENT ON COLUMN flow_definition."version" IS '流程版本'; +COMMENT ON COLUMN flow_definition.is_publish IS '是否发布(0未发布 1已发布 9失效)'; +COMMENT ON COLUMN flow_definition.form_custom IS '审批表单是否自定义(Y是 N否)'; +COMMENT ON COLUMN flow_definition.form_path IS '审批表单路径'; +COMMENT ON COLUMN flow_definition.activity_status IS '流程激活状态(0挂起 1激活)'; +COMMENT ON COLUMN flow_definition.listener_type IS '监听器类型'; +COMMENT ON COLUMN flow_definition.listener_path IS '监听器路径'; +COMMENT ON COLUMN flow_definition.ext IS '扩展字段,预留给业务系统使用'; +COMMENT ON COLUMN flow_definition.create_time IS '创建时间'; +COMMENT ON COLUMN flow_definition.update_time IS '更新时间'; +COMMENT ON COLUMN flow_definition.del_flag IS '删除标志'; +COMMENT ON COLUMN flow_definition.tenant_id IS '租户id'; + +CREATE TABLE flow_node +( + id int8 NOT NULL, -- 主键id + node_type int2 NOT NULL, -- 节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关) + definition_id int8 NOT NULL, -- 流程定义id + node_code varchar(100) NOT NULL, -- 流程节点编码 + node_name varchar(100) NULL, -- 流程节点名称 + permission_flag varchar(200) NULL, -- 权限标识(权限类型:权限标识,可以多个,用逗号隔开) + node_ratio numeric(6, 3) NULL, -- 流程签署比例值 + coordinate varchar(100) NULL, -- 坐标 + skip_any_node varchar(100) NULL DEFAULT 'N':: character varying, -- 是否可以退回任意节点(Y是 N否)即将删除 + any_node_skip varchar(100) NULL, -- 任意结点跳转 + listener_type varchar(100) NULL, -- 监听器类型 + listener_path varchar(400) NULL, -- 监听器路径 + handler_type varchar(100) NULL, -- 处理器类型 + handler_path varchar(400) NULL, -- 处理器路径 + form_custom bpchar(1) NULL DEFAULT 'N':: character varying, -- 审批表单是否自定义(Y是 N否) + form_path varchar(100) NULL, -- 审批表单路径 + "version" varchar(20) NOT NULL, -- 版本 + create_time timestamp NULL, -- 创建时间 + update_time timestamp NULL, -- 更新时间 + del_flag bpchar(1) NULL DEFAULT '0':: character varying, -- 删除标志 + tenant_id varchar(40) NULL, -- 租户id + CONSTRAINT flow_node_pkey PRIMARY KEY (id) +); +COMMENT ON TABLE flow_node IS '流程节点表'; + +COMMENT ON COLUMN flow_node.id IS '主键id'; +COMMENT ON COLUMN flow_node.node_type IS '节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)'; +COMMENT ON COLUMN flow_node.definition_id IS '流程定义id'; +COMMENT ON COLUMN flow_node.node_code IS '流程节点编码'; +COMMENT ON COLUMN flow_node.node_name IS '流程节点名称'; +COMMENT ON COLUMN flow_node.permission_flag IS '权限标识(权限类型:权限标识,可以多个,用逗号隔开)'; +COMMENT ON COLUMN flow_node.node_ratio IS '流程签署比例值'; +COMMENT ON COLUMN flow_node.coordinate IS '坐标'; +COMMENT ON COLUMN flow_node.skip_any_node IS '是否可以退回任意节点(Y是 N否)即将删除'; +COMMENT ON COLUMN flow_node.any_node_skip IS '任意结点跳转'; +COMMENT ON COLUMN flow_node.listener_type IS '监听器类型'; +COMMENT ON COLUMN flow_node.listener_path IS '监听器路径'; +COMMENT ON COLUMN flow_node.handler_type IS '处理器类型'; +COMMENT ON COLUMN flow_node.handler_path IS '处理器路径'; +COMMENT ON COLUMN flow_node.form_custom IS '审批表单是否自定义(Y是 N否)'; +COMMENT ON COLUMN flow_node.form_path IS '审批表单路径'; +COMMENT ON COLUMN flow_node."version" IS '版本'; +COMMENT ON COLUMN flow_node.create_time IS '创建时间'; +COMMENT ON COLUMN flow_node.update_time IS '更新时间'; +COMMENT ON COLUMN flow_node.del_flag IS '删除标志'; +COMMENT ON COLUMN flow_node.tenant_id IS '租户id'; --- 流程分类管理相关按钮 -insert into sys_menu values ('11623', '流程分类查询', '11622', '1', '#', '', '', 1, 0, 'F', '0', '0', 'workflow:category:query', '#', 103, 1, now(), null, null, ''); -insert into sys_menu values ('11624', '流程分类新增', '11622', '2', '#', '', '', 1, 0, 'F', '0', '0', 'workflow:category:add', '#', 103, 1, now(), null, null, ''); -insert into sys_menu values ('11625', '流程分类修改', '11622', '3', '#', '', '', 1, 0, 'F', '0', '0', 'workflow:category:edit', '#', 103, 1, now(), null, null, ''); -insert into sys_menu values ('11626', '流程分类删除', '11622', '4', '#', '', '', 1, 0, 'F', '0', '0', 'workflow:category:remove','#', 103, 1, now(), null, null, ''); -insert into sys_menu values ('11627', '流程分类导出', '11622', '5', '#', '', '', 1, 0, 'F', '0', '0', 'workflow:category:export','#', 103, 1, now(), null, null, ''); +CREATE TABLE flow_skip +( + id int8 NOT NULL, -- 主键id + definition_id int8 NOT NULL, -- 流程定义id + now_node_code varchar(100) NOT NULL, -- 当前流程节点的编码 + now_node_type int2 NULL, -- 当前节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关) + next_node_code varchar(100) NOT NULL, -- 下一个流程节点的编码 + next_node_type int2 NULL, -- 下一个节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关) + skip_name varchar(100) NULL, -- 跳转名称 + skip_type varchar(40) NULL, -- 跳转类型(PASS审批通过 REJECT退回) + skip_condition varchar(200) NULL, -- 跳转条件 + coordinate varchar(100) NULL, -- 坐标 + create_time timestamp NULL, -- 创建时间 + update_time timestamp NULL, -- 更新时间 + del_flag bpchar(1) NULL DEFAULT '0':: character varying, -- 删除标志 + tenant_id varchar(40) NULL, -- 租户id + CONSTRAINT flow_skip_pkey PRIMARY KEY (id) +); +COMMENT ON TABLE flow_skip IS '节点跳转关联表'; + +COMMENT ON COLUMN flow_skip.id IS '主键id'; +COMMENT ON COLUMN flow_skip.definition_id IS '流程定义id'; +COMMENT ON COLUMN flow_skip.now_node_code IS '当前流程节点的编码'; +COMMENT ON COLUMN flow_skip.now_node_type IS '当前节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)'; +COMMENT ON COLUMN flow_skip.next_node_code IS '下一个流程节点的编码'; +COMMENT ON COLUMN flow_skip.next_node_type IS '下一个节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)'; +COMMENT ON COLUMN flow_skip.skip_name IS '跳转名称'; +COMMENT ON COLUMN flow_skip.skip_type IS '跳转类型(PASS审批通过 REJECT退回)'; +COMMENT ON COLUMN flow_skip.skip_condition IS '跳转条件'; +COMMENT ON COLUMN flow_skip.coordinate IS '坐标'; +COMMENT ON COLUMN flow_skip.create_time IS '创建时间'; +COMMENT ON COLUMN flow_skip.update_time IS '更新时间'; +COMMENT ON COLUMN flow_skip.del_flag IS '删除标志'; +COMMENT ON COLUMN flow_skip.tenant_id IS '租户id'; + +CREATE TABLE flow_instance +( + id int8 NOT NULL, -- 主键id + definition_id int8 NOT NULL, -- 对应flow_definition表的id + business_id varchar(40) NOT NULL, -- 业务id + node_type int2 NOT NULL, -- 节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关) + node_code varchar(40) NOT NULL, -- 流程节点编码 + node_name varchar(100) NULL, -- 流程节点名称 + variable text NULL, -- 任务变量 + flow_status varchar(20) NOT NULL, -- 流程状态(0待提交 1审批中 2 审批通过 8已完成 9已退回 10失效) + activity_status int2 NOT NULL DEFAULT 1, -- 流程激活状态(0挂起 1激活) + create_by varchar(64) NULL DEFAULT '':: character varying, -- 创建者 + create_time timestamp NULL, -- 创建时间 + update_time timestamp NULL, -- 更新时间 + ext varchar(500) NULL, -- 扩展字段,预留给业务系统使用 + del_flag bpchar(1) NULL DEFAULT '0':: character varying, -- 删除标志 + tenant_id varchar(40) NULL, -- 租户id + CONSTRAINT flow_instance_pkey PRIMARY KEY (id) +); +COMMENT ON TABLE flow_instance IS '流程实例表'; + +COMMENT ON COLUMN flow_instance.id IS '主键id'; +COMMENT ON COLUMN flow_instance.definition_id IS '对应flow_definition表的id'; +COMMENT ON COLUMN flow_instance.business_id IS '业务id'; +COMMENT ON COLUMN flow_instance.node_type IS '节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)'; +COMMENT ON COLUMN flow_instance.node_code IS '流程节点编码'; +COMMENT ON COLUMN flow_instance.node_name IS '流程节点名称'; +COMMENT ON COLUMN flow_instance.variable IS '任务变量'; +COMMENT ON COLUMN flow_instance.flow_status IS '流程状态(0待提交 1审批中 2 审批通过 3自动通过 4终止 5作废 6撤销 7取回 8已完成 9已退回 10失效)'; +COMMENT ON COLUMN flow_instance.activity_status IS '流程激活状态(0挂起 1激活)'; +COMMENT ON COLUMN flow_instance.create_by IS '创建者'; +COMMENT ON COLUMN flow_instance.create_time IS '创建时间'; +COMMENT ON COLUMN flow_instance.update_time IS '更新时间'; +COMMENT ON COLUMN flow_instance.ext IS '扩展字段,预留给业务系统使用'; +COMMENT ON COLUMN flow_instance.del_flag IS '删除标志'; +COMMENT ON COLUMN flow_instance.tenant_id IS '租户id'; + +CREATE TABLE flow_task +( + id int8 NOT NULL, -- 主键id + definition_id int8 NOT NULL, -- 对应flow_definition表的id + instance_id int8 NOT NULL, -- 对应flow_instance表的id + node_code varchar(100) NOT NULL, -- 节点编码 + node_name varchar(100) NULL, -- 节点名称 + node_type int2 NOT NULL, -- 节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关) + form_custom bpchar(1) NULL DEFAULT 'N':: character varying, -- 审批表单是否自定义(Y是 N否) + form_path varchar(100) NULL, -- 审批表单路径 + create_time timestamp NULL, -- 创建时间 + update_time timestamp NULL, -- 更新时间 + del_flag bpchar(1) NULL DEFAULT '0':: character varying, -- 删除标志 + tenant_id varchar(40) NULL, -- 租户id + CONSTRAINT flow_task_pkey PRIMARY KEY (id) +); +COMMENT ON TABLE flow_task IS '待办任务表'; + +COMMENT ON COLUMN flow_task.id IS '主键id'; +COMMENT ON COLUMN flow_task.definition_id IS '对应flow_definition表的id'; +COMMENT ON COLUMN flow_task.instance_id IS '对应flow_instance表的id'; +COMMENT ON COLUMN flow_task.node_code IS '节点编码'; +COMMENT ON COLUMN flow_task.node_name IS '节点名称'; +COMMENT ON COLUMN flow_task.node_type IS '节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)'; +COMMENT ON COLUMN flow_task.form_custom IS '审批表单是否自定义(Y是 N否)'; +COMMENT ON COLUMN flow_task.form_path IS '审批表单路径'; +COMMENT ON COLUMN flow_task.create_time IS '创建时间'; +COMMENT ON COLUMN flow_task.update_time IS '更新时间'; +COMMENT ON COLUMN flow_task.del_flag IS '删除标志'; +COMMENT ON COLUMN flow_task.tenant_id IS '租户id'; + +CREATE TABLE flow_his_task +( + id int8 NOT NULL, -- 主键id + definition_id int8 NOT NULL, -- 对应flow_definition表的id + instance_id int8 NOT NULL, -- 对应flow_instance表的id + task_id int8 NOT NULL, -- 对应flow_task表的id + node_code varchar(100) NULL, -- 开始节点编码 + node_name varchar(100) NULL, -- 开始节点名称 + node_type int2 NULL, -- 开始节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关) + target_node_code varchar(200) NULL, -- 目标节点编码 + target_node_name varchar(200) NULL, -- 结束节点名称 + approver varchar(40) NULL, -- 审批者 + cooperate_type int2 NOT NULL DEFAULT 0, -- 协作方式(1审批 2转办 3委派 4会签 5票签 6加签 7减签) + collaborator varchar(40) NULL, -- 协作人(只有转办、会签、票签、委派) + skip_type varchar(10) NULL, -- 流转类型(PASS通过 REJECT退回 NONE无动作) + flow_status varchar(20) NOT NULL, -- 流程状态(0待提交 1审批中 2 审批通过 8已完成 9已退回 10失效) + form_custom bpchar(1) NULL DEFAULT 'N':: character varying, -- 审批表单是否自定义(Y是 N否) + form_path varchar(100) NULL, -- 审批表单路径 + ext varchar(500) NULL, -- 扩展字段,预留给业务系统使用 + message varchar(500) NULL, -- 审批意见 + variable text NULL, -- 任务变量 + create_time timestamp NULL, -- 创建时间 + update_time timestamp NULL, -- 更新时间 + del_flag bpchar(1) NULL DEFAULT '0':: character varying, -- 删除标志 + tenant_id varchar(40) NULL, -- 租户id + CONSTRAINT flow_his_task_pkey PRIMARY KEY (id) +); +COMMENT ON TABLE flow_his_task IS '历史任务记录表'; + +COMMENT ON COLUMN flow_his_task.id IS '主键id'; +COMMENT ON COLUMN flow_his_task.definition_id IS '对应flow_definition表的id'; +COMMENT ON COLUMN flow_his_task.instance_id IS '对应flow_instance表的id'; +COMMENT ON COLUMN flow_his_task.task_id IS '对应flow_task表的id'; +COMMENT ON COLUMN flow_his_task.node_code IS '开始节点编码'; +COMMENT ON COLUMN flow_his_task.node_name IS '开始节点名称'; +COMMENT ON COLUMN flow_his_task.node_type IS '开始节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)'; +COMMENT ON COLUMN flow_his_task.target_node_code IS '目标节点编码'; +COMMENT ON COLUMN flow_his_task.target_node_name IS '结束节点名称'; +COMMENT ON COLUMN flow_his_task.approver IS '审批者'; +COMMENT ON COLUMN flow_his_task.cooperate_type IS '协作方式(1审批 2转办 3委派 4会签 5票签 6加签 7减签)'; +COMMENT ON COLUMN flow_his_task.collaborator IS '协作人'; +COMMENT ON COLUMN flow_his_task.skip_type IS '流转类型(PASS通过 REJECT退回 NONE无动作)'; +COMMENT ON COLUMN flow_his_task.flow_status IS '流程状态(1审批中 2 审批通过 9已退回 10失效)'; +COMMENT ON COLUMN flow_his_task.form_custom IS '审批表单是否自定义(Y是 N否)'; +COMMENT ON COLUMN flow_his_task.form_path IS '审批表单路径'; +COMMENT ON COLUMN flow_his_task.message IS '审批意见'; +COMMENT ON COLUMN flow_his_task.variable IS '任务变量'; +COMMENT ON COLUMN flow_his_task.ext IS '扩展字段,预留给业务系统使用'; +COMMENT ON COLUMN flow_his_task.create_time IS '任务开始时间'; +COMMENT ON COLUMN flow_his_task.update_time IS '审批完成时间'; +COMMENT ON COLUMN flow_his_task.del_flag IS '删除标志'; +COMMENT ON COLUMN flow_his_task.tenant_id IS '租户id'; + +CREATE TABLE flow_user +( + id int8 NOT NULL, -- 主键id + "type" bpchar(1) NOT NULL, -- 人员类型(1待办任务的审批人权限 2待办任务的转办人权限 3流程实例的抄送人权限 4待办任务的委托人权限) + processed_by varchar(80) NULL, -- 权限人 + associated int8 NOT NULL, -- 任务表id + create_time timestamp NULL, -- 创建时间 + create_by varchar(80) NULL, -- 创建人 + update_time timestamp NULL, -- 更新时间 + del_flag bpchar(1) NULL DEFAULT '0':: character varying, -- 删除标志 + tenant_id varchar(40) NULL, -- 租户id + CONSTRAINT flow_user_pk PRIMARY KEY (id) +); +CREATE INDEX user_processed_type ON flow_user USING btree (processed_by, type); +COMMENT ON TABLE flow_user IS '流程用户表'; + +COMMENT ON COLUMN flow_user.id IS '主键id'; +COMMENT ON COLUMN flow_user."type" IS '人员类型(1待办任务的审批人权限 2待办任务的转办人权限 3待办任务的委托人权限)'; +COMMENT ON COLUMN flow_user.processed_by IS '权限人'; +COMMENT ON COLUMN flow_user.associated IS '任务表id'; +COMMENT ON COLUMN flow_user.create_time IS '创建时间'; +COMMENT ON COLUMN flow_user.create_by IS '创建人'; +COMMENT ON COLUMN flow_user.update_time IS '更新时间'; +COMMENT ON COLUMN flow_user.del_flag IS '删除标志'; +COMMENT ON COLUMN flow_user.tenant_id IS '租户id'; + +-- ---------------------------- +-- 流程分类表 +-- ---------------------------- +CREATE TABLE flow_category +( + category_id int8 NOT NULL, + tenant_id VARCHAR(20) DEFAULT '000000'::varchar, + parent_id int8 DEFAULT 0, + ancestors VARCHAR(500) DEFAULT ''::varchar, + category_name VARCHAR(30) NOT NULL, + order_num INT DEFAULT 0, + del_flag CHAR DEFAULT '0'::bpchar, + create_dept int8, + create_by int8, + create_time TIMESTAMP, + update_by int8, + update_time TIMESTAMP, + PRIMARY KEY (category_id) +); + +COMMENT ON TABLE flow_category IS '流程分类'; +COMMENT ON COLUMN flow_category.category_id IS '流程分类ID'; +COMMENT ON COLUMN flow_category.tenant_id IS '租户编号'; +COMMENT ON COLUMN flow_category.parent_id IS '父流程分类id'; +COMMENT ON COLUMN flow_category.ancestors IS '祖级列表'; +COMMENT ON COLUMN flow_category.category_name IS '流程分类名称'; +COMMENT ON COLUMN flow_category.order_num IS '显示顺序'; +COMMENT ON COLUMN flow_category.del_flag IS '删除标志(0代表存在 1代表删除)'; +COMMENT ON COLUMN flow_category.create_dept IS '创建部门'; +COMMENT ON COLUMN flow_category.create_by IS '创建者'; +COMMENT ON COLUMN flow_category.create_time IS '创建时间'; +COMMENT ON COLUMN flow_category.update_by IS '更新者'; +COMMENT ON COLUMN flow_category.update_time IS '更新时间'; + +INSERT INTO flow_category VALUES (100, '000000', 0, '0', 'OA审批', 0, '0', 103, 1, now(), NULL, NULL); +INSERT INTO flow_category VALUES (101, '000000', 100, '0,100', '假勤管理', 0, '0', 103, 1, now(), NULL, NULL); +INSERT INTO flow_category VALUES (102, '000000', 100, '0,100', '人事管理', 1, '0', 103, 1, now(), NULL, NULL); +INSERT INTO flow_category VALUES (103, '000000', 101, '0,100,101', '请假', 0, '0', 103, 1, now(), NULL, NULL); +INSERT INTO flow_category VALUES (104, '000000', 101, '0,100,101', '出差', 1, '0', 103, 1, now(), NULL, NULL); +INSERT INTO flow_category VALUES (105, '000000', 101, '0,100,101', '加班', 2, '0', 103, 1, now(), NULL, NULL); +INSERT INTO flow_category VALUES (106, '000000', 101, '0,100,101', '换班', 3, '0', 103, 1, now(), NULL, NULL); +INSERT INTO flow_category VALUES (107, '000000', 101, '0,100,101', '外出', 4, '0', 103, 1, now(), NULL, NULL); +INSERT INTO flow_category VALUES (108, '000000', 102, '0,100,102', '转正', 1, '0', 103, 1, now(), NULL, NULL); +INSERT INTO flow_category VALUES (109, '000000', 102, '0,100,102', '离职', 2, '0', 103, 1, now(), NULL, NULL); + +-- ---------------------------- -- 请假单信息 -create table test_leave +-- ---------------------------- +CREATE TABLE test_leave ( - id bigint not null - constraint test_leave_pk - primary key, - leave_type varchar(255), - start_date timestamp, - end_date timestamp, - leave_days bigint, - remark varchar(255), - status varchar(255), - create_dept bigint, - create_by bigint, - create_time timestamp, - update_by bigint, - update_time timestamp, - tenant_id varchar(20) + id int8 NOT NULL, + tenant_id VARCHAR(20) DEFAULT '000000'::varchar, + leave_type VARCHAR(255) NOT NULL, + start_date TIMESTAMP NOT NULL, + end_date TIMESTAMP NOT NULL, + leave_days int2 NOT NULL, + remark VARCHAR(255), + status VARCHAR(255), + create_dept int8, + create_by int8, + create_time TIMESTAMP, + update_by int8, + update_time TIMESTAMP, + PRIMARY KEY (id) ); -comment on table test_leave is '请假申请表'; -comment on column test_leave.id is '主键'; -comment on column test_leave.leave_type is '请假类型'; -comment on column test_leave.start_date is '开始时间'; -comment on column test_leave.end_date is '结束时间'; -comment on column test_leave.remark is '请假原因'; -comment on column test_leave.status is '状态'; -comment on column test_leave.create_dept is '创建部门'; -comment on column test_leave.create_by is '创建者'; -comment on column test_leave.create_time is '创建时间'; -comment on column test_leave.update_by is '更新者'; -comment on column test_leave.update_time is '更新时间'; -comment on column test_leave.tenant_id is '租户编码'; +COMMENT ON TABLE test_leave IS '请假申请表'; +COMMENT ON COLUMN test_leave.id IS 'id'; +COMMENT ON COLUMN test_leave.tenant_id IS '租户编号'; +COMMENT ON COLUMN test_leave.leave_type IS '请假类型'; +COMMENT ON COLUMN test_leave.start_date IS '开始时间'; +COMMENT ON COLUMN test_leave.end_date IS '结束时间'; +COMMENT ON COLUMN test_leave.leave_days IS '请假天数'; +COMMENT ON COLUMN test_leave.remark IS '请假原因'; +COMMENT ON COLUMN test_leave.status IS '状态'; +COMMENT ON COLUMN test_leave.create_dept IS '创建部门'; +COMMENT ON COLUMN test_leave.create_by IS '创建者'; +COMMENT ON COLUMN test_leave.create_time IS '创建时间'; +COMMENT ON COLUMN test_leave.update_by IS '更新者'; +COMMENT ON COLUMN test_leave.update_time IS '更新时间'; -alter table test_leave - owner to postgres; +INSERT INTO sys_menu VALUES ('11616', '工作流', '0', '6', 'workflow', '', '', '1', '0', 'M', '0', '0', '', 'workflow', 103, 1, now(), NULL, NULL, ''); +INSERT INTO sys_menu VALUES ('11618', '我的任务', '0', '7', 'task', '', '', '1', '0', 'M', '0', '0', '', 'my-task', 103, 1, now(), NULL, NULL, ''); +INSERT INTO sys_menu VALUES ('11619', '我的待办', '11618', '2', 'taskWaiting', 'workflow/task/taskWaiting', '', '1', '1', 'C', '0', '0', '', 'waiting', 103, 1, now(), NULL, NULL, ''); +INSERT INTO sys_menu VALUES ('11632', '我的已办', '11618', '3', 'taskFinish', 'workflow/task/taskFinish', '', '1', '1', 'C', '0', '0', '', 'finish', 103, 1, now(), NULL, NULL, ''); +INSERT INTO sys_menu VALUES ('11633', '我的抄送', '11618', '4', 'taskCopyList', 'workflow/task/taskCopyList', '', '1', '1', 'C', '0', '0', '', 'my-copy', 103, 1, now(), NULL, NULL, ''); +INSERT INTO sys_menu VALUES ('11620', '流程定义', '11616', '3', 'processDefinition', 'workflow/processDefinition/index', '', '1', '1', 'C', '0', '0', '', 'process-definition', 103, 1, now(), NULL, NULL, ''); +INSERT INTO sys_menu VALUES ('11621', '流程实例', '11630', '1', 'processInstance', 'workflow/processInstance/index', '', '1', '1', 'C', '0', '0', '', 'tree-table', 103, 1, now(), NULL, NULL, ''); +INSERT INTO sys_menu VALUES ('11622', '流程分类', '11616', '1', 'category', 'workflow/category/index', '', '1', '0', 'C', '0', '0', 'workflow:category:list', 'category', 103, 1, now(), NULL, NULL, ''); +INSERT INTO sys_menu VALUES ('11629', '我发起的', '11618', '1', 'myDocument', 'workflow/task/myDocument', '', '1', '1', 'C', '0', '0', '', 'guide', 103, 1, now(), NULL, NULL, ''); +INSERT INTO sys_menu VALUES ('11630', '流程监控', '11616', '4', 'monitor', '', '', '1', '0', 'M', '0', '0', '', 'monitor', 103, 1, now(), NULL, NULL, ''); +INSERT INTO sys_menu VALUES ('11631', '待办任务', '11630', '2', 'allTaskWaiting', 'workflow/task/allTaskWaiting', '', '1', '1', 'C', '0', '0', '', 'waiting', 103, 1, now(), NULL, NULL, ''); +INSERT INTO sys_menu VALUES ('11623', '流程分类查询', '11622', '1', '#', '', '', '1', '0', 'F', '0', '0', 'workflow:category:query', '#', 103, 1, now(), NULL, NULL, ''); +INSERT INTO sys_menu VALUES ('11624', '流程分类新增', '11622', '2', '#', '', '', '1', '0', 'F', '0', '0', 'workflow:category:add', '#', 103, 1, now(), NULL, NULL, ''); +INSERT INTO sys_menu VALUES ('11625', '流程分类修改', '11622', '3', '#', '', '', '1', '0', 'F', '0', '0', 'workflow:category:edit', '#', 103, 1, now(), NULL, NULL, ''); +INSERT INTO sys_menu VALUES ('11626', '流程分类删除', '11622', '4', '#', '', '', '1', '0', 'F', '0', '0', 'workflow:category:remove', '#', 103, 1, now(), NULL, NULL, ''); +INSERT INTO sys_menu VALUES ('11627', '流程分类导出', '11622', '5', '#', '', '', '1', '0', 'F', '0', '0', 'workflow:category:export', '#', 103, 1, now(), NULL, NULL, ''); +INSERT INTO sys_menu VALUES ('11638', '请假申请', '5', '1', 'leave', 'workflow/leave/index', '', '1', '0', 'C', '0', '0', 'workflow:leave:list', '#', 103, 1, now(), NULL, NULL, '请假申请菜单'); +INSERT INTO sys_menu VALUES ('11639', '请假申请查询', '11638', '1', '#', '', '', '1', '0', 'F', '0', '0', 'workflow:leave:query', '#', 103, 1, now(), NULL, NULL, ''); +INSERT INTO sys_menu VALUES ('11640', '请假申请新增', '11638', '2', '#', '', '', '1', '0', 'F', '0', '0', 'workflow:leave:add', '#', 103, 1, now(), NULL, NULL, ''); +INSERT INTO sys_menu VALUES ('11641', '请假申请修改', '11638', '3', '#', '', '', '1', '0', 'F', '0', '0', 'workflow:leave:edit', '#', 103, 1, now(), NULL, NULL, ''); +INSERT INTO sys_menu VALUES ('11642', '请假申请删除', '11638', '4', '#', '', '', '1', '0', 'F', '0', '0', 'workflow:leave:remove', '#', 103, 1, now(), NULL, NULL, ''); +INSERT INTO sys_menu VALUES ('11643', '请假申请导出', '11638', '5', '#', '', '', '1', '0', 'F', '0', '0', 'workflow:leave:export', '#', 103, 1, now(), NULL, NULL, ''); --- 流程分类信息表 -create table wf_category -( - id bigint not null - constraint wf_category_pk - primary key, - category_name varchar(255), - category_code varchar(255), - parent_id bigint, - sort_num bigint, - tenant_id varchar(20), - create_dept bigint, - create_by bigint, - create_time timestamp, - update_by bigint, - update_time timestamp -); +INSERT INTO sys_dict_type VALUES (13, '000000', '业务状态', 'wf_business_status', 103, 1, now(), NULL, NULL, '业务状态列表'); +INSERT INTO sys_dict_type VALUES (14, '000000', '表单类型', 'wf_form_type', 103, 1, now(), NULL, NULL, '表单类型列表'); +INSERT INTO sys_dict_type VALUES (15, '000000', '任务状态', 'wf_task_status', 103, 1, now(), NULL, NULL, '任务状态'); +INSERT INTO sys_dict_data VALUES (39, '000000', 1, '已撤销', 'cancel', 'wf_business_status', '', 'danger', 'N', 103, 1, now(), NULL, NULL, '已撤销'); +INSERT INTO sys_dict_data VALUES (40, '000000', 2, '草稿', 'draft', 'wf_business_status', '', 'info', 'N', 103, 1, now(), NULL, NULL, '草稿'); +INSERT INTO sys_dict_data VALUES (41, '000000', 3, '待审核', 'waiting', 'wf_business_status', '', 'primary', 'N', 103, 1, now(), NULL, NULL, '待审核'); +INSERT INTO sys_dict_data VALUES (42, '000000', 4, '已完成', 'finish', 'wf_business_status', '', 'success', 'N', 103, 1, now(), NULL, NULL, '已完成'); +INSERT INTO sys_dict_data VALUES (43, '000000', 5, '已作废', 'invalid', 'wf_business_status', '', 'danger', 'N', 103, 1, now(), NULL, NULL, '已作废'); +INSERT INTO sys_dict_data VALUES (44, '000000', 6, '已退回', 'back', 'wf_business_status', '', 'danger', 'N', 103, 1, now(), NULL, NULL, '已退回'); +INSERT INTO sys_dict_data VALUES (45, '000000', 7, '已终止', 'termination', 'wf_business_status', '', 'danger', 'N', 103, 1, now(), NULL, NULL, '已终止'); +INSERT INTO sys_dict_data VALUES (46, '000000', 1, '自定义表单', 'static', 'wf_form_type', '', 'success', 'N', 103, 1, now(), NULL, NULL, '自定义表单'); +INSERT INTO sys_dict_data VALUES (47, '000000', 2, '动态表单', 'dynamic', 'wf_form_type', '', 'primary', 'N', 103, 1, now(), NULL, NULL, '动态表单'); +INSERT INTO sys_dict_data VALUES (48, '000000', 1, '撤销', 'cancel', 'wf_task_status', '', 'danger', 'N', 103, 1, now(), NULL, NULL, '撤销'); +INSERT INTO sys_dict_data VALUES (49, '000000', 2, '通过', 'pass', 'wf_task_status', '', 'success', 'N', 103, 1, now(), NULL, NULL, '通过'); +INSERT INTO sys_dict_data VALUES (50, '000000', 3, '待审核', 'waiting', 'wf_task_status', '', 'primary', 'N', 103, 1, now(), NULL, NULL, '待审核'); +INSERT INTO sys_dict_data VALUES (51, '000000', 4, '作废', 'invalid', 'wf_task_status', '', 'danger', 'N', 103, 1, now(), NULL, NULL, '作废'); +INSERT INTO sys_dict_data VALUES (52, '000000', 5, '退回', 'back', 'wf_task_status', '', 'danger', 'N', 103, 1, now(), NULL, NULL, '退回'); +INSERT INTO sys_dict_data VALUES (53, '000000', 6, '终止', 'termination', 'wf_task_status', '', 'danger', 'N', 103, 1, now(), NULL, NULL, '终止'); +INSERT INTO sys_dict_data VALUES (54, '000000', 7, '转办', 'transfer', 'wf_task_status', '', 'primary', 'N', 103, 1, now(), NULL, NULL, '转办'); +INSERT INTO sys_dict_data VALUES (55, '000000', 8, '委托', 'depute', 'wf_task_status', '', 'primary', 'N', 103, 1, now(), NULL, NULL, '委托'); +INSERT INTO sys_dict_data VALUES (56, '000000', 9, '抄送', 'copy', 'wf_task_status', '', 'primary', 'N', 103, 1, now(), NULL, NULL, '抄送'); +INSERT INTO sys_dict_data VALUES (57, '000000', 10, '加签', 'sign', 'wf_task_status', '', 'primary', 'N', 103, 1, now(), NULL, NULL, '加签'); +INSERT INTO sys_dict_data VALUES (58, '000000', 11, '减签', 'sign_off', 'wf_task_status', '', 'danger', 'N', 103, 1, now(), NULL, NULL, '减签'); +INSERT INTO sys_dict_data VALUES (59, '000000', 11, '超时', 'timeout', 'wf_task_status', '', 'danger', 'N', 103, 1, now(), NULL, NULL, '超时'); -comment on table wf_category is '流程分类'; -comment on column wf_category.id is '主键'; -comment on column wf_category.category_name is '分类名称'; -comment on column wf_category.category_code is '分类编码'; -comment on column wf_category.parent_id is '父级id'; -comment on column wf_category.sort_num is '排序'; -comment on column wf_category.tenant_id is '租户id'; -comment on column wf_category.create_dept is '创建部门'; -comment on column wf_category.create_by is '创建者'; -comment on column wf_category.create_time is '创建时间'; -comment on column wf_category.update_by is '修改者'; -comment on column wf_category.update_time is '修改时间'; - -alter table wf_category - owner to postgres; - -create unique index uni_category_code - on wf_category (category_code); - -INSERT INTO wf_category values (1, 'OA', 'OA', 0, 0, '000000', 103, 1, now(), 1, now()); - -create table wf_task_back_node -( - id bigint not null - constraint pk_wf_task_back_node - primary key, - node_id varchar(255) not null, - node_name varchar(255) not null, - order_no bigint not null, - instance_id varchar(255) not null, - task_type varchar(255) not null, - assignee varchar(2000) not null, - tenant_id varchar(20), - create_dept bigint, - create_by bigint, - create_time timestamp, - update_by bigint, - update_time timestamp -); - -comment on table wf_task_back_node is '节点审批记录'; -comment on column wf_task_back_node.id is '主键'; -comment on column wf_task_back_node.node_id is '节点id'; -comment on column wf_task_back_node.node_name is '节点名称'; -comment on column wf_task_back_node.order_no is '排序'; -comment on column wf_task_back_node.instance_id is '流程实例id'; -comment on column wf_task_back_node.task_type is '节点类型'; -comment on column wf_task_back_node.assignee is '审批人'; -comment on column wf_task_back_node.tenant_id is '租户id'; -comment on column wf_task_back_node.create_dept is '创建部门'; -comment on column wf_task_back_node.create_by is '创建者'; -comment on column wf_task_back_node.create_time is '创建时间'; -comment on column wf_task_back_node.update_by is '修改者'; -comment on column wf_task_back_node.update_time is '修改时间'; - -alter table wf_task_back_node - owner to postgres; - -create table wf_definition_config -( - id bigint not null - constraint pk_wf_definition_config - primary key, - table_name varchar(255) not null, - definition_id varchar(255) not null, - process_key varchar(255) not null, - version bigint not null, - tenant_id varchar(20), - remark varchar(500), - create_dept bigint, - create_by bigint, - create_time timestamp, - update_by bigint, - update_time timestamp -); - -comment on table wf_definition_config is '流程定义配置'; -comment on column wf_definition_config.id is '主键'; -comment on column wf_definition_config.table_name is '表名'; -comment on column wf_definition_config.definition_id is '流程定义ID'; -comment on column wf_definition_config.process_key is '流程KEY'; -comment on column wf_definition_config.version is '流程版本'; -comment on column wf_definition_config.tenant_id is '租户id'; -comment on column wf_definition_config.remark is '备注'; -comment on column wf_definition_config.create_dept is '创建部门'; -comment on column wf_definition_config.create_by is '创建者'; -comment on column wf_definition_config.create_time is '创建时间'; -comment on column wf_definition_config.update_by is '修改者'; -comment on column wf_definition_config.update_time is '修改时间'; - -alter table wf_definition_config - owner to postgres; -create unique index uni_definition_id - on wf_definition_config (definition_id); - -create table wf_form_manage -( - id bigint not null - constraint pk_wf_form_manage - primary key, - form_name varchar(255) not null, - form_type varchar(255) not null, - router varchar(255) not null, - remark varchar(500), - tenant_id varchar(20), - create_dept bigint, - create_by bigint, - create_time timestamp, - update_by bigint, - update_time timestamp -); - -comment on table wf_form_manage is '表单管理'; -comment on column wf_form_manage.id is '主键'; -comment on column wf_form_manage.form_name is '表单名称'; -comment on column wf_form_manage.form_type is '表单类型'; -comment on column wf_form_manage.router is '路由地址/表单ID'; -comment on column wf_form_manage.remark is '备注'; -comment on column wf_form_manage.tenant_id is '租户id'; -comment on column wf_form_manage.create_dept is '创建部门'; -comment on column wf_form_manage.create_by is '创建者'; -comment on column wf_form_manage.create_time is '创建时间'; -comment on column wf_form_manage.update_by is '修改者'; -comment on column wf_form_manage.update_time is '修改时间'; - -insert into wf_form_manage(id, form_name, form_type, router, remark, tenant_id, create_dept, create_by, create_time, update_by, update_time) VALUES (1, '请假申请', 'static', '/workflow/leaveEdit/index', NULL, '000000', 103, 1, now(), 1, now()); - -create table wf_node_config -( - id bigint not null - constraint pk_wf_node_config - primary key, - form_id bigint, - form_type varchar(255), - node_name varchar(255) not null, - node_id varchar(255) not null, - definition_id varchar(255) not null, - apply_user_task char(1) default '0', - tenant_id varchar(20), - create_dept bigint, - create_by bigint, - create_time timestamp, - update_by bigint, - update_time timestamp -); - -comment on table wf_node_config is '节点配置'; -comment on column wf_node_config.id is '主键'; -comment on column wf_node_config.form_id is '表单id'; -comment on column wf_node_config.form_type is '表单类型'; -comment on column wf_node_config.node_id is '节点id'; -comment on column wf_node_config.node_name is '节点名称'; -comment on column wf_node_config.definition_id is '流程定义id'; -comment on column wf_node_config.apply_user_task is '是否为申请人节点 (0是 1否)'; -comment on column wf_node_config.tenant_id is '租户id'; -comment on column wf_node_config.create_dept is '创建部门'; -comment on column wf_node_config.create_by is '创建者'; -comment on column wf_node_config.create_time is '创建时间'; -comment on column wf_node_config.update_by is '修改者'; -comment on column wf_node_config.update_time is '修改时间'; - -INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11638, '请假申请', 5, 1, 'leave', 'workflow/leave/index', 1, 0, 'C', '0', '0', 'workflow:leave:list', '#', 103, 1, now(), NULL, NULL, '请假申请菜单'); -INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11639, '请假申请查询', 11638, 1, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:query', '#', 103, 1, now(), NULL, NULL, ''); -INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11640, '请假申请新增', 11638, 2, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:add', '#', 103, 1, now(), NULL, NULL, ''); -INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11641, '请假申请修改', 11638, 3, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:edit', '#', 103, 1, now(), NULL, NULL, ''); -INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11642, '请假申请删除', 11638, 4, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:remove', '#', 103, 1, now(), NULL, NULL, ''); -INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11643, '请假申请导出', 11638, 5, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:export', '#', 103, 1, now(), NULL, NULL, ''); - -INSERT INTO sys_dict_type(dict_id, tenant_id, dict_name, dict_type, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (13, '000000', '业务状态', 'wf_business_status', 103, 1, now(), NULL, NULL, '业务状态列表'); -INSERT INTO sys_dict_type(dict_id, tenant_id, dict_name, dict_type, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (14, '000000', '表单类型', 'wf_form_type', 103, 1, now(), NULL, NULL, '表单类型列表'); - -INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (39, '000000', 1, '已撤销', 'cancel', 'wf_business_status', '', 'danger', 'N', 103, 1, now(), NULL, NULL, '已撤销'); -INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (40, '000000', 2, '草稿', 'draft', 'wf_business_status', '', 'info', 'N', 103, 1, now(), NULL, NULL, '草稿'); -INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (41, '000000', 3, '待审核', 'waiting', 'wf_business_status', '', 'primary', 'N', 103, 1,now(), NULL, NULL, '待审核'); -INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (42, '000000', 4, '已完成', 'finish', 'wf_business_status', '', 'success', 'N', 103, 1, now(), NULL, NULL, '已完成'); -INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (43, '000000', 5, '已作废', 'invalid', 'wf_business_status', '', 'danger', 'N', 103, 1, now(), NULL, NULL, '已作废'); -INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (44, '000000', 6, '已退回', 'back', 'wf_business_status', '', 'danger', 'N', 103, 1, now(), NULL, NULL, '已退回'); -INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (45, '000000', 7, '已终止', 'termination', 'wf_business_status', '', 'danger', 'N', 103, 1,now(), NULL, NULL, '已终止'); -INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (46, '000000', 1, '自定义表单', 'static', 'wf_form_type', '', 'success', 'N', 103, 1, now(), NULL, NULL, '自定义表单'); -INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (47, '000000', 2, '动态表单', 'dynamic', 'wf_form_type', '', 'primary', 'N', 103, 1, now(), NULL, NULL, '动态表单'); - --- 表单管理 SQL -insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) -values(11628, '表单管理', '11616', '5', 'formManage', 'workflow/formManage/index', 1, 0, 'C', '0', '0', 'workflow:formManage:list', 'tree-table', 103, 1, now(), null, null, '表单管理菜单'); - --- 表单管理按钮 SQL -insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) -values(11644, '表单管理查询', 11628, '1', '#', '', 1, 0, 'F', '0', '0', 'workflow:formManage:query', '', 103, 1, now(), null, null, ''); - -insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) -values(11645, '表单管理新增', 11628, '2', '#', '', 1, 0, 'F', '0', '0', 'workflow:formManage:add', '', 103, 1, now(), null, null, ''); - -insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) -values(11646, '表单管理修改', 11628, '3', '#', '', 1, 0, 'F', '0', '0', 'workflow:formManage:edit', '', 103, 1, now(), null, null, ''); - -insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) -values(11647, '表单管理删除', 11628, '4', '#', '', 1, 0, 'F', '0', '0', 'workflow:formManage:remove', '', 103, 1, now(), null, null, ''); - -insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) -values(11648, '表单管理导出', 11628, '5', '#', '', 1, 0, 'F', '0', '0', 'workflow:formManage:export', 'tree-table', 103, 1, now(), null, null, ''); diff --git a/script/sql/ry_job.sql b/script/sql/ry_job.sql index 396798ee0..c6ec01b45 100644 --- a/script/sql/ry_job.sql +++ b/script/sql/ry_job.sql @@ -47,7 +47,7 @@ CREATE TABLE `sj_notify_config` `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', `namespace_id` varchar(64) NOT NULL DEFAULT '764d604ec6fc45f68cd92514c40e9e1a' COMMENT '命名空间id', `group_name` varchar(64) NOT NULL COMMENT '组名称', - `business_id` varchar(64) NOT NULL COMMENT '业务id (job_id或workflow_id或scene_name)', + `notify_name` varchar(64) NOT NULL DEFAULT '' COMMENT '通知名称', `system_task_type` tinyint(4) NOT NULL DEFAULT 3 COMMENT '任务类型 1. 重试任务 2. 重试回调 3、JOB任务 4、WORKFLOW任务', `notify_status` tinyint(4) NOT NULL DEFAULT 0 COMMENT '通知状态 0、未启用 1、启用', `recipient_ids` varchar(128) NOT NULL COMMENT '接收人id列表', @@ -59,7 +59,7 @@ CREATE TABLE `sj_notify_config` `create_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间', PRIMARY KEY (`id`), - KEY `idx_namespace_id_group_name_scene_name` (`namespace_id`, `group_name`, `business_id`) + KEY `idx_namespace_id_group_name_scene_name` (`namespace_id`, `group_name`) ) ENGINE = InnoDB AUTO_INCREMENT = 0 DEFAULT CHARSET = utf8mb4 COMMENT ='通知配置'; @@ -188,6 +188,7 @@ CREATE TABLE `sj_retry_scene_config` `max_retry_count` int(11) NOT NULL DEFAULT 5 COMMENT '最大重试次数', `back_off` tinyint(4) NOT NULL DEFAULT 1 COMMENT '1、默认等级 2、固定间隔时间 3、CRON 表达式', `trigger_interval` varchar(16) NOT NULL DEFAULT '' COMMENT '间隔时长', + `notify_ids` varchar(128) NOT NULL DEFAULT '' COMMENT '通知告警场景配置id列表', `deadline_request` bigint(20) unsigned NOT NULL DEFAULT 60000 COMMENT 'Deadline Request 调用链超时 单位毫秒', `executor_timeout` int(11) unsigned NOT NULL DEFAULT 5 COMMENT '任务执行超时时间,单位秒', `route_key` tinyint(4) NOT NULL DEFAULT 4 COMMENT '路由策略', @@ -300,6 +301,8 @@ CREATE TABLE `sj_job` `retry_interval` int(11) NOT NULL DEFAULT 0 COMMENT '重试间隔(s)', `bucket_index` int(11) NOT NULL DEFAULT 0 COMMENT 'bucket', `resident` tinyint(4) NOT NULL DEFAULT 0 COMMENT '是否是常驻任务', + `notify_ids` varchar(128) NOT NULL DEFAULT '' COMMENT '通知告警场景配置id列表', + `owner_id` bigint(20) NULL COMMENT '负责人id', `description` varchar(256) NOT NULL DEFAULT '' COMMENT '描述', `ext_attrs` varchar(256) NULL DEFAULT '' COMMENT '扩展字段', `deleted` tinyint(4) NOT NULL DEFAULT 0 COMMENT '逻辑删除 1、删除', @@ -313,7 +316,7 @@ CREATE TABLE `sj_job` AUTO_INCREMENT = 0 DEFAULT CHARSET = utf8mb4 COMMENT ='任务信息'; -INSERT INTO `sj_job` VALUES (1, 'dev', 'ruoyi_group', 'demo-job', null, 1, 1710344035622, 1, 1, 4, 1, 'testJobExecutor', 2, '60', 1, 60, 3, 1, 1, 116, 0, '', '', 0 , now(), now()); +INSERT INTO `sj_job` VALUES (1, 'dev', 'ruoyi_group', 'demo-job', null, 1, 1710344035622, 1, 1, 4, 1, 'testJobExecutor', 2, '60', 1, 60, 3, 1, 1, 116, 0, '', 1, '', '', 0 , now(), now()); CREATE TABLE `sj_job_log_message` ( @@ -451,6 +454,7 @@ CREATE TABLE `sj_workflow` `description` varchar(256) NOT NULL DEFAULT '' COMMENT '描述', `flow_info` text DEFAULT NULL COMMENT '流程信息', `wf_context` text DEFAULT NULL COMMENT '上下文', + `notify_ids` varchar(128) NOT NULL DEFAULT '' COMMENT '通知告警场景配置id列表', `bucket_index` int(11) NOT NULL DEFAULT 0 COMMENT 'bucket', `version` int(11) NOT NULL COMMENT '版本号', `ext_attrs` varchar(256) NULL DEFAULT '' COMMENT '扩展字段', diff --git a/script/sql/ry_vue_5.X.sql b/script/sql/ry_vue_5.X.sql index 3e3562d27..9e6244ddb 100644 --- a/script/sql/ry_vue_5.X.sql +++ b/script/sql/ry_vue_5.X.sql @@ -5,7 +5,7 @@ create table sys_social ( id bigint not null comment '主键', user_id bigint not null comment '用户ID', - tenant_id varchar(20) default null comment '租户id', + tenant_id varchar(20) default '000000' comment '租户id', auth_id varchar(255) not null comment '平台+平台唯一id', source varchar(255) not null comment '用户来源', open_id varchar(255) default null comment '平台编号唯一id', @@ -31,7 +31,7 @@ create table sys_social create_time datetime comment '创建时间', update_by bigint(20) comment '更新者', update_time datetime comment '更新时间', - del_flag char(1) default '0' comment '删除标志(0代表存在 2代表删除)', + del_flag char(1) default '0' comment '删除标志(0代表存在 1代表删除)', PRIMARY KEY (id) ) engine=innodb comment = '社会化关系表'; @@ -55,7 +55,7 @@ create table sys_tenant expire_time datetime comment '过期时间', account_count int default -1 comment '用户数量(-1不限制)', status char(1) default '0' comment '租户状态(0正常 1停用)', - del_flag char(1) default '0' comment '删除标志(0代表存在 2代表删除)', + del_flag char(1) default '0' comment '删除标志(0代表存在 1代表删除)', create_dept bigint(20) comment '创建部门', create_by bigint(20) comment '创建者', create_time datetime comment '创建时间', @@ -82,7 +82,7 @@ create table sys_tenant_package ( remark varchar(200) comment '备注', menu_check_strictly tinyint(1) default 1 comment '菜单树选择项是否关联显示', status char(1) default '0' comment '状态(0正常 1停用)', - del_flag char(1) default '0' comment '删除标志(0代表存在 2代表删除)', + del_flag char(1) default '0' comment '删除标志(0代表存在 1代表删除)', create_dept bigint(20) comment '创建部门', create_by bigint(20) comment '创建者', create_time datetime comment '创建时间', @@ -107,7 +107,7 @@ create table sys_dept ( phone varchar(11) default null comment '联系电话', email varchar(50) default null comment '邮箱', status char(1) default '0' comment '部门状态(0正常 1停用)', - del_flag char(1) default '0' comment '删除标志(0代表存在 2代表删除)', + del_flag char(1) default '0' comment '删除标志(0代表存在 1代表删除)', create_dept bigint(20) default null comment '创建部门', create_by bigint(20) default null comment '创建者', create_time datetime comment '创建时间', @@ -149,7 +149,7 @@ create table sys_user ( avatar bigint(20) comment '头像地址', password varchar(100) default '' comment '密码', status char(1) default '0' comment '帐号状态(0正常 1停用)', - del_flag char(1) default '0' comment '删除标志(0代表存在 2代表删除)', + del_flag char(1) default '0' comment '删除标志(0代表存在 1代表删除)', login_ip varchar(128) default '' comment '最后登录IP', login_date datetime comment '最后登录时间', create_dept bigint(20) default null comment '创建部门', @@ -212,7 +212,7 @@ create table sys_role ( menu_check_strictly tinyint(1) default 1 comment '菜单树选择项是否关联显示', dept_check_strictly tinyint(1) default 1 comment '部门树选择项是否关联显示', status char(1) not null comment '角色状态(0正常 1停用)', - del_flag char(1) default '0' comment '删除标志(0代表存在 2代表删除)', + del_flag char(1) default '0' comment '删除标志(0代表存在 1代表删除)', create_dept bigint(20) default null comment '创建部门', create_by bigint(20) default null comment '创建者', create_time datetime comment '创建时间', @@ -554,10 +554,10 @@ create table sys_oper_log ( oper_url varchar(255) default '' comment '请求URL', oper_ip varchar(128) default '' comment '主机地址', oper_location varchar(255) default '' comment '操作地点', - oper_param varchar(2000) default '' comment '请求参数', - json_result varchar(2000) default '' comment '返回参数', + oper_param varchar(4000) default '' comment '请求参数', + json_result varchar(4000) default '' comment '返回参数', status int(1) default 0 comment '操作状态(0正常 1异常)', - error_msg varchar(2000) default '' comment '错误消息', + error_msg varchar(4000) default '' comment '错误消息', oper_time datetime comment '操作时间', cost_time bigint(20) default 0 comment '消耗时间', primary key (oper_id), @@ -840,7 +840,7 @@ create table sys_oss_config ( insert into sys_oss_config values (1, '000000', 'minio', 'ruoyi', 'ruoyi123', 'ruoyi', '', '127.0.0.1:9000', '','N', '', '1' ,'0', '', 103, 1, sysdate(), 1, sysdate(), null); insert into sys_oss_config values (2, '000000', 'qiniu', 'XXXXXXXXXXXXXXX', 'XXXXXXXXXXXXXXX', 'ruoyi', '', 's3-cn-north-1.qiniucs.com', '','N', '', '1' ,'1', '', 103, 1, sysdate(), 1, sysdate(), null); insert into sys_oss_config values (3, '000000', 'aliyun', 'XXXXXXXXXXXXXXX', 'XXXXXXXXXXXXXXX', 'ruoyi', '', 'oss-cn-beijing.aliyuncs.com', '','N', '', '1' ,'1', '', 103, 1, sysdate(), 1, sysdate(), null); -insert into sys_oss_config values (4, '000000', 'qcloud', 'XXXXXXXXXXXXXXX', 'XXXXXXXXXXXXXXX', 'ruoyi-1250000000', '', 'cos.ap-beijing.myqcloud.com', '','N', 'ap-beijing', '1' ,'1', '', 103, 1, sysdate(), 1, sysdate(), null); +insert into sys_oss_config values (4, '000000', 'qcloud', 'XXXXXXXXXXXXXXX', 'XXXXXXXXXXXXXXX', 'ruoyi-1240000000', '', 'cos.ap-beijing.myqcloud.com', '','N', 'ap-beijing', '1' ,'1', '', 103, 1, sysdate(), 1, sysdate(), null); insert into sys_oss_config values (5, '000000', 'image', 'ruoyi', 'ruoyi123', 'ruoyi', 'image', '127.0.0.1:9000', '','N', '', '1' ,'1', '', 103, 1, sysdate(), 1, sysdate(), null); -- ---------------------------- @@ -856,7 +856,7 @@ create table sys_client ( active_timeout int(11) default 1800 comment 'token活跃超时时间', timeout int(11) default 604800 comment 'token固定超时', status char(1) default '0' comment '状态(0正常 1停用)', - del_flag char(1) default '0' comment '删除标志(0代表存在 2代表删除)', + del_flag char(1) default '0' comment '删除标志(0代表存在 1代表删除)', create_dept bigint(20) default null comment '创建部门', create_by bigint(20) default null comment '创建者', create_time datetime default null comment '创建时间', diff --git a/script/sql/ry_workflow.sql b/script/sql/ry_workflow.sql index e8dc798a9..9455636a0 100644 --- a/script/sql/ry_workflow.sql +++ b/script/sql/ry_workflow.sql @@ -1,176 +1,253 @@ -insert into sys_menu values('11616', '工作流' , '0', '6', 'workflow', '', '', '1', '0', 'M', '0', '0', '', 'workflow', 103, 1, sysdate(), NULL, NULL, ''); -insert into sys_menu values('11617', '模型管理', '11616', '2', 'model', 'workflow/model/index', '', '1', '1', 'C', '0', '0', 'workflow:model:list', 'model', 103, 1, sysdate(), NULL, NULL, ''); -insert into sys_menu values('11618', '我的任务', '0', '7', 'task', '', '', '1', '0', 'M', '0', '0', '', 'my-task', 103, 1, sysdate(), NULL, NULL, ''); -insert into sys_menu values('11619', '我的待办', '11618', '2', 'taskWaiting', 'workflow/task/taskWaiting', '', '1', '1', 'C', '0', '0', '', 'waiting', 103, 1, sysdate(), NULL, NULL, ''); -insert into sys_menu values('11632', '我的已办', '11618', '3', 'taskFinish', 'workflow/task/taskFinish', '', '1', '1', 'C', '0', '0', '', 'finish', 103, 1, sysdate(), NULL, NULL, ''); -insert into sys_menu values('11633', '我的抄送', '11618', '4', 'taskCopyList', 'workflow/task/taskCopyList', '', '1', '1', 'C', '0', '0', '', 'my-copy', 103, 1, sysdate(), NULL, NULL, ''); -insert into sys_menu values('11620', '流程定义', '11616', '3', 'processDefinition', 'workflow/processDefinition/index', '', '1', '1', 'C', '0', '0', '', 'process-definition', 103, 1, sysdate(), NULL, NULL, ''); -insert into sys_menu values('11621', '流程实例', '11630', '1', 'processInstance', 'workflow/processInstance/index', '', '1', '1', 'C', '0', '0', '', 'tree-table', 103, 1, sysdate(), NULL, NULL, ''); -insert into sys_menu values('11622', '流程分类', '11616', '1', 'category', 'workflow/category/index', '', '1', '0', 'C', '0', '0', 'workflow:category:list', 'category', 103, 1, sysdate(), NULL, NULL, ''); -insert into sys_menu values('11629', '我发起的', '11618', '1', 'myDocument', 'workflow/task/myDocument', '', '1', '1', 'C', '0', '0', '', 'guide', 103, 1, sysdate(), NULL, NULL, ''); -insert into sys_menu values('11630', '流程监控', '11616', '4', 'monitor', '', '', '1', '0', 'M', '0', '0', '', 'monitor', 103, 1, sysdate(), NULL, NULL, ''); -insert into sys_menu values('11631', '待办任务', '11630', '2', 'allTaskWaiting', 'workflow/task/allTaskWaiting', '', '1', '1', 'C', '0', '0', '', 'waiting', 103, 1, sysdate(), NULL, NULL, ''); +-- ---------------------------- +-- 0、warm-flow-all.sql,地址:https://gitee.com/dromara/warm-flow/blob/master/sql/mysql/warm-flow-all.sql +-- ---------------------------- +CREATE TABLE `flow_definition` +( + `id` bigint unsigned NOT NULL COMMENT '主键id', + `flow_code` varchar(40) NOT NULL COMMENT '流程编码', + `flow_name` varchar(100) NOT NULL COMMENT '流程名称', + `category` varchar(100) DEFAULT NULL COMMENT '流程类别', + `version` varchar(20) NOT NULL COMMENT '流程版本', + `is_publish` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否发布(0未发布 1已发布 9失效)', + `form_custom` char(1) DEFAULT 'N' COMMENT '审批表单是否自定义(Y是 N否)', + `form_path` varchar(100) DEFAULT NULL COMMENT '审批表单路径', + `activity_status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '流程激活状态(0挂起 1激活)', + `listener_type` varchar(100) DEFAULT NULL COMMENT '监听器类型', + `listener_path` varchar(400) DEFAULT NULL COMMENT '监听器路径', + `ext` varchar(500) DEFAULT NULL COMMENT '业务详情 存业务表对象json字符串', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + `del_flag` char(1) DEFAULT '0' COMMENT '删除标志', + `tenant_id` varchar(40) DEFAULT NULL COMMENT '租户id', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB COMMENT ='流程定义表'; + +CREATE TABLE `flow_node` +( + `id` bigint unsigned NOT NULL COMMENT '主键id', + `node_type` tinyint(1) NOT NULL COMMENT '节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)', + `definition_id` bigint NOT NULL COMMENT '流程定义id', + `node_code` varchar(100) NOT NULL COMMENT '流程节点编码', + `node_name` varchar(100) DEFAULT NULL COMMENT '流程节点名称', + `permission_flag` varchar(200) DEFAULT NULL COMMENT '权限标识(权限类型:权限标识,可以多个,用逗号隔开)', + `node_ratio` decimal(6, 3) DEFAULT NULL COMMENT '流程签署比例值', + `coordinate` varchar(100) DEFAULT NULL COMMENT '坐标', + `skip_any_node` varchar(100) DEFAULT 'N' COMMENT '是否可以退回任意节点(Y是 N否)即将删除', + `any_node_skip` varchar(100) DEFAULT NULL COMMENT '任意结点跳转', + `listener_type` varchar(100) DEFAULT NULL COMMENT '监听器类型', + `listener_path` varchar(400) DEFAULT NULL COMMENT '监听器路径', + `handler_type` varchar(100) DEFAULT NULL COMMENT '处理器类型', + `handler_path` varchar(400) DEFAULT NULL COMMENT '处理器路径', + `form_custom` char(1) DEFAULT 'N' COMMENT '审批表单是否自定义(Y是 N否)', + `form_path` varchar(100) DEFAULT NULL COMMENT '审批表单路径', + `version` varchar(20) NOT NULL COMMENT '版本', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + `del_flag` char(1) DEFAULT '0' COMMENT '删除标志', + `tenant_id` varchar(40) DEFAULT NULL COMMENT '租户id', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB COMMENT ='流程节点表'; + +CREATE TABLE `flow_skip` +( + `id` bigint unsigned NOT NULL COMMENT '主键id', + `definition_id` bigint NOT NULL COMMENT '流程定义id', + `now_node_code` varchar(100) NOT NULL COMMENT '当前流程节点的编码', + `now_node_type` tinyint(1) DEFAULT NULL COMMENT '当前节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)', + `next_node_code` varchar(100) NOT NULL COMMENT '下一个流程节点的编码', + `next_node_type` tinyint(1) DEFAULT NULL COMMENT '下一个节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)', + `skip_name` varchar(100) DEFAULT NULL COMMENT '跳转名称', + `skip_type` varchar(40) DEFAULT NULL COMMENT '跳转类型(PASS审批通过 REJECT退回)', + `skip_condition` varchar(200) DEFAULT NULL COMMENT '跳转条件', + `coordinate` varchar(100) DEFAULT NULL COMMENT '坐标', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + `del_flag` char(1) DEFAULT '0' COMMENT '删除标志', + `tenant_id` varchar(40) DEFAULT NULL COMMENT '租户id', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB COMMENT ='节点跳转关联表'; + +CREATE TABLE `flow_instance` +( + `id` bigint NOT NULL COMMENT '主键id', + `definition_id` bigint NOT NULL COMMENT '对应flow_definition表的id', + `business_id` varchar(40) NOT NULL COMMENT '业务id', + `node_type` tinyint(1) NOT NULL COMMENT '节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)', + `node_code` varchar(40) NOT NULL COMMENT '流程节点编码', + `node_name` varchar(100) DEFAULT NULL COMMENT '流程节点名称', + `variable` text COMMENT '任务变量', + `flow_status` varchar(20) NOT NULL COMMENT '流程状态(0待提交 1审批中 2 审批通过 3自动通过 4终止 5作废 6撤销 7取回 8已完成 9已退回 10失效)', + `activity_status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '流程激活状态(0挂起 1激活)', + `def_json` text COMMENT '流程定义json', + `create_by` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + `ext` varchar(500) DEFAULT NULL COMMENT '扩展字段,预留给业务系统使用', + `del_flag` char(1) DEFAULT '0' COMMENT '删除标志', + `tenant_id` varchar(40) DEFAULT NULL COMMENT '租户id', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB COMMENT ='流程实例表'; + +CREATE TABLE `flow_task` +( + `id` bigint NOT NULL COMMENT '主键id', + `definition_id` bigint NOT NULL COMMENT '对应flow_definition表的id', + `instance_id` bigint NOT NULL COMMENT '对应flow_instance表的id', + `node_code` varchar(100) NOT NULL COMMENT '节点编码', + `node_name` varchar(100) DEFAULT NULL COMMENT '节点名称', + `node_type` tinyint(1) NOT NULL COMMENT '节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)', + `form_custom` char(1) DEFAULT 'N' COMMENT '审批表单是否自定义(Y是 N否)', + `form_path` varchar(100) DEFAULT NULL COMMENT '审批表单路径', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + `del_flag` char(1) DEFAULT '0' COMMENT '删除标志', + `tenant_id` varchar(40) DEFAULT NULL COMMENT '租户id', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB COMMENT ='待办任务表'; + +CREATE TABLE `flow_his_task` +( + `id` bigint(20) unsigned NOT NULL COMMENT '主键id', + `definition_id` bigint(20) NOT NULL COMMENT '对应flow_definition表的id', + `instance_id` bigint(20) NOT NULL COMMENT '对应flow_instance表的id', + `task_id` bigint(20) NOT NULL COMMENT '对应flow_task表的id', + `node_code` varchar(100) DEFAULT NULL COMMENT '开始节点编码', + `node_name` varchar(100) DEFAULT NULL COMMENT '开始节点名称', + `node_type` tinyint(1) DEFAULT NULL COMMENT '开始节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)', + `target_node_code` varchar(200) DEFAULT NULL COMMENT '目标节点编码', + `target_node_name` varchar(200) DEFAULT NULL COMMENT '结束节点名称', + `approver` varchar(40) DEFAULT NULL COMMENT '审批者', + `cooperate_type` tinyint(1) NOT NULL DEFAULT '0' COMMENT '协作方式(1审批 2转办 3委派 4会签 5票签 6加签 7减签)', + `collaborator` varchar(40) DEFAULT NULL COMMENT '协作人', + `skip_type` varchar(10) NOT NULL COMMENT '流转类型(PASS通过 REJECT退回 NONE无动作)', + `flow_status` varchar(20) NOT NULL COMMENT '流程状态(1审批中 2 审批通过 9已退回 10失效)', + `form_custom` char(1) DEFAULT 'N' COMMENT '审批表单是否自定义(Y是 N否)', + `form_path` varchar(100) DEFAULT NULL COMMENT '审批表单路径', + `message` varchar(500) DEFAULT NULL COMMENT '审批意见', + `variable` TEXT DEFAULT NULL COMMENT '任务变量', + `ext` varchar(500) DEFAULT NULL COMMENT '业务详情 存业务表对象json字符串', + `create_time` datetime DEFAULT NULL COMMENT '任务开始时间', + `update_time` datetime DEFAULT NULL COMMENT '审批完成时间', + `del_flag` char(1) DEFAULT '0' COMMENT '删除标志', + `tenant_id` varchar(40) DEFAULT NULL COMMENT '租户id', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB COMMENT ='历史任务记录表'; --- 流程分类管理相关按钮 -insert into sys_menu values ('11623', '流程分类查询', '11622', '1', '#', '', '', 1, 0, 'F', '0', '0', 'workflow:category:query', '#', 103, 1, sysdate(), null, null, ''); -insert into sys_menu values ('11624', '流程分类新增', '11622', '2', '#', '', '', 1, 0, 'F', '0', '0', 'workflow:category:add', '#', 103, 1, sysdate(), null, null, ''); -insert into sys_menu values ('11625', '流程分类修改', '11622', '3', '#', '', '', 1, 0, 'F', '0', '0', 'workflow:category:edit', '#', 103, 1, sysdate(), null, null, ''); -insert into sys_menu values ('11626', '流程分类删除', '11622', '4', '#', '', '', 1, 0, 'F', '0', '0', 'workflow:category:remove','#', 103, 1, sysdate(), null, null, ''); -insert into sys_menu values ('11627', '流程分类导出', '11622', '5', '#', '', '', 1, 0, 'F', '0', '0', 'workflow:category:export','#', 103, 1, sysdate(), null, null, ''); +CREATE TABLE `flow_user` +( + `id` bigint unsigned NOT NULL COMMENT '主键id', + `type` char(1) NOT NULL COMMENT '人员类型(1待办任务的审批人权限 2待办任务的转办人权限 3待办任务的委托人权限)', + `processed_by` varchar(80) DEFAULT NULL COMMENT '权限人', + `associated` bigint NOT NULL COMMENT '任务表id', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `create_by` varchar(80) DEFAULT NULL COMMENT '创建人', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + `del_flag` char(1) DEFAULT '0' COMMENT '删除标志', + `tenant_id` varchar(40) DEFAULT NULL COMMENT '租户id', + PRIMARY KEY (`id`) USING BTREE, + KEY `user_processed_type` (`processed_by`, `type`) +) ENGINE = InnoDB COMMENT ='流程用户表'; + +-- ---------------------------- +-- 流程分类表 +-- ---------------------------- +create table flow_category +( + category_id bigint(20) not null comment '流程分类ID', + tenant_id varchar(20) default '000000' comment '租户编号', + parent_id bigint(20) default 0 comment '父流程分类id', + ancestors varchar(500) default '' comment '祖级列表', + category_name varchar(30) not null comment '流程分类名称', + order_num int(4) default 0 comment '显示顺序', + del_flag char(1) default '0' comment '删除标志(0代表存在 1代表删除)', + create_dept bigint(20) null comment '创建部门', + create_by bigint(20) null comment '创建者', + create_time datetime null comment '创建时间', + update_by bigint(20) null comment '更新者', + update_time datetime null comment '更新时间', + primary key (category_id) +) engine = innodb comment = '流程分类'; + +INSERT INTO flow_category values (100, '000000', 0, '0', 'OA审批', 0, '0', 103, 1, sysdate(), null, null); +INSERT INTO flow_category values (101, '000000', 100, '0,100', '假勤管理', 0, '0', 103, 1, sysdate(), null, null); +INSERT INTO flow_category values (102, '000000', 100, '0,100', '人事管理', 1, '0', 103, 1, sysdate(), null, null); +INSERT INTO flow_category values (103, '000000', 101, '0,100,101', '请假', 0, '0', 103, 1, sysdate(), null, null); +INSERT INTO flow_category values (104, '000000', 101, '0,100,101', '出差', 1, '0', 103, 1, sysdate(), null, null); +INSERT INTO flow_category values (105, '000000', 101, '0,100,101', '加班', 2, '0', 103, 1, sysdate(), null, null); +INSERT INTO flow_category values (106, '000000', 101, '0,100,101', '换班', 3, '0', 103, 1, sysdate(), null, null); +INSERT INTO flow_category values (107, '000000', 101, '0,100,101', '外出', 4, '0', 103, 1, sysdate(), null, null); +INSERT INTO flow_category values (108, '000000', 102, '0,100,102', '转正', 1, '0', 103, 1, sysdate(), null, null); +INSERT INTO flow_category values (109, '000000', 102, '0,100,102', '离职', 2, '0', 103, 1, sysdate(), null, null); + +-- ---------------------------- -- 请假单信息 +-- ---------------------------- create table test_leave ( - id bigint not null comment '主键', - leave_type varchar(255) not null comment '请假类型', - start_date datetime not null comment '开始时间', - end_date datetime not null comment '结束时间', - leave_days int(10) not null comment '请假天数', - remark varchar(255) null comment '请假原因', - status varchar(255) null comment '状态', - create_dept bigint null comment '创建部门', - create_by bigint null comment '创建者', - create_time datetime null comment '创建时间', - update_by bigint null comment '更新者', - update_time datetime null comment '更新时间', - tenant_id varchar(20) null comment '租户编号', - PRIMARY KEY (id) USING BTREE -) ENGINE = InnoDB COMMENT = '请假申请表'; - --- 流程分类信息表 -create table wf_category -( - id bigint not null comment '主键' - primary key, - category_name varchar(255) null comment '分类名称', - category_code varchar(255) null comment '分类编码', - parent_id bigint null comment '父级id', - sort_num int(19) null comment '排序', - tenant_id varchar(20) null comment '租户编号', - create_dept bigint null comment '创建部门', - create_by bigint null comment '创建者', - create_time datetime null comment '创建时间', - update_by bigint null comment '更新者', - update_time datetime null comment '更新时间', - constraint uni_category_code - unique (category_code) -) engine=innodb comment= '流程分类'; -INSERT INTO wf_category values (1, 'OA', 'OA', 0, 0, '000000', 103, 1, sysdate(), 1, sysdate()); - -create table wf_task_back_node -( - id bigint not null - primary key, - node_id varchar(255) not null comment '节点id', - node_name varchar(255) not null comment '节点名称', - order_no int not null comment '排序', - instance_id varchar(255) null comment '流程实例id', - task_type varchar(255) not null comment '节点类型', - assignee varchar(2000) not null comment '审批人', - tenant_id varchar(20) null comment '租户编号', - create_dept bigint null comment '创建部门', - create_by bigint null comment '创建者', - create_time datetime null comment '创建时间', - update_by bigint null comment '更新者', - update_time datetime null comment '更新时间' -) - comment '节点审批记录'; - -create table wf_definition_config -( - id bigint not null comment '主键' - primary key, - table_name varchar(255) not null comment '表名', - definition_id varchar(255) not null comment '流程定义ID', - process_key varchar(255) not null comment '流程KEY', - version int(10) not null comment '流程版本', - create_dept bigint null comment '创建部门', - create_by bigint null comment '创建者', - create_time datetime null comment '创建时间', - update_by bigint null comment '更新者', - update_time datetime null comment '更新时间', - remark varchar(500) default '' null comment '备注', - tenant_id varchar(20) null comment '租户编号', - constraint uni_definition_id - unique (definition_id) -) - comment '流程定义配置'; - -create table wf_form_manage -( - id bigint not null comment '主键' - primary key, - form_name varchar(255) not null comment '表单名称', - form_type varchar(255) not null comment '表单类型', - router varchar(255) not null comment '路由地址/表单ID', - remark varchar(500) null comment '备注', - tenant_id varchar(20) null comment '租户编号', + id bigint(20) not null comment 'id', + tenant_id varchar(20) default '000000' comment '租户编号', + leave_type varchar(255) not null comment '请假类型', + start_date datetime not null comment '开始时间', + end_date datetime not null comment '结束时间', + leave_days int(10) not null comment '请假天数', + remark varchar(255) null comment '请假原因', + status varchar(255) null comment '状态', create_dept bigint null comment '创建部门', create_by bigint null comment '创建者', create_time datetime null comment '创建时间', update_by bigint null comment '更新者', - update_time datetime null comment '更新时间' -) - comment '表单管理'; + update_time datetime null comment '更新时间', + PRIMARY KEY (id) USING BTREE +) ENGINE = InnoDB COMMENT = '请假申请表'; -insert into wf_form_manage(id, form_name, form_type, router, remark, tenant_id, create_dept, create_by, create_time, update_by, update_time) VALUES (1, '请假申请', 'static', '/workflow/leaveEdit/index', NULL, '000000', 103, 1, sysdate(), 1, sysdate()); +insert into sys_menu values ('11616', '工作流', '0', '6', 'workflow', '', '', '1', '0', 'M', '0', '0', '', 'workflow', 103, 1, sysdate(),NULL, NULL, ''); +insert into sys_menu values ('11618', '我的任务', '0', '7', 'task', '', '', '1', '0', 'M', '0', '0', '', 'my-task', 103, 1, sysdate(), NULL, NULL, ''); +insert into sys_menu values ('11619', '我的待办', '11618', '2', 'taskWaiting', 'workflow/task/taskWaiting', '', '1', '1', 'C', '0', '0', '', 'waiting', 103, 1, sysdate(), NULL, NULL, ''); +insert into sys_menu values ('11632', '我的已办', '11618', '3', 'taskFinish', 'workflow/task/taskFinish', '', '1', '1', 'C', '0', '0', '', 'finish', 103, 1, sysdate(), NULL, NULL, ''); +insert into sys_menu values ('11633', '我的抄送', '11618', '4', 'taskCopyList', 'workflow/task/taskCopyList', '', '1', '1', 'C', '0', '0', '', 'my-copy', 103, 1, sysdate(), NULL, NULL, ''); +insert into sys_menu values ('11620', '流程定义', '11616', '3', 'processDefinition', 'workflow/processDefinition/index', '', '1', '1', 'C', '0', '0', '', 'process-definition', 103, 1, sysdate(), NULL, NULL, ''); +insert into sys_menu values ('11621', '流程实例', '11630', '1', 'processInstance', 'workflow/processInstance/index', '', '1', '1', 'C', '0', '0', '', 'tree-table', 103, 1, sysdate(), NULL, NULL, ''); +insert into sys_menu values ('11622', '流程分类', '11616', '1', 'category', 'workflow/category/index', '', '1', '0', 'C', '0', '0', 'workflow:category:list', 'category', 103, 1, sysdate(), NULL, NULL, ''); +insert into sys_menu values ('11629', '我发起的', '11618', '1', 'myDocument', 'workflow/task/myDocument', '', '1', '1', 'C', '0', '0', '', 'guide', 103, 1, sysdate(), NULL, NULL, ''); +insert into sys_menu values ('11630', '流程监控', '11616', '4', 'monitor', '', '', '1', '0', 'M', '0', '0', '', 'monitor', 103, 1, sysdate(), NULL, NULL, ''); +insert into sys_menu values ('11631', '待办任务', '11630', '2', 'allTaskWaiting', 'workflow/task/allTaskWaiting', '', '1', '1', 'C', '0', '0', '', 'waiting', 103, 1, sysdate(), NULL, NULL, ''); +-- 流程分类管理相关按钮 +insert into sys_menu values ('11623', '流程分类查询', '11622', '1', '#', '', '', 1, 0, 'F', '0', '0', 'workflow:category:query', '#', 103, 1,sysdate(), null, null, ''); +insert into sys_menu values ('11624', '流程分类新增', '11622', '2', '#', '', '', 1, 0, 'F', '0', '0', 'workflow:category:add', '#', 103, 1,sysdate(), null, null, ''); +insert into sys_menu values ('11625', '流程分类修改', '11622', '3', '#', '', '', 1, 0, 'F', '0', '0', 'workflow:category:edit', '#', 103, 1,sysdate(), null, null, ''); +insert into sys_menu values ('11626', '流程分类删除', '11622', '4', '#', '', '', 1, 0, 'F', '0', '0', 'workflow:category:remove', '#', 103,1, sysdate(), null, null, ''); +insert into sys_menu values ('11627', '流程分类导出', '11622', '5', '#', '', '', 1, 0, 'F', '0', '0', 'workflow:category:export', '#', 103,1, sysdate(), null, null, ''); +-- 请假测试相关按钮 +insert into sys_menu VALUES (11638, '请假申请', 5, 1, 'leave', 'workflow/leave/index', '', 1, 0, 'C', '0', '0', 'workflow:leave:list', '#', 103, 1, sysdate(), NULL, NULL, '请假申请菜单'); +insert into sys_menu VALUES (11639, '请假申请查询', 11638, 1, '#', '', '', 1, 0, 'F', '0', '0', 'workflow:leave:query', '#', 103, 1, sysdate(), NULL, NULL, ''); +insert into sys_menu VALUES (11640, '请假申请新增', 11638, 2, '#', '', '', 1, 0, 'F', '0', '0', 'workflow:leave:add', '#', 103, 1, sysdate(), NULL, NULL, ''); +insert into sys_menu VALUES (11641, '请假申请修改', 11638, 3, '#', '', '', 1, 0, 'F', '0', '0', 'workflow:leave:edit', '#', 103, 1, sysdate(), NULL, NULL, ''); +insert into sys_menu VALUES (11642, '请假申请删除', 11638, 4, '#', '', '', 1, 0, 'F', '0', '0', 'workflow:leave:remove', '#', 103, 1, sysdate(), NULL, NULL, ''); +insert into sys_menu VALUES (11643, '请假申请导出', 11638, 5, '#', '', '', 1, 0, 'F', '0', '0', 'workflow:leave:export', '#', 103, 1, sysdate(), NULL, NULL, ''); -create table wf_node_config -( - id bigint not null comment '主键' - primary key, - form_id bigint null comment '表单id', - form_type varchar(255) null comment '表单类型', - node_name varchar(255) not null comment '节点名称', - node_id varchar(255) not null comment '节点id', - definition_id varchar(255) not null comment '流程定义id', - apply_user_task char(1) default '0' comment '是否为申请人节点 (0是 1否)', - create_dept bigint null comment '创建部门', - create_by bigint null comment '创建者', - create_time datetime null comment '创建时间', - update_by bigint null comment '更新者', - update_time datetime null comment '更新时间', - tenant_id varchar(20) null comment '租户编号' -) - comment '节点配置'; +INSERT INTO sys_dict_type VALUES (13, '000000', '业务状态', 'wf_business_status', 103, 1, sysdate(), NULL, NULL, '业务状态列表'); +INSERT INTO sys_dict_type VALUES (14, '000000', '表单类型', 'wf_form_type', 103, 1, sysdate(), NULL, NULL, '表单类型列表'); +INSERT INTO sys_dict_type VALUES (15, '000000', '任务状态', 'wf_task_status', 103, 1, sysdate(), NULL, NULL, '任务状态'); +INSERT INTO sys_dict_data VALUES (39, '000000', 1, '已撤销', 'cancel', 'wf_business_status', '', 'danger', 'N', 103, 1, sysdate(), NULL, NULL,'已撤销'); +INSERT INTO sys_dict_data VALUES (40, '000000', 2, '草稿', 'draft', 'wf_business_status', '', 'info', 'N', 103, 1, sysdate(), NULL, NULL, '草稿'); +INSERT INTO sys_dict_data VALUES (41, '000000', 3, '待审核', 'waiting', 'wf_business_status', '', 'primary', 'N', 103, 1, sysdate(), NULL, NULL,'待审核'); +INSERT INTO sys_dict_data VALUES (42, '000000', 4, '已完成', 'finish', 'wf_business_status', '', 'success', 'N', 103, 1, sysdate(), NULL, NULL,'已完成'); +INSERT INTO sys_dict_data VALUES (43, '000000', 5, '已作废', 'invalid', 'wf_business_status', '', 'danger', 'N', 103, 1, sysdate(), NULL, NULL,'已作废'); +INSERT INTO sys_dict_data VALUES (44, '000000', 6, '已退回', 'back', 'wf_business_status', '', 'danger', 'N', 103, 1, sysdate(), NULL, NULL,'已退回'); +INSERT INTO sys_dict_data VALUES (45, '000000', 7, '已终止', 'termination', 'wf_business_status', '', 'danger', 'N', 103, 1, sysdate(), NULL,NULL, '已终止'); +INSERT INTO sys_dict_data VALUES (46, '000000', 1, '自定义表单', 'static', 'wf_form_type', '', 'success', 'N', 103, 1, sysdate(), NULL, NULL,'自定义表单'); +INSERT INTO sys_dict_data VALUES (47, '000000', 2, '动态表单', 'dynamic', 'wf_form_type', '', 'primary', 'N', 103, 1, sysdate(), NULL, NULL,'动态表单'); +INSERT INTO sys_dict_data VALUES (48, '000000', 1, '撤销', 'cancel', 'wf_task_status', '', 'danger', 'N', 103, 1, sysdate(), NULL, NULL, '撤销'); +INSERT INTO sys_dict_data VALUES (49, '000000', 2, '通过', 'pass', 'wf_task_status', '', 'success', 'N', 103, 1, sysdate(), NULL, NULL, '通过'); +INSERT INTO sys_dict_data VALUES (50, '000000', 3, '待审核', 'waiting', 'wf_task_status', '', 'primary', 'N', 103, 1, sysdate(), NULL, NULL, '待审核'); +INSERT INTO sys_dict_data VALUES (51, '000000', 4, '作废', 'invalid', 'wf_task_status', '', 'danger', 'N', 103, 1, sysdate(), NULL, NULL, '作废'); +INSERT INTO sys_dict_data VALUES (52, '000000', 5, '退回', 'back', 'wf_task_status', '', 'danger', 'N', 103, 1, sysdate(), NULL, NULL, '退回'); +INSERT INTO sys_dict_data VALUES (53, '000000', 6, '终止', 'termination', 'wf_task_status', '', 'danger', 'N', 103, 1, sysdate(), NULL, NULL, '终止'); +INSERT INTO sys_dict_data VALUES (54, '000000', 7, '转办', 'transfer', 'wf_task_status', '', 'primary', 'N', 103, 1, sysdate(), NULL, NULL, '转办'); +INSERT INTO sys_dict_data VALUES (55, '000000', 8, '委托', 'depute', 'wf_task_status', '', 'primary', 'N', 103, 1, sysdate(), NULL, NULL, '委托'); +INSERT INTO sys_dict_data VALUES (56, '000000', 9, '抄送', 'copy', 'wf_task_status', '', 'primary', 'N', 103, 1, sysdate(), NULL, NULL, '抄送'); +INSERT INTO sys_dict_data VALUES (57, '000000', 10, '加签', 'sign', 'wf_task_status', '', 'primary', 'N', 103, 1, sysdate(), NULL, NULL, '加签'); +INSERT INTO sys_dict_data VALUES (58, '000000', 11, '减签', 'sign_off', 'wf_task_status', '', 'danger', 'N', 103, 1, sysdate(), NULL, NULL, '减签'); +INSERT INTO sys_dict_data VALUES (59, '000000', 11, '超时', 'timeout', 'wf_task_status', '', 'danger', 'N', 103, 1, sysdate(), NULL, NULL, '超时'); - -INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11638, '请假申请', 5, 1, 'leave', 'workflow/leave/index', 1, 0, 'C', '0', '0', 'workflow:leave:list', '#', 103, 1, sysdate(), NULL, NULL, '请假申请菜单'); -INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11639, '请假申请查询', 11638, 1, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:query', '#', 103, 1, sysdate(), NULL, NULL, ''); -INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11640, '请假申请新增', 11638, 2, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:add', '#', 103, 1, sysdate(), NULL, NULL, ''); -INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11641, '请假申请修改', 11638, 3, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:edit', '#', 103, 1, sysdate(), NULL, NULL, ''); -INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11642, '请假申请删除', 11638, 4, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:remove', '#', 103, 1, sysdate(), NULL, NULL, ''); -INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11643, '请假申请导出', 11638, 5, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:export', '#', 103, 1, sysdate(), NULL, NULL, ''); - -INSERT INTO sys_dict_type(dict_id, tenant_id, dict_name, dict_type, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (13, '000000', '业务状态', 'wf_business_status', 103, 1, sysdate(), NULL, NULL, '业务状态列表'); -INSERT INTO sys_dict_type(dict_id, tenant_id, dict_name, dict_type, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (14, '000000', '表单类型', 'wf_form_type', 103, 1, sysdate(), NULL, NULL, '表单类型列表'); - -INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (39, '000000', 1, '已撤销', 'cancel', 'wf_business_status', '', 'danger', 'N', 103, 1, sysdate(), NULL, NULL, '已撤销'); -INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (40, '000000', 2, '草稿', 'draft', 'wf_business_status', '', 'info', 'N', 103, 1, sysdate(), NULL, NULL, '草稿'); -INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (41, '000000', 3, '待审核', 'waiting', 'wf_business_status', '', 'primary', 'N', 103, 1,sysdate(), NULL, NULL, '待审核'); -INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (42, '000000', 4, '已完成', 'finish', 'wf_business_status', '', 'success', 'N', 103, 1, sysdate(), NULL, NULL, '已完成'); -INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (43, '000000', 5, '已作废', 'invalid', 'wf_business_status', '', 'danger', 'N', 103, 1, sysdate(), NULL, NULL, '已作废'); -INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (44, '000000', 6, '已退回', 'back', 'wf_business_status', '', 'danger', 'N', 103, 1, sysdate(), NULL, NULL, '已退回'); -INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (45, '000000', 7, '已终止', 'termination', 'wf_business_status', '', 'danger', 'N', 103, 1,sysdate(), NULL, NULL, '已终止'); -INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (46, '000000', 1, '自定义表单', 'static', 'wf_form_type', '', 'success', 'N', 103, 1, sysdate(), NULL, NULL, '自定义表单'); -INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (47, '000000', 2, '动态表单', 'dynamic', 'wf_form_type', '', 'primary', 'N', 103, 1, sysdate(), NULL, NULL, '动态表单'); - --- 表单管理 SQL -insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) -values(11628, '表单管理', '11616', '5', 'formManage', 'workflow/formManage/index', 1, 0, 'C', '0', '0', 'workflow:formManage:list', 'tree-table', 103, 1, sysdate(), null, null, '表单管理菜单'); - --- 表单管理按钮 SQL -insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) -values(11644, '表单管理查询', 11628, '1', '#', '', 1, 0, 'F', '0', '0', 'workflow:formManage:query', '', 103, 1, sysdate(), null, null, ''); - -insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) -values(11645, '表单管理新增', 11628, '2', '#', '', 1, 0, 'F', '0', '0', 'workflow:formManage:add', '', 103, 1, sysdate(), null, null, ''); - -insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) -values(11646, '表单管理修改', 11628, '3', '#', '', 1, 0, 'F', '0', '0', 'workflow:formManage:edit', '', 103, 1, sysdate(), null, null, ''); - -insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) -values(11647, '表单管理删除', 11628, '4', '#', '', 1, 0, 'F', '0', '0', 'workflow:formManage:remove', '', 103, 1, sysdate(), null, null, ''); - -insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) -values(11648, '表单管理导出', 11628, '5', '#', '', 1, 0, 'F', '0', '0', 'workflow:formManage:export', 'tree-table', 103, 1, sysdate(), null, null, ''); diff --git a/script/sql/sqlserver/sqlserver_ry_job.sql b/script/sql/sqlserver/sqlserver_ry_job.sql index bcf87f668..97addc3aa 100644 --- a/script/sql/sqlserver/sqlserver_ry_job.sql +++ b/script/sql/sqlserver/sqlserver_ry_job.sql @@ -2,7 +2,7 @@ SnailJob Database Transfer Tool Source Server Type : MySQL Target Server Type : Microsoft SQL Server - Date: 2024-07-06 12:55:47 + Date: 2024-12-27 22:24:37 */ @@ -212,7 +212,7 @@ CREATE TABLE sj_notify_config id bigint NOT NULL PRIMARY KEY IDENTITY, namespace_id nvarchar(64) NOT NULL DEFAULT '764d604ec6fc45f68cd92514c40e9e1a', group_name nvarchar(64) NOT NULL, - business_id nvarchar(64) NOT NULL, + notify_name nvarchar(64) NOT NULL DEFAULT '', system_task_type tinyint NOT NULL DEFAULT 3, notify_status tinyint NOT NULL DEFAULT 0, recipient_ids nvarchar(128) NOT NULL, @@ -226,7 +226,7 @@ CREATE TABLE sj_notify_config ) GO -CREATE INDEX idx_sj_notify_config_01 ON sj_notify_config (namespace_id, group_name, business_id) +CREATE INDEX idx_sj_notify_config_01 ON sj_notify_config (namespace_id, group_name) GO EXEC sp_addextendedproperty @@ -251,10 +251,10 @@ EXEC sp_addextendedproperty GO EXEC sp_addextendedproperty - 'MS_Description', N'业务id ( job_id或workflow_id或scene_name ) ', + 'MS_Description', N'通知名称', 'SCHEMA', N'dbo', 'TABLE', N'sj_notify_config', - 'COLUMN', N'business_id' + 'COLUMN', N'notify_name' GO EXEC sp_addextendedproperty @@ -917,6 +917,7 @@ CREATE TABLE sj_retry_scene_config max_retry_count int NOT NULL DEFAULT 5, back_off tinyint NOT NULL DEFAULT 1, trigger_interval nvarchar(16) NOT NULL DEFAULT '', + notify_ids nvarchar(128) NOT NULL DEFAULT '', deadline_request bigint NOT NULL DEFAULT 60000, executor_timeout int NOT NULL DEFAULT 5, route_key tinyint NOT NULL DEFAULT 4, @@ -985,6 +986,13 @@ EXEC sp_addextendedproperty 'COLUMN', N'trigger_interval' GO +EXEC sp_addextendedproperty + 'MS_Description', N'通知告警场景配置id列表', + 'SCHEMA', N'dbo', + 'TABLE', N'sj_retry_scene_config', + 'COLUMN', N'notify_ids' +GO + EXEC sp_addextendedproperty 'MS_Description', N'Deadline Request 调用链超时 单位毫秒', 'SCHEMA', N'dbo', @@ -1415,6 +1423,8 @@ CREATE TABLE sj_job retry_interval int NOT NULL DEFAULT 0, bucket_index int NOT NULL DEFAULT 0, resident tinyint NOT NULL DEFAULT 0, + notify_ids nvarchar(128) NOT NULL DEFAULT '', + owner_id bigint NULL, description nvarchar(256) NOT NULL DEFAULT '', ext_attrs nvarchar(256) NULL DEFAULT '', deleted tinyint NOT NULL DEFAULT 0, @@ -1577,6 +1587,20 @@ EXEC sp_addextendedproperty 'COLUMN', N'resident' GO +EXEC sp_addextendedproperty + 'MS_Description', N'通知告警场景配置id列表', + 'SCHEMA', N'dbo', + 'TABLE', N'sj_job', + 'COLUMN', N'notify_ids' +GO + +EXEC sp_addextendedproperty + 'MS_Description', N'负责人id', + 'SCHEMA', N'dbo', + 'TABLE', N'sj_job', + 'COLUMN', N'owner_id' +GO + EXEC sp_addextendedproperty 'MS_Description', N'描述', 'SCHEMA', N'dbo', @@ -1618,7 +1642,7 @@ EXEC sp_addextendedproperty 'TABLE', N'sj_job' GO -INSERT INTO sj_job (namespace_id, group_name, job_name, args_str, args_type, next_trigger_at, job_status, task_type, route_key, executor_type, executor_info, trigger_type, trigger_interval, block_strategy,executor_timeout, max_retry_times, parallel_num, retry_interval, bucket_index, resident, description, ext_attrs, deleted, create_dt, update_dt) VALUES (N'dev', N'ruoyi_group', N'demo-job', null, 1, 1710344035622, 1, 1, 4, 1, N'testJobExecutor', 2, N'60', 1, 60, 3, 1, 1, 116, 0, N'', N'', 0, getdate(), getdate()) +INSERT INTO sj_job (namespace_id, group_name, job_name, args_str, args_type, next_trigger_at, job_status, task_type, route_key, executor_type, executor_info, trigger_type, trigger_interval, block_strategy,executor_timeout, max_retry_times, parallel_num, retry_interval, bucket_index, resident, notify_ids, owner_id, description, ext_attrs, deleted, create_dt, update_dt) VALUES (N'dev', N'ruoyi_group', N'demo-job', null, 1, 1710344035622, 1, 1, 4, 1, N'testJobExecutor', 2, N'60', 1, 60, 3, 1, 1, 116, 0, N'', 1, N'', N'', 0, getdate(), getdate()) GO -- sj_job_log_message @@ -2308,6 +2332,7 @@ CREATE TABLE sj_workflow description nvarchar(256) NOT NULL DEFAULT '', flow_info nvarchar(max) NULL DEFAULT NULL, wf_context nvarchar(max) NULL DEFAULT NULL, + notify_ids nvarchar(128) NOT NULL DEFAULT '', bucket_index int NOT NULL DEFAULT 0, version int NOT NULL, ext_attrs nvarchar(256) NULL DEFAULT '', @@ -2413,6 +2438,13 @@ EXEC sp_addextendedproperty 'COLUMN', N'wf_context' GO +EXEC sp_addextendedproperty + 'MS_Description', N'通知告警场景配置id列表', + 'SCHEMA', N'dbo', + 'TABLE', N'sj_workflow', + 'COLUMN', N'notify_ids' +GO + EXEC sp_addextendedproperty 'MS_Description', N'bucket', 'SCHEMA', N'dbo', @@ -2744,4 +2776,3 @@ EXEC sp_addextendedproperty 'SCHEMA', N'dbo', 'TABLE', N'sj_workflow_task_batch' GO - diff --git a/script/sql/sqlserver/sqlserver_ry_vue_5.X.sql b/script/sql/sqlserver/sqlserver_ry_vue_5.X.sql index ad9a0b5f1..4607fb246 100644 --- a/script/sql/sqlserver/sqlserver_ry_vue_5.X.sql +++ b/script/sql/sqlserver/sqlserver_ry_vue_5.X.sql @@ -2,7 +2,7 @@ create table sys_social ( id bigint NOT NULL, user_id bigint NOT NULL, - tenant_id nvarchar(20) NULL, + tenant_id nvarchar(20) DEFAULT ('000000') NULL, auth_id nvarchar(255) NOT NULL, source nvarchar(255) NOT NULL, open_id nvarchar(255) NULL, @@ -175,7 +175,7 @@ EXEC sys.sp_addextendedproperty 'COLUMN', N'oauth_token_secret' GO EXEC sys.sp_addextendedproperty - 'MS_Description', N'删除标志(0代表存在 2代表删除)' , + 'MS_Description', N'删除标志(0代表存在 1代表删除)' , 'SCHEMA', N'dbo', 'TABLE', N'sys_social', 'COLUMN', N'del_flag' @@ -210,7 +210,11 @@ EXEC sys.sp_addextendedproperty 'TABLE', N'sys_social', 'COLUMN', N'update_time' GO - +EXEC sp_addextendedproperty + 'MS_Description', N'社会化关系表', + 'SCHEMA', N'dbo', + 'TABLE', N'sys_social' +GO CREATE TABLE sys_tenant ( @@ -326,7 +330,7 @@ EXEC sys.sp_addextendedproperty 'COLUMN', N'status' GO EXEC sys.sp_addextendedproperty - 'MS_Description', N'删除标志(0代表存在 2代表删除)' , + 'MS_Description', N'删除标志(0代表存在 1代表删除)' , 'SCHEMA', N'dbo', 'TABLE', N'sys_tenant', 'COLUMN', N'del_flag' @@ -423,7 +427,7 @@ EXEC sys.sp_addextendedproperty 'COLUMN', N'status' GO EXEC sys.sp_addextendedproperty - 'MS_Description', N'删除标志(0代表存在 2代表删除)' , + 'MS_Description', N'删除标志(0代表存在 1代表删除)' , 'SCHEMA', N'dbo', 'TABLE', N'sys_tenant_package', 'COLUMN', N'del_flag' @@ -1013,7 +1017,7 @@ EXEC sys.sp_addextendedproperty 'COLUMN', N'status' GO EXEC sys.sp_addextendedproperty - 'MS_Description', N'删除标志(0代表存在 2代表删除)' , + 'MS_Description', N'删除标志(0代表存在 1代表删除)' , 'SCHEMA', N'dbo', 'TABLE', N'sys_dept', 'COLUMN', N'del_flag' @@ -2002,10 +2006,10 @@ CREATE TABLE sys_oper_log oper_url nvarchar(255) DEFAULT '' NULL, oper_ip nvarchar(128) DEFAULT '' NULL, oper_location nvarchar(255) DEFAULT '' NULL, - oper_param nvarchar(2000) DEFAULT '' NULL, - json_result nvarchar(2000) DEFAULT '' NULL, + oper_param nvarchar(4000) DEFAULT '' NULL, + json_result nvarchar(4000) DEFAULT '' NULL, status int DEFAULT ((0)) NULL, - error_msg nvarchar(2000) DEFAULT '' NULL, + error_msg nvarchar(4000) DEFAULT '' NULL, oper_time datetime2(7) NULL, cost_time bigint DEFAULT ((0)) NULL, CONSTRAINT PK__sys_oper__34723BF9BD954573 PRIMARY KEY CLUSTERED (oper_id) @@ -2338,7 +2342,7 @@ EXEC sys.sp_addextendedproperty 'COLUMN', N'status' GO EXEC sys.sp_addextendedproperty - 'MS_Description', N'删除标志(0代表存在 2代表删除)' , + 'MS_Description', N'删除标志(0代表存在 1代表删除)' , 'SCHEMA', N'dbo', 'TABLE', N'sys_role', 'COLUMN', N'del_flag' @@ -2723,7 +2727,7 @@ EXEC sys.sp_addextendedproperty 'COLUMN', N'status' GO EXEC sys.sp_addextendedproperty - 'MS_Description', N'删除标志(0代表存在 2代表删除)' , + 'MS_Description', N'删除标志(0代表存在 1代表删除)' , 'SCHEMA', N'dbo', 'TABLE', N'sys_user', 'COLUMN', N'del_flag' @@ -3202,7 +3206,7 @@ EXEC sp_addextendedproperty 'COLUMN', N'status' GO EXEC sp_addextendedproperty - 'MS_Description', N'删除标志(0代表存在 2代表删除)', + 'MS_Description', N'删除标志(0代表存在 1代表删除)', 'SCHEMA', N'dbo', 'TABLE', N'sys_client', 'COLUMN', N'del_flag' diff --git a/script/sql/sqlserver/sqlserver_ry_workflow.sql b/script/sql/sqlserver/sqlserver_ry_workflow.sql index 2397c35f2..ea4b7205a 100644 --- a/script/sql/sqlserver/sqlserver_ry_workflow.sql +++ b/script/sql/sqlserver/sqlserver_ry_workflow.sql @@ -1,456 +1,1336 @@ -insert into sys_menu values('11616', '工作流' , '0', '6', 'workflow', '', '', '1', '0', 'M', '0', '0', '', 'workflow', 103, 1, getdate(), NULL, NULL, ''); -insert into sys_menu values('11617', '模型管理', '11616', '2', 'model', 'workflow/model/index', '', '1', '1', 'C', '0', '0', 'workflow:model:list', 'model', 103, 1, getdate(), NULL, NULL, ''); -insert into sys_menu values('11618', '我的任务', '0', '7', 'task', '', '', '1', '0', 'M', '0', '0', '', 'my-task', 103, 1, getdate(), NULL, NULL, ''); -insert into sys_menu values('11619', '我的待办', '11618', '2', 'taskWaiting', 'workflow/task/taskWaiting', '', '1', '1', 'C', '0', '0', '', 'waiting', 103, 1, getdate(), NULL, NULL, ''); -insert into sys_menu values('11632', '我的已办', '11618', '3', 'taskFinish', 'workflow/task/taskFinish', '', '1', '1', 'C', '0', '0', '', 'finish', 103, 1, getdate(), NULL, NULL, ''); -insert into sys_menu values('11633', '我的抄送', '11618', '4', 'taskCopyList', 'workflow/task/taskCopyList', '', '1', '1', 'C', '0', '0', '', 'my-copy', 103, 1, getdate(), NULL, NULL, ''); -insert into sys_menu values('11620', '流程定义', '11616', '3', 'processDefinition', 'workflow/processDefinition/index', '', '1', '1', 'C', '0', '0', '', 'process-definition', 103, 1, getdate(), NULL, NULL, ''); -insert into sys_menu values('11621', '流程实例', '11630', '1', 'processInstance', 'workflow/processInstance/index', '', '1', '1', 'C', '0', '0', '', 'tree-table', 103, 1, getdate(), NULL, NULL, ''); -insert into sys_menu values('11622', '流程分类', '11616', '1', 'category', 'workflow/category/index', '', '1', '0', 'C', '0', '0', 'workflow:category:list', 'category', 103, 1, getdate(), NULL, NULL, ''); -insert into sys_menu values('11629', '我发起的', '11618', '1', 'myDocument', 'workflow/task/myDocument', '', '1', '1', 'C', '0', '0', '', 'guide', 103, 1, getdate(), NULL, NULL, ''); -insert into sys_menu values('11630', '流程监控', '11616', '4', 'monitor', '', '', '1', '0', 'M', '0', '0', '', 'monitor', 103, 1, getdate(), NULL, NULL, ''); -insert into sys_menu values('11631', '待办任务', '11630', '2', 'allTaskWaiting', 'workflow/task/allTaskWaiting', '', '1', '1', 'C', '0', '0', '', 'waiting', 103, 1, getdate(), NULL, NULL, ''); +CREATE TABLE flow_definition ( + id bigint NOT NULL, + flow_code nvarchar(40) NOT NULL, + flow_name nvarchar(100) NOT NULL, + category nvarchar(100) NULL, + version nvarchar(20) NOT NULL, + is_publish tinyint DEFAULT('0') NULL, + form_custom nchar(1) DEFAULT('N') NULL, + form_path nvarchar(100) NULL, + activity_status tinyint DEFAULT('1') NULL, + listener_type nvarchar(100) NULL, + listener_path nvarchar(400) NULL, + ext nvarchar(500) NULL, + create_time datetime2(7) NULL, + update_time datetime2(7) NULL, + del_flag nchar(1) DEFAULT('0') NULL, + tenant_id nvarchar(40) NULL, + CONSTRAINT PK__flow_def__3213E83FEE39AE33 PRIMARY KEY CLUSTERED (id) + WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) + ON [PRIMARY] +) +ON [PRIMARY] +GO +EXEC sp_addextendedproperty +'MS_Description', N'主键id', +'SCHEMA', N'dbo', +'TABLE', N'flow_definition', +'COLUMN', N'id' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'流程编码', +'SCHEMA', N'dbo', +'TABLE', N'flow_definition', +'COLUMN', N'flow_code' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'流程名称', +'SCHEMA', N'dbo', +'TABLE', N'flow_definition', +'COLUMN', N'flow_name' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'流程类别', +'SCHEMA', N'dbo', +'TABLE', N'flow_definition', +'COLUMN', N'category' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'流程版本', +'SCHEMA', N'dbo', +'TABLE', N'flow_definition', +'COLUMN', N'version' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'是否发布(0未发布 1已发布 9失效)', +'SCHEMA', N'dbo', +'TABLE', N'flow_definition', +'COLUMN', N'is_publish' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'审批表单是否自定义(Y是 N否)', +'SCHEMA', N'dbo', +'TABLE', N'flow_definition', +'COLUMN', N'form_custom' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'审批表单路径', +'SCHEMA', N'dbo', +'TABLE', N'flow_definition', +'COLUMN', N'form_path' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'流程激活状态(0挂起 1激活)', +'SCHEMA', N'dbo', +'TABLE', N'flow_definition', +'COLUMN', N'activity_status' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'监听器类型', +'SCHEMA', N'dbo', +'TABLE', N'flow_definition', +'COLUMN', N'listener_type' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'监听器路径', +'SCHEMA', N'dbo', +'TABLE', N'flow_definition', +'COLUMN', N'listener_path' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'业务详情 存业务表对象json字符串', +'SCHEMA', N'dbo', +'TABLE', N'flow_definition', +'COLUMN', N'ext' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'创建时间', +'SCHEMA', N'dbo', +'TABLE', N'flow_definition', +'COLUMN', N'create_time' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'更新时间', +'SCHEMA', N'dbo', +'TABLE', N'flow_definition', +'COLUMN', N'update_time' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'删除标志', +'SCHEMA', N'dbo', +'TABLE', N'flow_definition', +'COLUMN', N'del_flag' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'租户id', +'SCHEMA', N'dbo', +'TABLE', N'flow_definition', +'COLUMN', N'tenant_id' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'流程定义表', +'SCHEMA', N'dbo', +'TABLE', N'flow_definition' +GO + +CREATE TABLE flow_node ( + id bigint NOT NULL, + node_type tinyint NOT NULL, + definition_id bigint NOT NULL, + node_code nvarchar(100) NOT NULL, + node_name nvarchar(100) NULL, + permission_flag nvarchar(200) NULL, + node_ratio decimal(6,3) NULL, + coordinate nvarchar(100) NULL, + skip_any_node nvarchar(100) DEFAULT('N') NULL, + any_node_skip nvarchar(100) NULL, + listener_type nvarchar(100) NULL, + listener_path nvarchar(400) NULL, + handler_type nvarchar(100) NULL, + handler_path nvarchar(400) NULL, + form_custom nchar(1) DEFAULT('N') NULL, + form_path nvarchar(100) NULL, + version nvarchar(20) NOT NULL, + create_time datetime2(7) NULL, + update_time datetime2(7) NULL, + del_flag nchar(1) DEFAULT('0') NULL, + tenant_id nvarchar(40) NULL, + CONSTRAINT PK__flow_nod__3213E83F372470DE PRIMARY KEY CLUSTERED (id) + WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) + ON [PRIMARY] +) +ON [PRIMARY] +GO + +EXEC sp_addextendedproperty +'MS_Description', N'主键id', +'SCHEMA', N'dbo', +'TABLE', N'flow_node', +'COLUMN', N'id' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)', +'SCHEMA', N'dbo', +'TABLE', N'flow_node', +'COLUMN', N'node_type' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'流程定义id', +'SCHEMA', N'dbo', +'TABLE', N'flow_node', +'COLUMN', N'definition_id' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'流程节点编码', +'SCHEMA', N'dbo', +'TABLE', N'flow_node', +'COLUMN', N'node_code' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'流程节点名称', +'SCHEMA', N'dbo', +'TABLE', N'flow_node', +'COLUMN', N'node_name' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'权限标识(权限类型:权限标识,可以多个,用逗号隔开)', +'SCHEMA', N'dbo', +'TABLE', N'flow_node', +'COLUMN', N'permission_flag' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'流程签署比例值', +'SCHEMA', N'dbo', +'TABLE', N'flow_node', +'COLUMN', N'node_ratio' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'坐标', +'SCHEMA', N'dbo', +'TABLE', N'flow_node', +'COLUMN', N'coordinate' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'是否可以退回任意节点(Y是 N否)即将删除', +'SCHEMA', N'dbo', +'TABLE', N'flow_node', +'COLUMN', N'skip_any_node' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'任意结点跳转', +'SCHEMA', N'dbo', +'TABLE', N'flow_node', +'COLUMN', N'any_node_skip' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'监听器类型', +'SCHEMA', N'dbo', +'TABLE', N'flow_node', +'COLUMN', N'listener_type' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'监听器路径', +'SCHEMA', N'dbo', +'TABLE', N'flow_node', +'COLUMN', N'listener_path' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'处理器类型', +'SCHEMA', N'dbo', +'TABLE', N'flow_node', +'COLUMN', N'handler_type' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'处理器路径', +'SCHEMA', N'dbo', +'TABLE', N'flow_node', +'COLUMN', N'handler_path' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'审批表单是否自定义(Y是 N否)', +'SCHEMA', N'dbo', +'TABLE', N'flow_node', +'COLUMN', N'form_custom' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'审批表单路径', +'SCHEMA', N'dbo', +'TABLE', N'flow_node', +'COLUMN', N'form_path' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'版本', +'SCHEMA', N'dbo', +'TABLE', N'flow_node', +'COLUMN', N'version' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'创建时间', +'SCHEMA', N'dbo', +'TABLE', N'flow_node', +'COLUMN', N'create_time' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'更新时间', +'SCHEMA', N'dbo', +'TABLE', N'flow_node', +'COLUMN', N'update_time' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'删除标志', +'SCHEMA', N'dbo', +'TABLE', N'flow_node', +'COLUMN', N'del_flag' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'租户id', +'SCHEMA', N'dbo', +'TABLE', N'flow_node', +'COLUMN', N'tenant_id' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'流程节点表', +'SCHEMA', N'dbo', +'TABLE', N'flow_node' +GO + +CREATE TABLE flow_skip ( + id bigint NOT NULL, + definition_id bigint NOT NULL, + now_node_code nvarchar(100) NOT NULL, + now_node_type tinyint NULL, + next_node_code nvarchar(100) NOT NULL, + next_node_type tinyint NULL, + skip_name nvarchar(100) NULL, + skip_type nvarchar(40) NULL, + skip_condition nvarchar(200) NULL, + coordinate nvarchar(100) NULL, + create_time datetime2(7) NULL, + update_time datetime2(7) NULL, + del_flag nchar(1) DEFAULT('0') NULL, + tenant_id nvarchar(40) NULL, + CONSTRAINT PK__flow_ski__3213E83F073FEE6E PRIMARY KEY CLUSTERED (id) + WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) + ON [PRIMARY] +) +ON [PRIMARY] +GO + +EXEC sp_addextendedproperty +'MS_Description', N'主键id', +'SCHEMA', N'dbo', +'TABLE', N'flow_skip', +'COLUMN', N'id' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'流程定义id', +'SCHEMA', N'dbo', +'TABLE', N'flow_skip', +'COLUMN', N'definition_id' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'当前流程节点的编码', +'SCHEMA', N'dbo', +'TABLE', N'flow_skip', +'COLUMN', N'now_node_code' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'当前节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)', +'SCHEMA', N'dbo', +'TABLE', N'flow_skip', +'COLUMN', N'now_node_type' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'下一个流程节点的编码', +'SCHEMA', N'dbo', +'TABLE', N'flow_skip', +'COLUMN', N'next_node_code' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'下一个节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)', +'SCHEMA', N'dbo', +'TABLE', N'flow_skip', +'COLUMN', N'next_node_type' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'跳转名称', +'SCHEMA', N'dbo', +'TABLE', N'flow_skip', +'COLUMN', N'skip_name' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'跳转类型(PASS审批通过 REJECT退回)', +'SCHEMA', N'dbo', +'TABLE', N'flow_skip', +'COLUMN', N'skip_type' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'跳转条件', +'SCHEMA', N'dbo', +'TABLE', N'flow_skip', +'COLUMN', N'skip_condition' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'坐标', +'SCHEMA', N'dbo', +'TABLE', N'flow_skip', +'COLUMN', N'coordinate' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'创建时间', +'SCHEMA', N'dbo', +'TABLE', N'flow_skip', +'COLUMN', N'create_time' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'更新时间', +'SCHEMA', N'dbo', +'TABLE', N'flow_skip', +'COLUMN', N'update_time' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'删除标志', +'SCHEMA', N'dbo', +'TABLE', N'flow_skip', +'COLUMN', N'del_flag' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'租户id', +'SCHEMA', N'dbo', +'TABLE', N'flow_skip', +'COLUMN', N'tenant_id' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'节点跳转关联表', +'SCHEMA', N'dbo', +'TABLE', N'flow_skip' +GO + +CREATE TABLE flow_instance ( + id bigint NOT NULL, + definition_id bigint NOT NULL, + business_id nvarchar(40) NOT NULL, + node_type tinyint NOT NULL, + node_code nvarchar(40) NOT NULL, + node_name nvarchar(100) NULL, + variable nvarchar(max) NULL, + flow_status nvarchar(20) NOT NULL, + activity_status tinyint DEFAULT('1') NULL, + def_json nvarchar(max) NULL, + create_by nvarchar(64) NULL, + create_time datetime2(7) NULL, + update_time datetime2(7) NULL, + ext nvarchar(500) NULL, + del_flag nchar(1) DEFAULT('0') NULL, + tenant_id nvarchar(40) NULL, + CONSTRAINT PK__flow_ins__3213E83F5190FEE1 PRIMARY KEY CLUSTERED (id) + WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) + ON [PRIMARY] +) +ON [PRIMARY] +TEXTIMAGE_ON [PRIMARY] +GO + +EXEC sp_addextendedproperty +'MS_Description', N'主键id', +'SCHEMA', N'dbo', +'TABLE', N'flow_instance', +'COLUMN', N'id' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'对应flow_definition表的id', +'SCHEMA', N'dbo', +'TABLE', N'flow_instance', +'COLUMN', N'definition_id' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'业务id', +'SCHEMA', N'dbo', +'TABLE', N'flow_instance', +'COLUMN', N'business_id' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)', +'SCHEMA', N'dbo', +'TABLE', N'flow_instance', +'COLUMN', N'node_type' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'流程节点编码', +'SCHEMA', N'dbo', +'TABLE', N'flow_instance', +'COLUMN', N'node_code' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'流程节点名称', +'SCHEMA', N'dbo', +'TABLE', N'flow_instance', +'COLUMN', N'node_name' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'任务变量', +'SCHEMA', N'dbo', +'TABLE', N'flow_instance', +'COLUMN', N'variable' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'流程状态(0待提交 1审批中 2 审批通过 3自动通过 4终止 5作废 6撤销 7取回 8已完成 9已退回 10失效)', +'SCHEMA', N'dbo', +'TABLE', N'flow_instance', +'COLUMN', N'flow_status' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'流程激活状态(0挂起 1激活)', +'SCHEMA', N'dbo', +'TABLE', N'flow_instance', +'COLUMN', N'activity_status' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'流程定义json', +'SCHEMA', N'dbo', +'TABLE', N'flow_instance', +'COLUMN', N'def_json' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'创建者', +'SCHEMA', N'dbo', +'TABLE', N'flow_instance', +'COLUMN', N'create_by' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'创建时间', +'SCHEMA', N'dbo', +'TABLE', N'flow_instance', +'COLUMN', N'create_time' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'更新时间', +'SCHEMA', N'dbo', +'TABLE', N'flow_instance', +'COLUMN', N'update_time' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'扩展字段,预留给业务系统使用', +'SCHEMA', N'dbo', +'TABLE', N'flow_instance', +'COLUMN', N'ext' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'删除标志', +'SCHEMA', N'dbo', +'TABLE', N'flow_instance', +'COLUMN', N'del_flag' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'租户id', +'SCHEMA', N'dbo', +'TABLE', N'flow_instance', +'COLUMN', N'tenant_id' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'流程实例表', +'SCHEMA', N'dbo', +'TABLE', N'flow_instance' +GO + +CREATE TABLE flow_task ( + id bigint NOT NULL, + definition_id bigint NOT NULL, + instance_id bigint NOT NULL, + node_code nvarchar(100) NOT NULL, + node_name nvarchar(100) NULL, + node_type tinyint NOT NULL, + form_custom nchar(1) DEFAULT('N') NULL, + form_path nvarchar(100) NULL, + create_time datetime2(7) NULL, + update_time datetime2(7) NULL, + del_flag nchar(1) DEFAULT('0') NULL, + tenant_id nvarchar(40) NULL, + CONSTRAINT PK__flow_tas__3213E83F5AE1F1BA PRIMARY KEY CLUSTERED (id) + WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) + ON [PRIMARY] +) +ON [PRIMARY] +GO + +EXEC sp_addextendedproperty +'MS_Description', N'主键id', +'SCHEMA', N'dbo', +'TABLE', N'flow_task', +'COLUMN', N'id' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'对应flow_definition表的id', +'SCHEMA', N'dbo', +'TABLE', N'flow_task', +'COLUMN', N'definition_id' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'对应flow_instance表的id', +'SCHEMA', N'dbo', +'TABLE', N'flow_task', +'COLUMN', N'instance_id' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'节点编码', +'SCHEMA', N'dbo', +'TABLE', N'flow_task', +'COLUMN', N'node_code' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'节点名称', +'SCHEMA', N'dbo', +'TABLE', N'flow_task', +'COLUMN', N'node_name' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)', +'SCHEMA', N'dbo', +'TABLE', N'flow_task', +'COLUMN', N'node_type' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'审批表单是否自定义(Y是 N否)', +'SCHEMA', N'dbo', +'TABLE', N'flow_task', +'COLUMN', N'form_custom' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'审批表单路径', +'SCHEMA', N'dbo', +'TABLE', N'flow_task', +'COLUMN', N'form_path' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'创建时间', +'SCHEMA', N'dbo', +'TABLE', N'flow_task', +'COLUMN', N'create_time' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'更新时间', +'SCHEMA', N'dbo', +'TABLE', N'flow_task', +'COLUMN', N'update_time' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'删除标志', +'SCHEMA', N'dbo', +'TABLE', N'flow_task', +'COLUMN', N'del_flag' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'租户id', +'SCHEMA', N'dbo', +'TABLE', N'flow_task', +'COLUMN', N'tenant_id' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'待办任务表', +'SCHEMA', N'dbo', +'TABLE', N'flow_task' +GO + +CREATE TABLE flow_his_task ( + id bigint NOT NULL, + definition_id bigint NOT NULL, + instance_id bigint NOT NULL, + task_id bigint NOT NULL, + node_code nvarchar(200) NULL, + node_name nvarchar(200) NULL, + node_type tinyint NULL, + target_node_code nvarchar(100) NULL, + target_node_name nvarchar(100) NULL, + approver nvarchar(40) NULL, + cooperate_type tinyint DEFAULT('0') NULL, + collaborator nvarchar(40) NULL, + skip_type nvarchar(10) NOT NULL, + flow_status nvarchar(20) NOT NULL, + form_custom nchar(1) DEFAULT('N') NULL, + form_path nvarchar(100) NULL, + message nvarchar(500) NULL, + variable nvarchar(max) NULL, + ext nvarchar(500) NULL, + create_time datetime2(7) NULL, + update_time datetime2(7) NULL, + del_flag nchar(1) DEFAULT('0') NULL, + tenant_id nvarchar(40) NULL, + CONSTRAINT PK__flow_his__3213E83F67951564 PRIMARY KEY CLUSTERED (id) + WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) + ON [PRIMARY] +) +ON [PRIMARY] +GO + +EXEC sp_addextendedproperty +'MS_Description', N'主键id', +'SCHEMA', N'dbo', +'TABLE', N'flow_his_task', +'COLUMN', N'id' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'对应flow_definition表的id', +'SCHEMA', N'dbo', +'TABLE', N'flow_his_task', +'COLUMN', N'definition_id' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'对应flow_instance表的id', +'SCHEMA', N'dbo', +'TABLE', N'flow_his_task', +'COLUMN', N'instance_id' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'对应flow_task表的id', +'SCHEMA', N'dbo', +'TABLE', N'flow_his_task', +'COLUMN', N'task_id' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'开始节点编码', +'SCHEMA', N'dbo', +'TABLE', N'flow_his_task', +'COLUMN', N'node_code' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'开始节点名称', +'SCHEMA', N'dbo', +'TABLE', N'flow_his_task', +'COLUMN', N'node_name' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'开始节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)', +'SCHEMA', N'dbo', +'TABLE', N'flow_his_task', +'COLUMN', N'node_type' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'目标节点编码', +'SCHEMA', N'dbo', +'TABLE', N'flow_his_task', +'COLUMN', N'target_node_code' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'结束节点名称', +'SCHEMA', N'dbo', +'TABLE', N'flow_his_task', +'COLUMN', N'target_node_name' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'审批者', +'SCHEMA', N'dbo', +'TABLE', N'flow_his_task', +'COLUMN', N'approver' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'协作方式(1审批 2转办 3委派 4会签 5票签 6加签 7减签)', +'SCHEMA', N'dbo', +'TABLE', N'flow_his_task', +'COLUMN', N'cooperate_type' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'协作人', +'SCHEMA', N'dbo', +'TABLE', N'flow_his_task', +'COLUMN', N'collaborator' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'流转类型(PASS通过 REJECT退回 NONE无动作)', +'SCHEMA', N'dbo', +'TABLE', N'flow_his_task', +'COLUMN', N'skip_type' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'流程状态(1审批中 2 审批通过 9已退回 10失效)', +'SCHEMA', N'dbo', +'TABLE', N'flow_his_task', +'COLUMN', N'flow_status' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'审批表单是否自定义(Y是 N否)', +'SCHEMA', N'dbo', +'TABLE', N'flow_his_task', +'COLUMN', N'form_custom' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'审批表单路径', +'SCHEMA', N'dbo', +'TABLE', N'flow_his_task', +'COLUMN', N'form_path' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'审批意见', +'SCHEMA', N'dbo', +'TABLE', N'flow_his_task', +'COLUMN', N'message' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'任务变量', +'SCHEMA', N'dbo', +'TABLE', N'flow_his_task', +'COLUMN', N'variable' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'业务详情 存业务表对象json字符串', +'SCHEMA', N'dbo', +'TABLE', N'flow_his_task', +'COLUMN', N'ext' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'任务开始时间', +'SCHEMA', N'dbo', +'TABLE', N'flow_his_task', +'COLUMN', N'create_time' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'审批完成时间', +'SCHEMA', N'dbo', +'TABLE', N'flow_his_task', +'COLUMN', N'update_time' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'删除标志', +'SCHEMA', N'dbo', +'TABLE', N'flow_his_task', +'COLUMN', N'del_flag' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'租户id', +'SCHEMA', N'dbo', +'TABLE', N'flow_his_task', +'COLUMN', N'tenant_id' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'历史任务记录表', +'SCHEMA', N'dbo', +'TABLE', N'flow_his_task' +GO + +CREATE TABLE flow_user ( + id bigint NOT NULL, + type nchar(1) NOT NULL, + processed_by nvarchar(80) NULL, + associated bigint NOT NULL, + create_time datetime2(7) NULL, + create_by nvarchar(80) NULL, + update_time datetime2(7) NULL, + del_flag nchar(1) DEFAULT('0') NULL, + tenant_id nvarchar(40) NULL, + CONSTRAINT PK__flow_use__3213E83FFA38CA8B PRIMARY KEY CLUSTERED (id) + WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) + ON [PRIMARY] +) +ON [PRIMARY] +GO + +CREATE NONCLUSTERED INDEX user_processed_type ON flow_user (processed_by ASC, type ASC) +GO + +EXEC sp_addextendedproperty +'MS_Description', N'主键id', +'SCHEMA', N'dbo', +'TABLE', N'flow_user', +'COLUMN', N'id' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'人员类型(1待办任务的审批人权限 2待办任务的转办人权限 3待办任务的委托人权限)', +'SCHEMA', N'dbo', +'TABLE', N'flow_user', +'COLUMN', N'type' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'权限人', +'SCHEMA', N'dbo', +'TABLE', N'flow_user', +'COLUMN', N'processed_by' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'任务表id', +'SCHEMA', N'dbo', +'TABLE', N'flow_user', +'COLUMN', N'associated' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'创建时间', +'SCHEMA', N'dbo', +'TABLE', N'flow_user', +'COLUMN', N'create_time' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'创建人', +'SCHEMA', N'dbo', +'TABLE', N'flow_user', +'COLUMN', N'create_by' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'更新时间', +'SCHEMA', N'dbo', +'TABLE', N'flow_user', +'COLUMN', N'update_time' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'删除标志', +'SCHEMA', N'dbo', +'TABLE', N'flow_user', +'COLUMN', N'del_flag' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'租户id', +'SCHEMA', N'dbo', +'TABLE', N'flow_user', +'COLUMN', N'tenant_id' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'流程用户表', +'SCHEMA', N'dbo', +'TABLE', N'flow_user' +GO + +CREATE TABLE flow_category ( + category_id bigint NOT NULL, + tenant_id nvarchar(20) DEFAULT('000000') NULL, + parent_id bigint DEFAULT(0) NULL, + ancestors nvarchar(500) DEFAULT('') NULL, + category_name nvarchar(30) NOT NULL, + order_num int DEFAULT(0) NULL, + del_flag nchar(1) DEFAULT('0') NULL, + create_dept bigint NULL, + create_by bigint NULL, + create_time datetime2(7) NULL, + update_by bigint NULL, + update_time datetime2(7) NULL, + CONSTRAINT PK__flow_cat__D54EE9B4AE98B9C1 PRIMARY KEY CLUSTERED (category_id) + WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) + ON [PRIMARY] +) +ON [PRIMARY] +GO + +EXEC sp_addextendedproperty +'MS_Description', N'流程分类ID', +'SCHEMA', N'dbo', +'TABLE', N'flow_category', +'COLUMN', N'category_id' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'租户编号', +'SCHEMA', N'dbo', +'TABLE', N'flow_category', +'COLUMN', N'tenant_id' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'父流程分类id', +'SCHEMA', N'dbo', +'TABLE', N'flow_category', +'COLUMN', N'parent_id' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'祖级列表', +'SCHEMA', N'dbo', +'TABLE', N'flow_category', +'COLUMN', N'ancestors' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'流程分类名称', +'SCHEMA', N'dbo', +'TABLE', N'flow_category', +'COLUMN', N'category_name' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'显示顺序', +'SCHEMA', N'dbo', +'TABLE', N'flow_category', +'COLUMN', N'order_num' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'删除标志(0代表存在 1代表删除)', +'SCHEMA', N'dbo', +'TABLE', N'flow_category', +'COLUMN', N'del_flag' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'创建部门', +'SCHEMA', N'dbo', +'TABLE', N'flow_category', +'COLUMN', N'create_dept' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'创建者', +'SCHEMA', N'dbo', +'TABLE', N'flow_category', +'COLUMN', N'create_by' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'创建时间', +'SCHEMA', N'dbo', +'TABLE', N'flow_category', +'COLUMN', N'create_time' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'更新者', +'SCHEMA', N'dbo', +'TABLE', N'flow_category', +'COLUMN', N'update_by' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'更新时间', +'SCHEMA', N'dbo', +'TABLE', N'flow_category', +'COLUMN', N'update_time' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'流程分类', +'SCHEMA', N'dbo', +'TABLE', N'flow_category' +GO + +INSERT flow_category VALUES (100, N'000000', 0, N'0', N'OA审批', 0, N'0', 103, 1, getdate(), NULL, NULL); +GO +INSERT flow_category VALUES (101, N'000000', 100, N'0,100', N'假勤管理', 0, N'0', 103, 1, getdate(), NULL, NULL); +GO +INSERT flow_category VALUES (102, N'000000', 100, N'0,100', N'人事管理', 1, N'0', 103, 1, getdate(), NULL, NULL); +GO +INSERT flow_category VALUES (103, N'000000', 101, N'0,100,101', N'请假', 0, N'0', 103, 1, getdate(), NULL, NULL); +GO +INSERT flow_category VALUES (104, N'000000', 101, N'0,100,101', N'出差', 1, N'0', 103, 1, getdate(), NULL, NULL); +GO +INSERT flow_category VALUES (105, N'000000', 101, N'0,100,101', N'加班', 2, N'0', 103, 1, getdate(), NULL, NULL); +GO +INSERT flow_category VALUES (106, N'000000', 101, N'0,100,101', N'换班', 3, N'0', 103, 1, getdate(), NULL, NULL); +GO +INSERT flow_category VALUES (107, N'000000', 101, N'0,100,101', N'外出', 4, N'0', 103, 1, getdate(), NULL, NULL); +GO +INSERT flow_category VALUES (108, N'000000', 102, N'0,100,102', N'转正', 1, N'0', 103, 1, getdate(), NULL, NULL); +GO +INSERT flow_category VALUES (109, N'000000', 102, N'0,100,102', N'离职', 2, N'0', 103, 1, getdate(), NULL, NULL); +GO + +CREATE TABLE test_leave ( + id bigint NOT NULL, + tenant_id nvarchar(20) DEFAULT('000000') NULL, + leave_type nvarchar(255) NOT NULL, + start_date datetime2(7) NOT NULL, + end_date datetime2(7) NOT NULL, + leave_days int NOT NULL, + remark nvarchar(255) NULL, + status nvarchar(255) NULL, + create_dept bigint NULL, + create_by bigint NULL, + create_time datetime2(7) NULL, + update_by bigint NULL, + update_time datetime2(7) NULL, + CONSTRAINT PK__test_lea__3213E83F348788FA PRIMARY KEY CLUSTERED (id) + WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) + ON [PRIMARY] +) +ON [PRIMARY] +GO + +EXEC sp_addextendedproperty +'MS_Description', N'id', +'SCHEMA', N'dbo', +'TABLE', N'test_leave', +'COLUMN', N'id' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'租户编号', +'SCHEMA', N'dbo', +'TABLE', N'test_leave', +'COLUMN', N'tenant_id' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'请假类型', +'SCHEMA', N'dbo', +'TABLE', N'test_leave', +'COLUMN', N'leave_type' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'开始时间', +'SCHEMA', N'dbo', +'TABLE', N'test_leave', +'COLUMN', N'start_date' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'结束时间', +'SCHEMA', N'dbo', +'TABLE', N'test_leave', +'COLUMN', N'end_date' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'请假天数', +'SCHEMA', N'dbo', +'TABLE', N'test_leave', +'COLUMN', N'leave_days' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'请假原因', +'SCHEMA', N'dbo', +'TABLE', N'test_leave', +'COLUMN', N'remark' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'状态', +'SCHEMA', N'dbo', +'TABLE', N'test_leave', +'COLUMN', N'status' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'创建部门', +'SCHEMA', N'dbo', +'TABLE', N'test_leave', +'COLUMN', N'create_dept' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'创建者', +'SCHEMA', N'dbo', +'TABLE', N'test_leave', +'COLUMN', N'create_by' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'创建时间', +'SCHEMA', N'dbo', +'TABLE', N'test_leave', +'COLUMN', N'create_time' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'更新者', +'SCHEMA', N'dbo', +'TABLE', N'test_leave', +'COLUMN', N'update_by' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'更新时间', +'SCHEMA', N'dbo', +'TABLE', N'test_leave', +'COLUMN', N'update_time' +GO + +EXEC sp_addextendedproperty +'MS_Description', N'请假申请表', +'SCHEMA', N'dbo', +'TABLE', N'test_leave' +GO + +INSERT sys_menu VALUES (11616, N'工作流', 0, 6, N'workflow', NULL, N'', 1, 0, N'M', N'0', N'0', N'', N'workflow', 103, 1, GETDATE(), NULL, NULL, N''); +GO +INSERT sys_menu VALUES (11618, N'我的任务', 0, 7, N'task', NULL, N'', 1, 0, N'M', N'0', N'0', N'', N'my-task', 103, 1, GETDATE(), NULL, NULL, N''); +GO +INSERT sys_menu VALUES (11619, N'我的待办', 11618, 2, N'taskWaiting', N'workflow/task/taskWaiting', N'', 1, 1, N'C', N'0', N'0', N'', N'waiting', 103, 1, GETDATE(), NULL, NULL, N''); +GO +INSERT sys_menu VALUES (11632, N'我的已办', 11618, 3, N'taskFinish', N'workflow/task/taskFinish', N'', 1, 1, N'C', N'0', N'0', N'', N'finish', 103, 1, GETDATE(), NULL, NULL, N''); +GO +INSERT sys_menu VALUES (11633, N'我的抄送', 11618, 4, N'taskCopyList', N'workflow/task/taskCopyList', N'', 1, 1, N'C', N'0', N'0', N'', N'my-copy', 103, 1, GETDATE(), NULL, NULL, N''); +GO +INSERT sys_menu VALUES (11620, N'流程定义', 11616, 3, N'processDefinition', N'workflow/processDefinition/index', N'', 1, 1, N'C', N'0', N'0', N'', N'process-definition', 103, 1, GETDATE(), NULL, NULL, N''); +GO +INSERT sys_menu VALUES (11621, N'流程实例', 11630, 1, N'processInstance', N'workflow/processInstance/index', N'', 1, 1, N'C', N'0', N'0', N'', N'tree-table', 103, 1, GETDATE(), NULL, NULL, N''); +GO +INSERT sys_menu VALUES (11622, N'流程分类', 11616, 1, N'category', N'workflow/category/index', N'', 1, 0, N'C', N'0', N'0', N'workflow:category:list', N'category', 103, 1, GETDATE(), NULL, NULL, N''); +GO +INSERT sys_menu VALUES (11629, N'我发起的', 11618, 1, N'myDocument', N'workflow/task/myDocument', N'', 1, 1, N'C', N'0', N'0', N'', N'guide', 103, 1, GETDATE(), NULL, NULL, N''); +GO +INSERT sys_menu VALUES (11630, N'流程监控', 11616, 4, N'monitor', NULL, N'', 1, 0, N'M', N'0', N'0', N'', N'monitor', 103, 1, GETDATE(), NULL, NULL, N''); +GO +INSERT sys_menu VALUES (11631, N'待办任务', 11630, 2, N'allTaskWaiting', N'workflow/task/allTaskWaiting', N'', 1, 1, N'C', N'0', N'0', N'', N'waiting', 103, 1, GETDATE(), NULL, NULL, N''); +GO -- 流程分类管理相关按钮 -insert into sys_menu values ('11623', '流程分类查询', '11622', '1', '#', '', '', 1, 0, 'F', '0', '0', 'workflow:category:query', '#', 103, 1, getdate(), null, null, ''); -insert into sys_menu values ('11624', '流程分类新增', '11622', '2', '#', '', '', 1, 0, 'F', '0', '0', 'workflow:category:add', '#', 103, 1, getdate(), null, null, ''); -insert into sys_menu values ('11625', '流程分类修改', '11622', '3', '#', '', '', 1, 0, 'F', '0', '0', 'workflow:category:edit', '#', 103, 1, getdate(), null, null, ''); -insert into sys_menu values ('11626', '流程分类删除', '11622', '4', '#', '', '', 1, 0, 'F', '0', '0', 'workflow:category:remove','#', 103, 1, getdate(), null, null, ''); -insert into sys_menu values ('11627', '流程分类导出', '11622', '5', '#', '', '', 1, 0, 'F', '0', '0', 'workflow:category:export','#', 103, 1, getdate(), null, null, ''); --- 请假单信息 -create table test_leave -( - id bigint not null - primary key, - leave_type nvarchar(255) not null, - start_date datetime2 not null, - end_date datetime2 not null, - leave_days int not null, - remark nvarchar(255), - status nvarchar(255), - create_dept bigint, - create_by bigint, - create_time datetime2, - update_by bigint, - update_time datetime2, - tenant_id nvarchar(20) -) -go - -exec sp_addextendedproperty 'MS_Description', N'请假申请表', 'SCHEMA', 'dbo', 'TABLE', 'test_leave' -go - -exec sp_addextendedproperty 'MS_Description', N'主键', 'SCHEMA', 'dbo', 'TABLE', 'test_leave', 'COLUMN', 'id' -go - -exec sp_addextendedproperty 'MS_Description', N'请假类型', 'SCHEMA', 'dbo', 'TABLE', 'test_leave', 'COLUMN', - 'leave_type' -go - -exec sp_addextendedproperty 'MS_Description', N'开始时间', 'SCHEMA', 'dbo', 'TABLE', 'test_leave', 'COLUMN', - 'start_date' -go - -exec sp_addextendedproperty 'MS_Description', N'结束时间', 'SCHEMA', 'dbo', 'TABLE', 'test_leave', 'COLUMN', 'end_date' -go - -exec sp_addextendedproperty 'MS_Description', N'请假天数', 'SCHEMA', 'dbo', 'TABLE', 'test_leave', 'COLUMN', - 'leave_days' -go - -exec sp_addextendedproperty 'MS_Description', N'请假原因', 'SCHEMA', 'dbo', 'TABLE', 'test_leave', 'COLUMN', 'remark' -go - -exec sp_addextendedproperty 'MS_Description', N'状态', 'SCHEMA', 'dbo', 'TABLE', 'test_leave', 'COLUMN', 'status' -go - -exec sp_addextendedproperty 'MS_Description', N'创建部门', 'SCHEMA', 'dbo', 'TABLE', 'test_leave', 'COLUMN', - 'create_dept' -go - -exec sp_addextendedproperty 'MS_Description', N'创建者', 'SCHEMA', 'dbo', 'TABLE', 'test_leave', 'COLUMN', 'create_by' -go - -exec sp_addextendedproperty 'MS_Description', N'创建时间', 'SCHEMA', 'dbo', 'TABLE', 'test_leave', 'COLUMN', - 'create_time' -go - -exec sp_addextendedproperty 'MS_Description', N'更新者', 'SCHEMA', 'dbo', 'TABLE', 'test_leave', 'COLUMN', 'update_by' -go - -exec sp_addextendedproperty 'MS_Description', N'更新时间', 'SCHEMA', 'dbo', 'TABLE', 'test_leave', 'COLUMN', - 'update_time' -go - -exec sp_addextendedproperty 'MS_Description', N'租户编号', 'SCHEMA', 'dbo', 'TABLE', 'test_leave', 'COLUMN', 'tenant_id' -go - --- 流程分类信息表 -create table wf_category -( - id bigint not null - primary key, - category_name nvarchar(255), - category_code nvarchar(255) - constraint uni_category_code - unique, - parent_id bigint, - sort_num int, - tenant_id nvarchar(20), - create_dept bigint, - create_by bigint, - create_time datetime2, - update_by bigint, - update_time datetime2 -) -go - -exec sp_addextendedproperty 'MS_Description', N'流程分类', 'SCHEMA', 'dbo', 'TABLE', 'wf_category' -go - -exec sp_addextendedproperty 'MS_Description', N'主键', 'SCHEMA', 'dbo', 'TABLE', 'wf_category', 'COLUMN', 'id' -go - -exec sp_addextendedproperty 'MS_Description', N'分类名称', 'SCHEMA', 'dbo', 'TABLE', 'wf_category', 'COLUMN', - 'category_name' -go - -exec sp_addextendedproperty 'MS_Description', N'分类编码', 'SCHEMA', 'dbo', 'TABLE', 'wf_category', 'COLUMN', - 'category_code' -go - -exec sp_addextendedproperty 'MS_Description', N'父级id', 'SCHEMA', 'dbo', 'TABLE', 'wf_category', 'COLUMN', 'parent_id' -go - -exec sp_addextendedproperty 'MS_Description', N'排序', 'SCHEMA', 'dbo', 'TABLE', 'wf_category', 'COLUMN', 'sort_num' -go - -exec sp_addextendedproperty 'MS_Description', N'租户编号', 'SCHEMA', 'dbo', 'TABLE', 'wf_category', 'COLUMN', - 'tenant_id' -go - -exec sp_addextendedproperty 'MS_Description', N'创建部门', 'SCHEMA', 'dbo', 'TABLE', 'wf_category', 'COLUMN', - 'create_dept' -go - -exec sp_addextendedproperty 'MS_Description', N'创建者', 'SCHEMA', 'dbo', 'TABLE', 'wf_category', 'COLUMN', 'create_by' -go - -exec sp_addextendedproperty 'MS_Description', N'创建时间', 'SCHEMA', 'dbo', 'TABLE', 'wf_category', 'COLUMN', - 'create_time' -go - -exec sp_addextendedproperty 'MS_Description', N'更新者', 'SCHEMA', 'dbo', 'TABLE', 'wf_category', 'COLUMN', 'update_by' -go - -exec sp_addextendedproperty 'MS_Description', N'更新时间', 'SCHEMA', 'dbo', 'TABLE', 'wf_category', 'COLUMN', - 'update_time' -go - -INSERT INTO wf_category values (1, 'OA', 'OA', 0, 0, '000000', 103, 1, getdate(), 1, getdate()); - -create table wf_task_back_node -( - id bigint not null primary key, - node_id nvarchar(255) not null, - node_name nvarchar(255) not null, - order_no int not null, - instance_id nvarchar(255) not null, - task_type nvarchar(255) not null, - assignee nvarchar(2000) not null, - tenant_id nvarchar(20), - create_dept bigint, - create_by bigint, - create_time datetime2, - update_by bigint, - update_time datetime2 -) - -go -exec sp_addextendedproperty 'MS_Description', N'节点审批记录', 'SCHEMA', 'dbo', 'TABLE', 'wf_task_back_node' -go - -exec sp_addextendedproperty 'MS_Description', N'主键', 'SCHEMA', 'dbo', 'TABLE', 'wf_task_back_node', 'COLUMN', 'id' -go - -exec sp_addextendedproperty 'MS_Description', N'节点id', 'SCHEMA', 'dbo', 'TABLE', 'wf_task_back_node', 'COLUMN', - 'node_id' -go - -exec sp_addextendedproperty 'MS_Description', N'节点名称', 'SCHEMA', 'dbo', 'TABLE', 'wf_task_back_node', 'COLUMN', - 'node_name' -go - -exec sp_addextendedproperty 'MS_Description', N'排序', 'SCHEMA', 'dbo', 'TABLE', 'wf_task_back_node', 'COLUMN', 'order_no' -go - -exec sp_addextendedproperty 'MS_Description', N'流程实例id', 'SCHEMA', 'dbo', 'TABLE', 'wf_task_back_node', 'COLUMN', 'instance_id' -go - -exec sp_addextendedproperty 'MS_Description', N'节点类型', 'SCHEMA', 'dbo', 'TABLE', 'wf_task_back_node', 'COLUMN', 'task_type' -go - -exec sp_addextendedproperty 'MS_Description', N'审批人', 'SCHEMA', 'dbo', 'TABLE', 'wf_task_back_node', 'COLUMN', 'assignee' -go - -exec sp_addextendedproperty 'MS_Description', N'租户编号', 'SCHEMA', 'dbo', 'TABLE', 'wf_task_back_node', 'COLUMN', - 'tenant_id' -go - -exec sp_addextendedproperty 'MS_Description', N'创建部门', 'SCHEMA', 'dbo', 'TABLE', 'wf_task_back_node', 'COLUMN', - 'create_dept' -go - -exec sp_addextendedproperty 'MS_Description', N'创建者', 'SCHEMA', 'dbo', 'TABLE', 'wf_task_back_node', 'COLUMN', 'create_by' -go - -exec sp_addextendedproperty 'MS_Description', N'创建时间', 'SCHEMA', 'dbo', 'TABLE', 'wf_task_back_node', 'COLUMN', - 'create_time' -go - -exec sp_addextendedproperty 'MS_Description', N'更新者', 'SCHEMA', 'dbo', 'TABLE', 'wf_task_back_node', 'COLUMN', 'update_by' -go - -exec sp_addextendedproperty 'MS_Description', N'更新时间', 'SCHEMA', 'dbo', 'TABLE', 'wf_task_back_node', 'COLUMN', - 'update_time' -go - -create table wf_definition_config -( - id bigint not null primary key, - table_name nvarchar(255) not null, - definition_id nvarchar(255) not null - constraint uni_definition_id - unique, - process_key nvarchar(255) not null, - version bigint not null, - remark nvarchar(500) DEFAULT ('') null, - tenant_id nvarchar(20), - create_dept bigint, - create_by bigint, - create_time datetime2, - update_by bigint, - update_time datetime2 -) - -go -exec sp_addextendedproperty 'MS_Description', N'流程定义配置', 'SCHEMA', 'dbo', 'TABLE', 'wf_definition_config' -go - -exec sp_addextendedproperty 'MS_Description', N'主键', 'SCHEMA', 'dbo', 'TABLE', 'wf_definition_config', 'COLUMN', 'id' -go - -exec sp_addextendedproperty 'MS_Description', N'表名', 'SCHEMA', 'dbo', 'TABLE', 'wf_definition_config', 'COLUMN', - 'table_name' -go - -exec sp_addextendedproperty 'MS_Description', N'流程定义ID', 'SCHEMA', 'dbo', 'TABLE', 'wf_definition_config', 'COLUMN', - 'definition_id' -go - -exec sp_addextendedproperty 'MS_Description', N'流程KEY', 'SCHEMA', 'dbo', 'TABLE', 'wf_definition_config', 'COLUMN', - 'process_key' -go - -exec sp_addextendedproperty 'MS_Description', N'流程版本', 'SCHEMA', 'dbo', 'TABLE', 'wf_definition_config', 'COLUMN', - 'version' -go - -exec sp_addextendedproperty 'MS_Description', N'备注', 'SCHEMA', 'dbo', 'TABLE', 'wf_definition_config', 'COLUMN', - 'remark' -go - -exec sp_addextendedproperty 'MS_Description', N'租户编号', 'SCHEMA', 'dbo', 'TABLE', 'wf_definition_config', 'COLUMN', - 'tenant_id' -go - -exec sp_addextendedproperty 'MS_Description', N'创建部门', 'SCHEMA', 'dbo', 'TABLE', 'wf_definition_config', 'COLUMN', - 'create_dept' -go - -exec sp_addextendedproperty 'MS_Description', N'创建者', 'SCHEMA', 'dbo', 'TABLE', 'wf_definition_config', 'COLUMN', 'create_by' -go - -exec sp_addextendedproperty 'MS_Description', N'创建时间', 'SCHEMA', 'dbo', 'TABLE', 'wf_definition_config', 'COLUMN', - 'create_time' -go - -exec sp_addextendedproperty 'MS_Description', N'更新者', 'SCHEMA', 'dbo', 'TABLE', 'wf_definition_config', 'COLUMN', 'update_by' -go - -exec sp_addextendedproperty 'MS_Description', N'更新时间', 'SCHEMA', 'dbo', 'TABLE', 'wf_definition_config', 'COLUMN', - 'update_time' -go - -create table wf_form_manage -( - id bigint not null primary key, - form_name nvarchar(255) not null, - form_type nvarchar(255) not null, - router nvarchar(255) not null, - remark nvarchar(500) null, - tenant_id nvarchar(20), - create_dept bigint, - create_by bigint, - create_time datetime2, - update_by bigint, - update_time datetime2 -) - -go -exec sp_addextendedproperty 'MS_Description', N'表单管理', 'SCHEMA', 'dbo', 'TABLE', 'wf_form_manage' -go - -exec sp_addextendedproperty 'MS_Description', N'主键', 'SCHEMA', 'dbo', 'TABLE', 'wf_form_manage', 'COLUMN', 'id' -go - -exec sp_addextendedproperty 'MS_Description', N'表单名称', 'SCHEMA', 'dbo', 'TABLE', 'wf_form_manage', 'COLUMN', - 'form_name' -go - -exec sp_addextendedproperty 'MS_Description', N'表单类型', 'SCHEMA', 'dbo', 'TABLE', 'wf_form_manage', 'COLUMN', - 'form_type' -go - -exec sp_addextendedproperty 'MS_Description', N'路由地址/表单ID', 'SCHEMA', 'dbo', 'TABLE', 'wf_form_manage', 'COLUMN', - 'router' -go - -exec sp_addextendedproperty 'MS_Description', N'备注', 'SCHEMA', 'dbo', 'TABLE', 'wf_form_manage', 'COLUMN', - 'remark' -go - -exec sp_addextendedproperty 'MS_Description', N'租户编号', 'SCHEMA', 'dbo', 'TABLE', 'wf_form_manage', 'COLUMN', - 'tenant_id' -go - -exec sp_addextendedproperty 'MS_Description', N'创建部门', 'SCHEMA', 'dbo', 'TABLE', 'wf_form_manage', 'COLUMN', - 'create_dept' -go - -exec sp_addextendedproperty 'MS_Description', N'创建者', 'SCHEMA', 'dbo', 'TABLE', 'wf_form_manage', 'COLUMN', 'create_by' -go - -exec sp_addextendedproperty 'MS_Description', N'创建时间', 'SCHEMA', 'dbo', 'TABLE', 'wf_form_manage', 'COLUMN', - 'create_time' -go - -exec sp_addextendedproperty 'MS_Description', N'更新者', 'SCHEMA', 'dbo', 'TABLE', 'wf_form_manage', 'COLUMN', 'update_by' -go - -exec sp_addextendedproperty 'MS_Description', N'更新时间', 'SCHEMA', 'dbo', 'TABLE', 'wf_form_manage', 'COLUMN', - 'update_time' -go - -insert into wf_form_manage(id, form_name, form_type, router, remark, tenant_id, create_dept, create_by, create_time, update_by, update_time) VALUES (1, '请假申请', 'static', '/workflow/leaveEdit/index', NULL, '000000', 103, 1, getdate(), 1, getdate()); - -create table wf_node_config -( - id bigint not null primary key, - form_id bigint, - form_type nvarchar(255) , - node_name nvarchar(255) not null, - node_id nvarchar(255) not null, - definition_id nvarchar(255) not null, - apply_user_task nchar default ('0') null, - tenant_id nvarchar(20), - create_dept bigint, - create_by bigint, - create_time datetime2, - update_by bigint, - update_time datetime2 -) - -go -exec sp_addextendedproperty 'MS_Description', N'节点配置', 'SCHEMA', 'dbo', 'TABLE', 'wf_node_config' -go - -exec sp_addextendedproperty 'MS_Description', N'主键', 'SCHEMA', 'dbo', 'TABLE', 'wf_node_config', 'COLUMN', 'id' -go - -exec sp_addextendedproperty 'MS_Description', N'表单id', 'SCHEMA', 'dbo', 'TABLE', 'wf_node_config', 'COLUMN', - 'form_id' -go - -exec sp_addextendedproperty 'MS_Description', N'表单类型', 'SCHEMA', 'dbo', 'TABLE', 'wf_node_config', 'COLUMN', - 'form_type' -go - -exec sp_addextendedproperty 'MS_Description', N'节点名称', 'SCHEMA', 'dbo', 'TABLE', 'wf_node_config', 'COLUMN', - 'node_name' -go - -exec sp_addextendedproperty 'MS_Description', N'节点id', 'SCHEMA', 'dbo', 'TABLE', 'wf_node_config', 'COLUMN', - 'node_id' -go - -exec sp_addextendedproperty 'MS_Description', N'流程定义id', 'SCHEMA', 'dbo', 'TABLE', 'wf_node_config', 'COLUMN', - 'definition_id' -go - -exec sp_addextendedproperty 'MS_Description', N'是否为申请人节点 (0是 1否)', 'SCHEMA', 'dbo', 'TABLE', 'wf_node_config', 'COLUMN', - 'apply_user_task' -go - -exec sp_addextendedproperty 'MS_Description', N'租户编号', 'SCHEMA', 'dbo', 'TABLE', 'wf_node_config', 'COLUMN', - 'tenant_id' -go - -exec sp_addextendedproperty 'MS_Description', N'创建部门', 'SCHEMA', 'dbo', 'TABLE', 'wf_node_config', 'COLUMN', - 'create_dept' -go - -exec sp_addextendedproperty 'MS_Description', N'创建者', 'SCHEMA', 'dbo', 'TABLE', 'wf_node_config', 'COLUMN', 'create_by' -go - -exec sp_addextendedproperty 'MS_Description', N'创建时间', 'SCHEMA', 'dbo', 'TABLE', 'wf_node_config', 'COLUMN', - 'create_time' -go - -exec sp_addextendedproperty 'MS_Description', N'更新者', 'SCHEMA', 'dbo', 'TABLE', 'wf_node_config', 'COLUMN', 'update_by' -go - -exec sp_addextendedproperty 'MS_Description', N'更新时间', 'SCHEMA', 'dbo', 'TABLE', 'wf_node_config', 'COLUMN', - 'update_time' -go - -INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11638, '请假申请', 5, 1, 'leave', 'workflow/leave/index', 1, 0, 'C', '0', '0', 'workflow:leave:list', '#', 103, 1, getdate(), NULL, NULL, '请假申请菜单'); -INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11639, '请假申请查询', 11638, 1, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:query', '#', 103, 1, getdate(), NULL, NULL, ''); -INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11640, '请假申请新增', 11638, 2, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:add', '#', 103, 1, getdate(), NULL, NULL, ''); -INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11641, '请假申请修改', 11638, 3, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:edit', '#', 103, 1, getdate(), NULL, NULL, ''); -INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11642, '请假申请删除', 11638, 4, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:remove', '#', 103, 1, getdate(), NULL, NULL, ''); -INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (11643, '请假申请导出', 11638, 5, '#', '', 1, 0, 'F', '0', '0', 'workflow:leave:export', '#', 103, 1, getdate(), NULL, NULL, ''); - -INSERT INTO sys_dict_type(dict_id, tenant_id, dict_name, dict_type, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (13, '000000', '业务状态', 'wf_business_status', 103, 1, getdate(), NULL, NULL, '业务状态列表'); -INSERT INTO sys_dict_type(dict_id, tenant_id, dict_name, dict_type, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (14, '000000', '表单类型', 'wf_form_type', 103, 1, getdate(), NULL, NULL, '表单类型列表'); - -INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (39, '000000', 1, '已撤销', 'cancel', 'wf_business_status', '', 'danger', 'N', 103, 1, getdate(), NULL, NULL, '已撤销'); -INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (40, '000000', 2, '草稿', 'draft', 'wf_business_status', '', 'info', 'N', 103, 1, getdate(), NULL, NULL, '草稿'); -INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (41, '000000', 3, '待审核', 'waiting', 'wf_business_status', '', 'primary', 'N', 103, 1,getdate(), NULL, NULL, '待审核'); -INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (42, '000000', 4, '已完成', 'finish', 'wf_business_status', '', 'success', 'N', 103, 1, getdate(), NULL, NULL, '已完成'); -INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (43, '000000', 5, '已作废', 'invalid', 'wf_business_status', '', 'danger', 'N', 103, 1, getdate(), NULL, NULL, '已作废'); -INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (44, '000000', 6, '已退回', 'back', 'wf_business_status', '', 'danger', 'N', 103, 1, getdate(), NULL, NULL, '已退回'); -INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (45, '000000', 7, '已终止', 'termination', 'wf_business_status', '', 'danger', 'N', 103, 1,getdate(), NULL, NULL, '已终止'); -INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (46, '000000', 1, '自定义表单', 'static', 'wf_form_type', '', 'success', 'N', 103, 1, getdate(), NULL, NULL, '自定义表单'); -INSERT INTO sys_dict_data(dict_code, tenant_id, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, create_dept, create_by, create_time, update_by, update_time, remark) VALUES (47, '000000', 2, '动态表单', 'dynamic', 'wf_form_type', '', 'primary', 'N', 103, 1, getdate(), NULL, NULL, '动态表单'); - --- 表单管理 SQL -insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) -values(11628, '表单管理', '11616', '5', 'formManage', 'workflow/formManage/index', 1, 0, 'C', '0', '0', 'workflow:formManage:list', 'tree-table', 103, 1, getdate(), null, null, '表单管理菜单'); - --- 表单管理按钮 SQL -insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) -values(11644, '表单管理查询', 11628, '1', '#', '', 1, 0, 'F', '0', '0', 'workflow:formManage:query', '', 103, 1, getdate(), null, null, ''); - -insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) -values(11645, '表单管理新增', 11628, '2', '#', '', 1, 0, 'F', '0', '0', 'workflow:formManage:add', '', 103, 1, getdate(), null, null, ''); - -insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) -values(11646, '表单管理修改', 11628, '3', '#', '', 1, 0, 'F', '0', '0', 'workflow:formManage:edit', '', 103, 1, getdate(), null, null, ''); - -insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) -values(11647, '表单管理删除', 11628, '4', '#', '', 1, 0, 'F', '0', '0', 'workflow:formManage:remove', '', 103, 1, getdate(), null, null, ''); - -insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time, update_by, update_time, remark) -values(11648, '表单管理导出', 11628, '5', '#', '', 1, 0, 'F', '0', '0', 'workflow:formManage:export', 'tree-table', 103, 1, getdate(), null, null, ''); +INSERT sys_menu VALUES (11623, N'流程分类查询', 11622, 1, N'#', N'', N'', 1, 0, N'F', N'0', N'0', N'workflow:category:query', N'#', 103, 1, GETDATE(), NULL, NULL, N''); +GO +INSERT sys_menu VALUES (11624, N'流程分类新增', 11622, 2, N'#', N'', N'', 1, 0, N'F', N'0', N'0', N'workflow:category:add', N'#', 103, 1, GETDATE(), NULL, NULL, N''); +GO +INSERT sys_menu VALUES (11625, N'流程分类修改', 11622, 3, N'#', N'', N'', 1, 0, N'F', N'0', N'0', N'workflow:category:edit', N'#', 103, 1, GETDATE(), NULL, NULL, N''); +GO +INSERT sys_menu VALUES (11626, N'流程分类删除', 11622, 4, N'#', N'', N'', 1, 0, N'F', N'0', N'0', N'workflow:category:remove', N'#', 103, 1, GETDATE(), NULL, NULL, N''); +GO +INSERT sys_menu VALUES (11627, N'流程分类导出', 11622, 5, N'#', N'', N'', 1, 0, N'F', N'0', N'0', N'workflow:category:export', N'#', 103, 1, GETDATE(), NULL, NULL, N''); +GO + +-- 请假测试相关按钮 +INSERT sys_menu VALUES (11638, N'请假申请', 5, 1, N'leave', N'workflow/leave/index', N'', 1, 0, N'C', N'0', N'0', N'workflow:leave:list', N'#', 103, 1, GETDATE(), NULL, NULL, N'请假申请菜单'); +GO +INSERT sys_menu VALUES (11639, N'请假申请查询', 11638, 1, N'#', N'', N'', 1, 0, N'F', N'0', N'0', N'workflow:leave:query', N'#', 103, 1, GETDATE(), NULL, NULL, N''); +GO +INSERT sys_menu VALUES (11640, N'请假申请新增', 11638, 2, N'#', N'', N'', 1, 0, N'F', N'0', N'0', N'workflow:leave:add', N'#', 103, 1, GETDATE(), NULL, NULL, N''); +GO +INSERT sys_menu VALUES (11641, N'请假申请修改', 11638, 3, N'#', N'', N'', 1, 0, N'F', N'0', N'0', N'workflow:leave:edit', N'#', 103, 1, GETDATE(), NULL, NULL, N''); +GO +INSERT sys_menu VALUES (11642, N'请假申请删除', 11638, 4, N'#', N'', N'', 1, 0, N'F', N'0', N'0', N'workflow:leave:remove', N'#', 103, 1, GETDATE(), NULL, NULL, N''); +GO +INSERT sys_menu VALUES (11643, N'请假申请导出', 11638, 5, N'#', N'', N'', 1, 0, N'F', N'0', N'0', N'workflow:leave:export', N'#', 103, 1, GETDATE(), NULL, NULL, N''); + +INSERT sys_dict_type VALUES (13, N'000000', N'业务状态', N'wf_business_status', 103, 1, GETDATE(), NULL, NULL, N'业务状态列表'); +GO +INSERT sys_dict_type VALUES (14, N'000000', N'表单类型', N'wf_form_type', 103, 1, GETDATE(), NULL, NULL, N'表单类型列表'); +GO +INSERT sys_dict_type VALUES (15, N'000000', N'任务状态', N'wf_task_status', 103, 1, GETDATE(), NULL, NULL, N'任务状态'); +GO + +INSERT sys_dict_data VALUES (39, N'000000', 1, N'已撤销', N'cancel', N'wf_business_status', N'', N'danger', N'N', 103, 1, GETDATE(), NULL, NULL, N'已撤销'); +GO +INSERT sys_dict_data VALUES (40, N'000000', 2, N'草稿', N'draft', N'wf_business_status', N'', N'info', N'N', 103, 1, GETDATE(), NULL, NULL, N'草稿'); +GO +INSERT sys_dict_data VALUES (41, N'000000', 3, N'待审核', N'waiting', N'wf_business_status', N'', N'primary', N'N', 103, 1, GETDATE(), NULL, NULL, N'待审核'); +GO +INSERT sys_dict_data VALUES (42, N'000000', 4, N'已完成', N'finish', N'wf_business_status', N'', N'success', N'N', 103, 1, GETDATE(), NULL, NULL, N'已完成'); +GO +INSERT sys_dict_data VALUES (43, N'000000', 5, N'已作废', N'invalid', N'wf_business_status', N'', N'danger', N'N', 103, 1, GETDATE(), NULL, NULL, N'已作废'); +GO +INSERT sys_dict_data VALUES (44, N'000000', 6, N'已退回', N'back', N'wf_business_status', N'', N'danger', N'N', 103, 1, GETDATE(), NULL, NULL, N'已退回'); +GO +INSERT sys_dict_data VALUES (45, N'000000', 7, N'已终止', N'termination', N'wf_business_status', N'', N'danger', N'N', 103, 1, GETDATE(), NULL, NULL, N'已终止'); +GO +INSERT sys_dict_data VALUES (46, N'000000', 1, N'自定义表单', N'static', N'wf_form_type', N'', N'success', N'N', 103, 1, GETDATE(), NULL, NULL, N'自定义表单'); +GO +INSERT sys_dict_data VALUES (47, N'000000', 2, N'动态表单', N'dynamic', N'wf_form_type', N'', N'primary', N'N', 103, 1, GETDATE(), NULL, NULL, N'动态表单'); +GO +INSERT sys_dict_data VALUES (48, N'000000', 1, N'撤销', N'cancel', N'wf_task_status', N'', N'danger', N'N', 103, 1, GETDATE(), NULL, NULL, N'撤销'); +GO +INSERT sys_dict_data VALUES (49, N'000000', 2, N'通过', N'pass', N'wf_task_status', N'', N'success', N'N', 103, 1, GETDATE(), NULL, NULL, N'通过'); +GO +INSERT sys_dict_data VALUES (50, N'000000', 3, N'待审核', N'waiting', N'wf_task_status', N'', N'primary', N'N', 103, 1, GETDATE(), NULL, NULL, N'待审核'); +GO +INSERT sys_dict_data VALUES (51, N'000000', 4, N'作废', N'invalid', N'wf_task_status', N'', N'danger', N'N', 103, 1, GETDATE(), NULL, NULL, N'作废'); +GO +INSERT sys_dict_data VALUES (52, N'000000', 5, N'退回', N'back', N'wf_task_status', N'', N'danger', N'N', 103, 1, GETDATE(), NULL, NULL, N'退回'); +GO +INSERT sys_dict_data VALUES (53, N'000000', 6, N'终止', N'termination', N'wf_task_status', N'', N'danger', N'N', 103, 1, GETDATE(), NULL, NULL, N'终止'); +GO +INSERT sys_dict_data VALUES (54, N'000000', 7, N'转办', N'transfer', N'wf_task_status', N'', N'primary', N'N', 103, 1, GETDATE(), NULL, NULL, N'转办'); +GO +INSERT sys_dict_data VALUES (55, N'000000', 8, N'委托', N'depute', N'wf_task_status', N'', N'primary', N'N', 103, 1, GETDATE(), NULL, NULL, N'委托'); +GO +INSERT sys_dict_data VALUES (56, N'000000', 9, N'抄送', N'copy', N'wf_task_status', N'', N'primary', N'N', 103, 1, GETDATE(), NULL, NULL, N'抄送'); +GO +INSERT sys_dict_data VALUES (57, N'000000', 10, N'加签', N'sign', N'wf_task_status', N'', N'primary', N'N', 103, 1, GETDATE(), NULL, NULL, N'加签'); +GO +INSERT sys_dict_data VALUES (58, N'000000', 11, N'减签', N'sign_off', N'wf_task_status', N'', N'danger', N'N', 103, 1, GETDATE(), NULL, NULL, N'减签'); +GO +INSERT sys_dict_data VALUES (59, N'000000', 11, N'超时', N'timeout', N'wf_task_status', N'', N'danger', N'N', 103, 1, GETDATE(), NULL, NULL, N'超时'); +GO