diff --git a/.run/ruoyi-monitor-admin.run.xml b/.run/ruoyi-monitor-admin.run.xml index c399b2967..4e0c21057 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 5dbde4ec4..bf72a8bae 100644 --- a/.run/ruoyi-server.run.xml +++ b/.run/ruoyi-server.run.xml @@ -2,7 +2,7 @@ - diff --git a/.run/ruoyi-snailjob-server.run.xml b/.run/ruoyi-snailjob-server.run.xml index e1e13fc6f..885007b07 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 fc3131a24..08832377e 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ [![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.3.0-success.svg)](https://gitee.com/dromara/RuoYi-Vue-Plus) +[![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)]() diff --git a/pom.xml b/pom.xml index 1d4366f2d..21d163bae 100644 --- a/pom.xml +++ b/pom.xml @@ -13,21 +13,21 @@ Dromara RuoYi-Vue-Plus多租户管理系统 - 5.3.0 - 3.4.2 + 5.3.1-BETA + 3.4.3 UTF-8 UTF-8 17 3.5.16 - 2.8.4 + 2.8.5 0.15.0 4.0.3 2.3 1.40.0 - 3.5.10 + 3.5.10.1 3.9.1 5.8.35 - 3.4.1 + 3.4.2 3.44.0 2.2.7 4.3.1 @@ -42,7 +42,6 @@ 2.28.22 - 0.31.3 3.3.3 @@ -50,7 +49,7 @@ 8.7.2-20250101 - 1.6.6 + 1.6.7 3.2.2 @@ -245,18 +244,18 @@ s3 ${aws.sdk.version} - - - software.amazon.awssdk.crt - aws-crt - ${aws.crt.version} - software.amazon.awssdk s3-transfer-manager ${aws.sdk.version} + + + software.amazon.awssdk + netty-nio-client + ${aws.sdk.version} + org.dromara.sms4j diff --git a/ruoyi-admin/src/main/java/org/dromara/web/controller/CaptchaController.java b/ruoyi-admin/src/main/java/org/dromara/web/controller/CaptchaController.java index 1a476a94a..0848170af 100644 --- a/ruoyi-admin/src/main/java/org/dromara/web/controller/CaptchaController.java +++ b/ruoyi-admin/src/main/java/org/dromara/web/controller/CaptchaController.java @@ -11,6 +11,7 @@ import lombok.extern.slf4j.Slf4j; import org.dromara.common.core.constant.Constants; import org.dromara.common.core.constant.GlobalConstants; import org.dromara.common.core.domain.R; +import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.utils.SpringUtils; import org.dromara.common.core.utils.StringUtils; import org.dromara.common.core.utils.reflect.ReflectUtils; @@ -79,12 +80,21 @@ public class CaptchaController { * * @param email 邮箱 */ - @RateLimiter(key = "#email", time = 60, count = 1) @GetMapping("/resource/email/code") public R emailCode(@NotBlank(message = "{user.email.not.blank}") String email) { if (!mailProperties.getEnabled()) { return R.fail("当前系统没有开启邮箱功能!"); } + SpringUtils.getAopProxy(this).emailCodeImpl(email); + return R.ok(); + } + + /** + * 邮箱验证码 + * 独立方法避免验证码关闭之后仍然走限流 + */ + @RateLimiter(key = "#email", time = 60, count = 1) + public void emailCodeImpl(String email) { String key = GlobalConstants.CAPTCHA_CODE_KEY + email; String code = RandomUtil.randomNumbers(4); RedisUtils.setCacheObject(key, code, Duration.ofMinutes(Constants.CAPTCHA_EXPIRATION)); @@ -92,23 +102,30 @@ public class CaptchaController { MailUtils.sendText(email, "登录验证码", "您本次验证码为:" + code + ",有效性为" + Constants.CAPTCHA_EXPIRATION + "分钟,请尽快填写。"); } catch (Exception e) { log.error("验证码短信发送异常 => {}", e.getMessage()); - return R.fail(e.getMessage()); + throw new ServiceException(e.getMessage()); } - return R.ok(); } /** * 生成验证码 */ - @RateLimiter(time = 60, count = 10, limitType = LimitType.IP) @GetMapping("/auth/code") public R getCode() { - CaptchaVo captchaVo = new CaptchaVo(); boolean captchaEnabled = captchaProperties.getEnable(); if (!captchaEnabled) { + CaptchaVo captchaVo = new CaptchaVo(); captchaVo.setCaptchaEnabled(false); return R.ok(captchaVo); } + return R.ok(SpringUtils.getAopProxy(this).getCodeImpl()); + } + + /** + * 生成验证码 + * 独立方法避免验证码关闭之后仍然走限流 + */ + @RateLimiter(time = 60, count = 10, limitType = LimitType.IP) + public CaptchaVo getCodeImpl() { // 保存验证码信息 String uuid = IdUtil.simpleUUID(); String verifyKey = GlobalConstants.CAPTCHA_CODE_KEY + uuid; @@ -128,9 +145,10 @@ public class CaptchaController { code = exp.getValue(String.class); } RedisUtils.setCacheObject(verifyKey, code, Duration.ofMinutes(Constants.CAPTCHA_EXPIRATION)); + CaptchaVo captchaVo = new CaptchaVo(); captchaVo.setUuid(uuid); captchaVo.setImg(captcha.getImageBase64()); - return R.ok(captchaVo); + return captchaVo; } } diff --git a/ruoyi-admin/src/main/java/org/dromara/web/controller/IndexController.java b/ruoyi-admin/src/main/java/org/dromara/web/controller/IndexController.java index c444f28c9..cdcfed62a 100644 --- a/ruoyi-admin/src/main/java/org/dromara/web/controller/IndexController.java +++ b/ruoyi-admin/src/main/java/org/dromara/web/controller/IndexController.java @@ -1,9 +1,9 @@ package org.dromara.web.controller; import cn.dev33.satoken.annotation.SaIgnore; -import org.dromara.common.core.config.RuoYiConfig; -import org.dromara.common.core.utils.StringUtils; import lombok.RequiredArgsConstructor; +import org.dromara.common.core.utils.SpringUtils; +import org.dromara.common.core.utils.StringUtils; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @@ -17,16 +17,12 @@ import org.springframework.web.bind.annotation.RestController; @RestController public class IndexController { - /** - * 系统基础配置 - */ - private final RuoYiConfig ruoyiConfig; - /** * 访问首页,提示语 */ @GetMapping("/") public String index() { - return StringUtils.format("欢迎使用{}后台管理框架,当前版本:v{},请通过前端地址访问。", ruoyiConfig.getName(), ruoyiConfig.getVersion()); + return StringUtils.format("欢迎使用{}后台管理框架,请通过前端地址访问。", SpringUtils.getApplicationName()); } + } diff --git a/ruoyi-admin/src/main/resources/application-dev.yml b/ruoyi-admin/src/main/resources/application-dev.yml index 5465921cb..d2c45eae1 100644 --- a/ruoyi-admin/src/main/resources/application-dev.yml +++ b/ruoyi-admin/src/main/resources/application-dev.yml @@ -120,8 +120,8 @@ redisson: nettyThreads: 8 # 单节点配置 singleServerConfig: - # 客户端名称 - clientName: ${ruoyi.name} + # 客户端名称 不能用中文 + clientName: RuoYi-Vue-Plus # 最小空闲连接数 connectionMinimumIdleSize: 8 # 连接池大小 diff --git a/ruoyi-admin/src/main/resources/application-prod.yml b/ruoyi-admin/src/main/resources/application-prod.yml index 80c1f969c..1c7eae428 100644 --- a/ruoyi-admin/src/main/resources/application-prod.yml +++ b/ruoyi-admin/src/main/resources/application-prod.yml @@ -123,8 +123,8 @@ redisson: nettyThreads: 32 # 单节点配置 singleServerConfig: - # 客户端名称 - clientName: ${ruoyi.name} + # 客户端名称 不能用中文 + clientName: RuoYi-Vue-Plus # 最小空闲连接数 connectionMinimumIdleSize: 32 # 连接池大小 diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml index dbe16888d..c15d89c02 100644 --- a/ruoyi-admin/src/main/resources/application.yml +++ b/ruoyi-admin/src/main/resources/application.yml @@ -1,24 +1,3 @@ -# 项目相关配置 -ruoyi: - # 名称 - name: RuoYi-Vue-Plus - # 版本 - version: ${revision} - # 版权年份 - copyrightYear: 2024 - -captcha: - enable: true - # 页面 <参数设置> 可开启关闭 验证码校验 - # 验证码类型 math 数组计算 char 字符验证 - type: MATH - # line 线段干扰 circle 圆圈干扰 shear 扭曲干扰 - category: CIRCLE - # 数字验证码位数 - numberLength: 1 - # 字符验证码长度 - charLength: 4 - # 开发环境配置 server: # 服务器的HTTP端口,默认为8080 @@ -41,6 +20,18 @@ server: # 阻塞任务线程池, 当执行类似servlet请求阻塞操作, undertow会从这个线程池中取得线程,它的值设置取决于系统的负载 worker: 256 +captcha: + enable: true + # 页面 <参数设置> 可开启关闭 验证码校验 + # 验证码类型 math 数组计算 char 字符验证 + type: MATH + # line 线段干扰 circle 圆圈干扰 shear 扭曲干扰 + category: CIRCLE + # 数字验证码位数 + numberLength: 1 + # 字符验证码长度 + charLength: 4 + # 日志配置 logging: level: @@ -61,7 +52,7 @@ user: # Spring配置 spring: application: - name: ${ruoyi.name} + name: RuoYi-Vue-Plus threads: # 开启虚拟线程 仅jdk21可用 virtual: @@ -191,7 +182,7 @@ springdoc: # persistAuthorization: true info: # 标题 - title: '标题:${ruoyi.name}多租户管理系统_接口文档' + title: '标题:RuoYi-Vue-Plus多租户管理系统_接口文档' # 描述 description: '描述:用于管理集团旗下公司的人员信息,具体包括XXX,XXX模块...' # 版本 @@ -228,7 +219,6 @@ xss: # 排除链接(多个用逗号分隔) excludeUrls: - /system/notice - - /warm-flow/save-xml # 全局线程池相关配置 # 如使用JDK21请直接使用虚拟线程 不要开启此配置 @@ -281,3 +271,11 @@ warm-flow: ui: true # 默认Authorization,如果有多个token,用逗号分隔 token-name: ${sa-token.token-name},clientid + # 流程状态对应的三元色 + chart-status-color: + ## 未办理 + - 62,62,62 + ## 待办理 + - 255,205,23 + ## 已办理 + - 157,255,0 diff --git a/ruoyi-admin/src/test/java/org/dromara/test/DemoUnitTest.java b/ruoyi-admin/src/test/java/org/dromara/test/DemoUnitTest.java index 5b3dfdc91..2d11a10f0 100644 --- a/ruoyi-admin/src/test/java/org/dromara/test/DemoUnitTest.java +++ b/ruoyi-admin/src/test/java/org/dromara/test/DemoUnitTest.java @@ -1,6 +1,6 @@ package org.dromara.test; -import org.dromara.common.core.config.RuoYiConfig; +import org.dromara.common.web.config.properties.CaptchaProperties; import org.junit.jupiter.api.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @@ -17,19 +17,19 @@ import java.util.concurrent.TimeUnit; public class DemoUnitTest { @Autowired - private RuoYiConfig ruoYiConfig; + private CaptchaProperties captchaProperties; @DisplayName("测试 @SpringBootTest @Test @DisplayName 注解") @Test public void testTest() { - System.out.println(ruoYiConfig); + System.out.println(captchaProperties); } @Disabled @DisplayName("测试 @Disabled 注解") @Test public void testDisabled() { - System.out.println(ruoYiConfig); + System.out.println(captchaProperties); } @Timeout(value = 2L, unit = TimeUnit.SECONDS) @@ -37,7 +37,7 @@ public class DemoUnitTest { @Test public void testTimeout() throws InterruptedException { Thread.sleep(3000); - System.out.println(ruoYiConfig); + System.out.println(captchaProperties); } diff --git a/ruoyi-common/ruoyi-common-bom/pom.xml b/ruoyi-common/ruoyi-common-bom/pom.xml index 24acb086d..e82179891 100644 --- a/ruoyi-common/ruoyi-common-bom/pom.xml +++ b/ruoyi-common/ruoyi-common-bom/pom.xml @@ -14,7 +14,7 @@ - 5.3.0 + 5.3.1-BETA diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/config/RuoYiConfig.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/config/RuoYiConfig.java deleted file mode 100644 index cc0d2dfce..000000000 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/config/RuoYiConfig.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.dromara.common.core.config; - -import lombok.Data; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.stereotype.Component; - -/** - * 读取项目相关配置 - * - * @author Lion Li - */ - -@Data -@Component -@ConfigurationProperties(prefix = "ruoyi") -public class RuoYiConfig { - - /** - * 项目名称 - */ - private String name; - - /** - * 版本 - */ - private String version; - - /** - * 版权年份 - */ - private String copyrightYear; - -} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/config/ValidatorConfig.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/config/ValidatorConfig.java index 45c5bd13c..ddcd836e4 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/config/ValidatorConfig.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/config/ValidatorConfig.java @@ -3,6 +3,7 @@ package org.dromara.common.core.config; import jakarta.validation.Validator; import org.hibernate.validator.HibernateValidator; import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration; import org.springframework.context.MessageSource; import org.springframework.context.annotation.Bean; import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean; @@ -14,11 +15,11 @@ import java.util.Properties; * * @author Lion Li */ -@AutoConfiguration +@AutoConfiguration(before = ValidationAutoConfiguration.class) public class ValidatorConfig { /** - * 配置校验框架 快速返回模式 + * 配置校验框架 快速失败模式 */ @Bean public Validator validator(MessageSource messageSource) { @@ -28,7 +29,7 @@ public class ValidatorConfig { // 设置使用 HibernateValidator 校验器 factoryBean.setProviderClass(HibernateValidator.class); Properties properties = new Properties(); - // 设置 快速异常返回 + // 设置快速失败模式(fail-fast),即校验过程中一旦遇到失败,立即停止并返回错误 properties.setProperty("hibernate.validator.fail_fast", "true"); factoryBean.setValidationProperties(properties); // 加载配置 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 bf8efc550..519034cf2 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 @@ -30,6 +30,11 @@ public interface CacheNames { */ String SYS_DICT = "sys_dict"; + /** + * 数据字典类型 + */ + String SYS_DICT_TYPE = "sys_dict_type"; + /** * 租户 */ diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/RegexConstants.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/RegexConstants.java index 77eed8c09..f1e04f760 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/RegexConstants.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/RegexConstants.java @@ -17,9 +17,14 @@ public interface RegexConstants extends RegexPool { String DICTIONARY_TYPE = "^[a-z][a-z0-9_]*$"; /** - * 权限标识必须符合 tool:build:list 格式,或者空字符串 + * 权限标识必须符合以下格式: + * 1. 标准格式:xxx:yyy:zzz + * - 第一部分(xxx):只能包含字母、数字和下划线(_),不能使用 `*` + * - 第二部分(yyy):可以包含字母、数字、下划线(_)和 `*` + * - 第三部分(zzz):可以包含字母、数字、下划线(_)和 `*` + * 2. 允许空字符串(""),表示没有权限标识 */ - String PERMISSION_STRING = "^(|^[a-zA-Z0-9_]+:[a-zA-Z0-9_]+:[a-zA-Z0-9_]+)$"; + String PERMISSION_STRING = "^$|^[a-zA-Z0-9_]+:[a-zA-Z0-9_*]+:[a-zA-Z0-9_*]+$"; /** * 身份证号码(后6位) 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 index 55240bbf8..8a37a51fc 100644 --- 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 @@ -72,4 +72,9 @@ public interface SystemConstants { */ Long SUPER_ADMIN_ID = 1L; + /** + * 根部门祖级列表 + */ + String ROOT_DEPT_ANCESTORS = "0"; + } 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 index 65c012faf..7b748b0b5 100644 --- 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 @@ -11,7 +11,6 @@ import java.io.Serializable; * * @author AprilWind */ - @Data @NoArgsConstructor public class DeptDTO implements Serializable { diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/DictDataDTO.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/DictDataDTO.java new file mode 100644 index 000000000..dff1a75dd --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/DictDataDTO.java @@ -0,0 +1,41 @@ +package org.dromara.common.core.domain.dto; + +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serial; +import java.io.Serializable; + +/** + * 字典数据DTO + * + * @author AprilWind + */ +@Data +@NoArgsConstructor +public class DictDataDTO implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 字典标签 + */ + private String dictLabel; + + /** + * 字典键值 + */ + private String dictValue; + + /** + * 是否默认(Y是 N否) + */ + private String isDefault; + + /** + * 备注 + */ + private String remark; + +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/DictTypeDTO.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/DictTypeDTO.java new file mode 100644 index 000000000..43ab142c2 --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/DictTypeDTO.java @@ -0,0 +1,41 @@ +package org.dromara.common.core.domain.dto; + +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serial; +import java.io.Serializable; + +/** + * 字典类型DTO + * + * @author AprilWind + */ +@Data +@NoArgsConstructor +public class DictTypeDTO implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 字典主键 + */ + private Long dictId; + + /** + * 字典名称 + */ + private String dictName; + + /** + * 字典类型 + */ + private String dictType; + + /** + * 备注 + */ + private String remark; + +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/RoleDTO.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/RoleDTO.java index aea8e7a9d..d14ffbb0f 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/RoleDTO.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/RoleDTO.java @@ -35,7 +35,7 @@ public class RoleDTO implements Serializable { private String roleKey; /** - * 数据范围(1:所有数据权限;2:自定义数据权限;3:本部门数据权限;4:本部门及以下数据权限;5:仅本人数据权限) + * 数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限 5:仅本人数据权限 6:部门及以下或本人数据权限) */ private String dataScope; 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/ProcessCreateTaskEvent.java similarity index 85% rename from ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/event/ProcessTaskEvent.java rename to ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/event/ProcessCreateTaskEvent.java index 33bc6e5a6..05047ab84 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/ProcessCreateTaskEvent.java @@ -6,12 +6,12 @@ import java.io.Serial; import java.io.Serializable; /** - * 流程办理监听 + * 流程创建任务监听 * * @author may */ @Data -public class ProcessTaskEvent implements Serializable { +public class ProcessCreateTaskEvent implements Serializable { @Serial private static final long serialVersionUID = 1L; diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/DictService.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/DictService.java index b78a7f257..d80395cc8 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/DictService.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/DictService.java @@ -1,5 +1,9 @@ package org.dromara.common.core.service; +import org.dromara.common.core.domain.dto.DictDataDTO; +import org.dromara.common.core.domain.dto.DictTypeDTO; + +import java.util.List; import java.util.Map; /** @@ -64,4 +68,20 @@ public interface DictService { */ Map getAllDictByDictType(String dictType); + /** + * 根据字典类型查询详细信息 + * + * @param dictType 字典类型 + * @return 字典类型详细信息 + */ + DictTypeDTO getDictType(String dictType); + + /** + * 根据字典类型查询字典数据列表 + * + * @param dictType 字典类型 + * @return 字典数据列表 + */ + List getDictData(String dictType); + } diff --git a/ruoyi-common/ruoyi-common-core/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/ruoyi-common/ruoyi-common-core/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index 3395e73bd..43c7fcfe0 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/ruoyi-common/ruoyi-common-core/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -1,6 +1,5 @@ org.dromara.common.core.config.ApplicationConfig org.dromara.common.core.config.AsyncConfig -org.dromara.common.core.config.RuoYiConfig org.dromara.common.core.config.ThreadPoolConfig org.dromara.common.core.config.ValidatorConfig org.dromara.common.core.utils.SpringUtils diff --git a/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/filter/EncryptResponseBodyWrapper.java b/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/filter/EncryptResponseBodyWrapper.java index c0af232ee..7bbca49d0 100644 --- a/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/filter/EncryptResponseBodyWrapper.java +++ b/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/filter/EncryptResponseBodyWrapper.java @@ -76,10 +76,7 @@ public class EncryptResponseBodyWrapper extends HttpServletResponseWrapper { String encryptPassword = EncryptUtils.encryptByRsa(encryptAes, publicKey); // 设置响应头 - servletResponse.addHeader("Access-Control-Expose-Headers", headerFlag); servletResponse.setHeader(headerFlag, encryptPassword); - servletResponse.setHeader("Access-Control-Allow-Origin", "*"); - servletResponse.setHeader("Access-Control-Allow-Methods", "*"); servletResponse.setCharacterEncoding(StandardCharsets.UTF_8.toString()); // 获取原始内容 diff --git a/ruoyi-common/ruoyi-common-oss/pom.xml b/ruoyi-common/ruoyi-common-oss/pom.xml index 18d004f57..190dc5d46 100644 --- a/ruoyi-common/ruoyi-common-oss/pom.xml +++ b/ruoyi-common/ruoyi-common-oss/pom.xml @@ -31,11 +31,6 @@ software.amazon.awssdk s3 - - - software.amazon.awssdk - netty-nio-client - software.amazon.awssdk @@ -54,10 +49,10 @@ - + - software.amazon.awssdk.crt - aws-crt + software.amazon.awssdk + netty-nio-client 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 e3b20dde3..7ac044c8e 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 @@ -16,10 +16,10 @@ import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; import software.amazon.awssdk.core.ResponseInputStream; import software.amazon.awssdk.core.async.AsyncResponseTransformer; import software.amazon.awssdk.core.async.BlockingInputStreamAsyncRequestBody; +import software.amazon.awssdk.http.nio.netty.NettyNioAsyncHttpClient; import software.amazon.awssdk.regions.Region; 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.presigner.S3Presigner; import software.amazon.awssdk.transfer.s3.S3TransferManager; @@ -84,18 +84,14 @@ public class OssClient { // MinIO 使用 HTTPS 限制使用域名访问,站点填域名。需要启用路径样式访问 boolean isStyle = !StringUtils.containsAny(properties.getEndpoint(), OssConstant.CLOUD_SERVICE); - // 创建AWS基于 CRT 的 S3 客户端 - this.client = S3AsyncClient.crtBuilder() + // 创建AWS基于 Netty 的 S3 客户端 + this.client = S3AsyncClient.builder() .credentialsProvider(credentialsProvider) .endpointOverride(URI.create(getEndpoint())) .region(of()) - .targetThroughputInGbps(20.0) - .minimumPartSizeInBytes(10 * 1025 * 1024L) - .checksumValidationEnabled(false) .forcePathStyle(isStyle) - .httpConfiguration(S3CrtHttpConfiguration.builder() - .connectionTimeout(Duration.ofSeconds(60)) // 设置连接超时 - .build()) + .httpClient(NettyNioAsyncHttpClient.builder() + .connectionTimeout(Duration.ofSeconds(60)).build()) .build(); //AWS基于 CRT 的 S3 AsyncClient 实例用作 S3 传输管理器的底层客户端 diff --git a/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/manager/CaffeineCacheDecorator.java b/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/manager/CaffeineCacheDecorator.java index 6e83df13a..8662c537d 100644 --- a/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/manager/CaffeineCacheDecorator.java +++ b/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/manager/CaffeineCacheDecorator.java @@ -78,6 +78,7 @@ public class CaffeineCacheDecorator implements Cache { @Override public void clear() { + CAFFEINE.invalidateAll(); cache.clear(); } 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 e2c92366f..a5729387d 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 @@ -63,23 +63,25 @@ public class LoginHelper { /** * 获取用户(多级缓存) */ - public static LoginUser getLoginUser() { + @SuppressWarnings("unchecked cast") + public static T getLoginUser() { SaSession session = StpUtil.getTokenSession(); if (ObjectUtil.isNull(session)) { return null; } - return (LoginUser) session.get(LOGIN_USER_KEY); + return (T) session.get(LOGIN_USER_KEY); } /** * 获取用户基于token */ - public static LoginUser getLoginUser(String token) { + @SuppressWarnings("unchecked cast") + public static T getLoginUser(String token) { SaSession session = StpUtil.getTokenSessionByToken(token); if (ObjectUtil.isNull(session)) { return null; } - return (LoginUser) session.get(LOGIN_USER_KEY); + return (T) session.get(LOGIN_USER_KEY); } /** @@ -191,7 +193,11 @@ public class LoginHelper { * @return 结果 */ public static boolean isTenantAdmin() { - return Convert.toBool(isTenantAdmin(getLoginUser().getRolePermission())); + LoginUser loginUser = getLoginUser(); + if (loginUser == null) { + return false; + } + return Convert.toBool(isTenantAdmin(loginUser.getRolePermission())); } /** 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 b94fd8a31..8252ed5e5 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 @@ -1,5 +1,6 @@ package org.dromara.system.domain; +import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableLogic; import com.baomidou.mybatisplus.annotation.TableName; @@ -8,6 +9,8 @@ import lombok.EqualsAndHashCode; import org.dromara.common.tenant.core.TenantEntity; import java.io.Serial; +import java.util.ArrayList; +import java.util.List; /** * 部门表 sys_dept @@ -80,4 +83,10 @@ public class SysDept extends TenantEntity { */ private String ancestors; + /** + * 子部门 + */ + @TableField(exist = false) + private List children = new ArrayList<>(); + } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysOss.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysOss.java index af88898ec..2285a5da7 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysOss.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysOss.java @@ -42,6 +42,11 @@ public class SysOss extends TenantEntity { */ private String url; + /** + * 扩展字段 + */ + private String ext1; + /** * 服务商 */ 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 a7c0ad5a0..aa1b19a4f 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 @@ -42,7 +42,7 @@ public class SysRole extends TenantEntity { private Integer roleSort; /** - * 数据范围(1:所有数据权限;2:自定义数据权限;3:本部门数据权限;4:本部门及以下数据权限;5:仅本人数据权限) + * 数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限 5:仅本人数据权限 6:部门及以下或本人数据权限) */ private String dataScope; diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysOssBo.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysOssBo.java index 7cb3104c2..ff624c9bf 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysOssBo.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysOssBo.java @@ -41,6 +41,11 @@ public class SysOssBo extends BaseEntity { */ private String url; + /** + * 扩展字段 + */ + private String ext1; + /** * 服务商 */ 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 3207bad1e..5e3e60260 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 @@ -49,7 +49,7 @@ public class SysRoleBo extends BaseEntity { private Integer roleSort; /** - * 数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限) + * 数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限 5:仅本人数据权限 6:部门及以下或本人数据权限) */ private String dataScope; 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 2669a8179..1472d2428 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 @@ -103,6 +103,11 @@ public class SysUserBo extends BaseEntity { */ private Long roleId; + /** + * 用户ID + */ + private String userIds; + /** * 排除不查询的用户(工作流用) */ diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysDeptVo.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysDeptVo.java index c56fb09bc..24ae56476 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysDeptVo.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysDeptVo.java @@ -2,15 +2,18 @@ package org.dromara.system.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.system.domain.SysDept; -import io.github.linpeilie.annotations.AutoMapper; -import lombok.Data; +import org.dromara.system.domain.SysMenu; import java.io.Serial; import java.io.Serializable; +import java.util.ArrayList; import java.util.Date; +import java.util.List; /** * 部门视图对象 sys_dept @@ -99,4 +102,9 @@ public class SysDeptVo implements Serializable { @ExcelProperty(value = "创建时间") private Date createTime; + /** + * 子部门 + */ + private List children = new ArrayList<>(); + } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysOssVo.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysOssVo.java index 8d5c429ca..fe0565182 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysOssVo.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysOssVo.java @@ -47,6 +47,11 @@ public class SysOssVo implements Serializable { */ private String url; + /** + * 扩展字段 + */ + private String ext1; + /** * 创建时间 */ 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 ffb2c6d5a..1913170ed 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 @@ -51,10 +51,10 @@ public class SysRoleVo implements Serializable { private Integer roleSort; /** - * 数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限) + * 数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限 5:仅本人数据权限 6:部门及以下或本人数据权限) */ @ExcelProperty(value = "数据范围", converter = ExcelDictConvert.class) - @ExcelDictFormat(readConverterExp = "1=所有数据权限,2=自定义数据权限,3=本部门数据权限,4=本部门及以下数据权限,5=仅本人数据权限") + @ExcelDictFormat(readConverterExp = "1=全部数据权限,2=自定义数据权限,3=本部门数据权限,4=本部门及以下数据权限,5=仅本人数据权限,6=部门及以下或本人数据权限") private String dataScope; /** diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysUserService.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysUserService.java index 0325a2558..1fe554547 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysUserService.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysUserService.java @@ -16,10 +16,17 @@ import java.util.List; public interface ISysUserService { + /** + * 根据条件分页查询用户列表 + * + * @param user 用户信息 + * @param pageQuery 发呢也 + * @return 用户信息 + */ TableDataInfo selectPageUserList(SysUserBo user, PageQuery pageQuery); /** - * 根据条件分页查询用户列表 + * 导出用户列表 * * @param user 用户信息 * @return 用户信息集合信息 @@ -29,7 +36,8 @@ public interface ISysUserService { /** * 根据条件分页查询已分配用户角色列表 * - * @param user 用户信息 + * @param user 用户信息 + * @param pageQuery 分页 * @return 用户信息集合信息 */ TableDataInfo selectAllocatedList(SysUserBo user, PageQuery pageQuery); @@ -37,7 +45,8 @@ public interface ISysUserService { /** * 根据条件分页查询未分配用户角色列表 * - * @param user 用户信息 + * @param user 用户信息 + * @param pageQuery 分页 * @return 用户信息集合信息 */ TableDataInfo selectUnallocatedList(SysUserBo user, PageQuery pageQuery); 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 ca062bee6..ecd309f4e 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 @@ -323,8 +323,10 @@ public class SysDeptServiceImpl implements ISysDeptService, DeptService { dept.setAncestors(oldDept.getAncestors()); } int result = baseMapper.updateById(dept); - if (SystemConstants.NORMAL.equals(dept.getStatus()) && StringUtils.isNotEmpty(dept.getAncestors()) - && !StringUtils.equals(SystemConstants.NORMAL, dept.getAncestors())) { + // 如果部门状态为启用,且部门祖级列表不为空,且部门祖级列表不等于根部门祖级列表(如果部门祖级列表不等于根部门祖级列表,则说明存在上级部门) + if (SystemConstants.NORMAL.equals(dept.getStatus()) + && StringUtils.isNotEmpty(dept.getAncestors()) + && !StringUtils.equals(SystemConstants.ROOT_DEPT_ANCESTORS, dept.getAncestors())) { // 如果该部门是启用状态,则启用该部门的所有上级部门 updateParentDeptStatusNormal(dept); } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDictTypeServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDictTypeServiceImpl.java index 1be0b7f40..1e5188c38 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDictTypeServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDictTypeServiceImpl.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.util.ObjectUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; @@ -8,6 +9,8 @@ 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.domain.dto.DictDataDTO; +import org.dromara.common.core.domain.dto.DictTypeDTO; import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.service.DictService; import org.dromara.common.core.utils.MapstructUtils; @@ -121,6 +124,7 @@ public class SysDictTypeServiceImpl implements ISysDictTypeService, DictService * @param dictType 字典类型 * @return 字典类型 */ + @Cacheable(cacheNames = CacheNames.SYS_DICT_TYPE, key = "#dictType") @Override public SysDictTypeVo selectDictTypeByType(String dictType) { return baseMapper.selectVoOne(new LambdaQueryWrapper().eq(SysDictType::getDictType, dictType)); @@ -140,6 +144,7 @@ public class SysDictTypeServiceImpl implements ISysDictTypeService, DictService throw new ServiceException(String.format("%1$s已分配,不能删除", dictType.getDictName())); } CacheUtils.evict(CacheNames.SYS_DICT, dictType.getDictType()); + CacheUtils.evict(CacheNames.SYS_DICT_TYPE, dictType.getDictType()); } baseMapper.deleteByIds(Arrays.asList(dictIds)); } @@ -150,6 +155,7 @@ public class SysDictTypeServiceImpl implements ISysDictTypeService, DictService @Override public void resetDictCache() { CacheUtils.clear(CacheNames.SYS_DICT); + CacheUtils.clear(CacheNames.SYS_DICT_TYPE); } /** @@ -188,6 +194,7 @@ public class SysDictTypeServiceImpl implements ISysDictTypeService, DictService int row = baseMapper.updateById(dict); if (row > 0) { CacheUtils.evict(CacheNames.SYS_DICT, oldDict.getDictType()); + CacheUtils.evict(CacheNames.SYS_DICT_TYPE, oldDict.getDictType()); return dictDataMapper.selectDictDataByType(dict.getDictType()); } throw new ServiceException("操作失败"); @@ -249,10 +256,40 @@ public class SysDictTypeServiceImpl implements ISysDictTypeService, DictService } } + /** + * 获取字典下所有的字典值与标签 + * + * @param dictType 字典类型 + * @return dictValue为key,dictLabel为值组成的Map + */ @Override public Map getAllDictByDictType(String dictType) { - List list = selectDictDataByType(dictType); + List list = SpringUtils.getAopProxy(this).selectDictDataByType(dictType); return StreamUtils.toMap(list, SysDictDataVo::getDictValue, SysDictDataVo::getDictLabel); } + /** + * 根据字典类型查询详细信息 + * + * @param dictType 字典类型 + * @return 字典类型详细信息 + */ + @Override + public DictTypeDTO getDictType(String dictType) { + SysDictTypeVo vo = SpringUtils.getAopProxy(this).selectDictTypeByType(dictType); + return BeanUtil.toBean(vo, DictTypeDTO.class); + } + + /** + * 根据字典类型查询字典数据列表 + * + * @param dictType 字典类型 + * @return 字典数据列表 + */ + @Override + public List getDictData(String dictType) { + List list = SpringUtils.getAopProxy(this).selectDictDataByType(dictType); + return BeanUtil.copyToList(list, DictDataDTO.class); + } + } 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 5888985a7..894f6acc8 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 @@ -154,6 +154,7 @@ public class SysPostServiceImpl implements ISysPostService, PostService { public boolean checkPostNameUnique(SysPostBo post) { boolean exist = baseMapper.exists(new LambdaQueryWrapper() .eq(SysPost::getPostName, post.getPostName()) + .eq(SysPost::getDeptId, post.getDeptId()) .ne(ObjectUtil.isNotNull(post.getPostId()), SysPost::getPostId, post.getPostId())); return !exist; } 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 index 23dd0520c..2fbf2408b 100644 --- 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 @@ -53,6 +53,7 @@ public class SysTaskAssigneeServiceImpl implements TaskAssigneeService { PageQuery pageQuery = new PageQuery(taskQuery.getPageSize(), taskQuery.getPageNum()); QueryWrapper wrapper = Wrappers.query(); wrapper.eq("r.del_flag", SystemConstants.NORMAL) + .eq("r.status", 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()), @@ -75,6 +76,7 @@ public class SysTaskAssigneeServiceImpl implements TaskAssigneeService { public TaskAssigneeDTO selectPostsByTaskAssigneeList(TaskAssigneeBody taskQuery) { PageQuery pageQuery = new PageQuery(taskQuery.getPageSize(), taskQuery.getPageNum()); LambdaQueryWrapper wrapper = Wrappers.lambdaQuery() + .eq(SysPost::getStatus, SystemConstants.NORMAL) .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()), @@ -106,6 +108,7 @@ public class SysTaskAssigneeServiceImpl implements TaskAssigneeService { PageQuery pageQuery = new PageQuery(taskQuery.getPageSize(), taskQuery.getPageNum()); LambdaQueryWrapper wrapper = Wrappers.lambdaQuery() .eq(SysDept::getDelFlag, SystemConstants.NORMAL) + .eq(SysDept::getStatus, 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()), @@ -143,6 +146,7 @@ public class SysTaskAssigneeServiceImpl implements TaskAssigneeService { PageQuery pageQuery = new PageQuery(taskQuery.getPageSize(), taskQuery.getPageNum()); QueryWrapper wrapper = Wrappers.query(); wrapper.eq("u.del_flag", SystemConstants.NORMAL) + .eq("u.status", 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, 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 f31bd3027..a73415c64 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 @@ -179,10 +179,20 @@ public class SysTenantServiceImpl implements ISysTenantService { for (SysDictType dictType : dictTypeList) { dictType.setDictId(null); dictType.setTenantId(tenantId); + dictType.setCreateDept(null); + dictType.setCreateBy(null); + dictType.setCreateTime(null); + dictType.setUpdateBy(null); + dictType.setUpdateTime(null); } for (SysDictData dictData : dictDataList) { dictData.setDictCode(null); dictData.setTenantId(tenantId); + dictData.setCreateDept(null); + dictData.setCreateBy(null); + dictData.setCreateTime(null); + dictData.setUpdateBy(null); + dictData.setUpdateTime(null); } dictTypeMapper.insertBatch(dictTypeList); dictDataMapper.insertBatch(dictDataList); @@ -192,6 +202,11 @@ public class SysTenantServiceImpl implements ISysTenantService { for (SysConfig config : sysConfigList) { config.setConfigId(null); config.setTenantId(tenantId); + config.setCreateDept(null); + config.setCreateBy(null); + config.setCreateTime(null); + config.setUpdateBy(null); + config.setUpdateTime(null); } configMapper.insertBatch(sysConfigList); @@ -433,6 +448,9 @@ public class SysTenantServiceImpl implements ISysTenantService { data.setTenantId(tenantId); data.setCreateTime(null); data.setUpdateTime(null); + data.setCreateDept(null); + data.setCreateBy(null); + data.setUpdateBy(null); set.add(tenantId); saveDataList.add(data); } @@ -454,6 +472,9 @@ public class SysTenantServiceImpl implements ISysTenantService { data.setTenantId(tenantId); data.setCreateTime(null); data.setUpdateTime(null); + data.setCreateDept(null); + data.setCreateBy(null); + data.setUpdateBy(null); set.add(tenantId); saveDataList.add(data); } 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 40811707b..cecd7f56f 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 @@ -79,6 +79,7 @@ public class SysUserServiceImpl implements ISysUserService, UserService { QueryWrapper wrapper = Wrappers.query(); wrapper.eq("u.del_flag", SystemConstants.NORMAL) .eq(ObjectUtil.isNotNull(user.getUserId()), "u.user_id", user.getUserId()) + .in(StringUtils.isNotBlank(user.getUserIds()), "u.user_id", StringUtils.splitTo(user.getUserIds(), Convert::toLong)) .like(StringUtils.isNotBlank(user.getUserName()), "u.user_name", user.getUserName()) .eq(StringUtils.isNotBlank(user.getStatus()), "u.status", user.getStatus()) .like(StringUtils.isNotBlank(user.getPhonenumber()), "u.phonenumber", user.getPhonenumber()) diff --git a/ruoyi-modules/ruoyi-workflow/README.md b/ruoyi-modules/ruoyi-workflow/README.md deleted file mode 100644 index 59096b10e..000000000 --- a/ruoyi-modules/ruoyi-workflow/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# 工作流说明 - -工作流目前在未成熟阶段 后续仍会经历重构 甚至重写(生产使用前请慎重考虑后续是否要更新维护) \ No newline at end of file diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/ButtonPermissionEnum.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/ButtonPermissionEnum.java new file mode 100644 index 000000000..7a224051d --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/ButtonPermissionEnum.java @@ -0,0 +1,60 @@ +package org.dromara.workflow.common.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 按钮权限枚举 + * + * @author AprilWind + */ +@Getter +@AllArgsConstructor +public enum ButtonPermissionEnum implements NodeExtEnum { + + /** + * 是否弹窗选人 + */ + POP("是否弹窗选人", "pop", false), + + /** + * 是否能委托 + */ + TRUST("是否能委托", "trust", false), + + /** + * 是否能转办 + */ + TRANSFER("是否能转办", "transfer", false), + + /** + * 是否能抄送 + */ + COPY("是否能抄送", "copy", false), + + /** + * 是否显示退回 + */ + BACK("是否显示退回", "back", true), + + /** + * 是否能加签 + */ + ADD_SIGN("是否能加签", "addSign", false), + + /** + * 是否能减签 + */ + SUB_SIGN("是否能减签", "subSign", false), + + /** + * 是否能终止 + */ + TERMINATION("是否能终止", "termination", true); + + private final String label; + private final String value; + private final boolean selected; + +} + diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/NodeExtEnum.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/NodeExtEnum.java new file mode 100644 index 000000000..9926a8eb9 --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/NodeExtEnum.java @@ -0,0 +1,32 @@ +package org.dromara.workflow.common.enums; + +/** + * 节点扩展属性枚举 + * + * @author AprilWind + */ +public interface NodeExtEnum { + + /** + * 选项label + * + * @return 选项label + */ + String getLabel(); + + /** + * 选项值 + * + * @return 选项值 + */ + String getValue(); + + /** + * 是否默认选中 + * + * @return 是否默认选中 + */ + boolean isSelected(); + +} + 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 index 463916b10..5534b6732 100644 --- 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 @@ -12,6 +12,7 @@ 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.warm.flow.orm.entity.FlowNode; import org.dromara.workflow.common.ConditionalOnEnable; import org.dromara.workflow.domain.bo.*; import org.dromara.workflow.domain.vo.FlowHisTaskVo; @@ -127,6 +128,16 @@ public class FlwTaskController extends BaseController { return R.ok(flwTaskService.selectById(taskId)); } + /** + * 获取下一节点信息 + * + * @param bo 参数 + */ + @PostMapping("/getNextNodeList") + public R> getNextNodeList(@RequestBody FlowNextNodeBo bo) { + return R.ok(flwTaskService.getNextNodeList(bo)); + } + /** * 终止任务 * diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/FlowCategory.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/FlowCategory.java index 86ac1ac32..28918f1d9 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/FlowCategory.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/FlowCategory.java @@ -1,5 +1,6 @@ package org.dromara.workflow.domain; +import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableLogic; import com.baomidou.mybatisplus.annotation.TableName; @@ -8,6 +9,8 @@ import lombok.EqualsAndHashCode; import org.dromara.common.tenant.core.TenantEntity; import java.io.Serial; +import java.util.ArrayList; +import java.util.List; /** * 流程分类对象 wf_category @@ -55,4 +58,10 @@ public class FlowCategory extends TenantEntity { @TableLogic private String delFlag; + /** + * 子菜单 + */ + @TableField(exist = false) + private List children = new ArrayList<>(); + } 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 9fdf48478..e5befff75 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 @@ -58,9 +58,13 @@ public class CompleteTaskBo implements Serializable { */ private Map variables; + /** + * 弹窗选择的办理人 + */ + private Map assigneeMap; + /** * 扩展变量(此处为逗号分隔的ossId) - * @return */ private String ext; diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowNextNodeBo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowNextNodeBo.java new file mode 100644 index 000000000..385eb892b --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowNextNodeBo.java @@ -0,0 +1,38 @@ +package org.dromara.workflow.domain.bo; + +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 FlowNextNodeBo implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + /** + * 任务id + */ + private String taskId; + + /** + * 流程变量 + */ + 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/vo/ButtonPermission.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/ButtonPermission.java new file mode 100644 index 000000000..51f320d2d --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/ButtonPermission.java @@ -0,0 +1,34 @@ +package org.dromara.workflow.domain.vo; + +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; + +/** + * 按钮权限 + * + * @author may + * @date 2025-02-28 + */ +@Data +public class ButtonPermission implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 枚举路径 + */ + private String code; + + /** + * 按钮编码 + */ + private String value; + + /** + * 是否显示 + */ + private boolean show; +} 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 index c5d27855f..f1c4caad5 100644 --- 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 @@ -8,7 +8,9 @@ import org.dromara.workflow.domain.FlowCategory; import java.io.Serial; import java.io.Serializable; +import java.util.ArrayList; import java.util.Date; +import java.util.List; /** @@ -64,4 +66,9 @@ public class FlowCategoryVo implements Serializable { @ExcelProperty(value = "创建时间") private Date createTime; + /** + * 子菜单 + */ + private List children = new ArrayList<>(); + } 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 index 3fb08d954..785e866c8 100644 --- 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 @@ -1,16 +1,20 @@ package org.dromara.workflow.domain.vo; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.json.JSONUtil; import lombok.Data; +import org.dromara.common.core.utils.StringUtils; 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 org.dromara.workflow.common.enums.ButtonPermissionEnum; import java.io.Serial; import java.io.Serializable; import java.math.BigDecimal; -import java.util.Date; -import java.util.List; +import java.util.*; +import java.util.stream.Collectors; /** * 任务视图 @@ -173,4 +177,39 @@ public class FlowTaskVo implements Serializable { */ @Translation(type = TransConstant.USER_ID_TO_NICKNAME, mapper = "createBy") private String createByName; + + /** + * 是否为申请人节点 + */ + private boolean applyNode; + + /** + * 按钮权限 + */ + private List buttonList; + + public List getButtonList(String ext) { + List buttonPermissions = Arrays.stream(ButtonPermissionEnum.values()) + .map(value -> { + ButtonPermission buttonPermission = new ButtonPermission(); + buttonPermission.setCode(value.getValue()); + buttonPermission.setShow(false); + return buttonPermission; + }) + .collect(Collectors.toList()); + if (StringUtils.isNotBlank(ext)) { + List buttonCodeList = JSONUtil.toList(JSONUtil.parseArray(ext), ButtonPermission.class); + if (CollUtil.isNotEmpty(buttonCodeList)) { + Optional firstPermission = buttonCodeList.stream().findFirst(); + firstPermission.ifPresent(permission -> { + Set codeSet = Arrays.stream(permission.getValue().split(",")) + .map(String::trim) + .filter(code -> !code.isEmpty()) + .collect(Collectors.toSet()); + buttonPermissions.forEach(bp -> bp.setShow(codeSet.contains(bp.getCode()))); + }); + } + } + return buttonPermissions; + } } 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 index 4b215ef60..3efc52da8 100644 --- 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 @@ -1,9 +1,9 @@ package org.dromara.workflow.handler; import lombok.extern.slf4j.Slf4j; +import org.dromara.common.core.domain.event.ProcessCreateTaskEvent; 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; @@ -23,7 +23,7 @@ import java.util.Map; public class FlowProcessEventHandler { /** - * 总体流程监听(例如: 草稿,撤销,退回,作废,终止,已完成等) + * 总体流程监听(例如: 草稿,撤销,退回,作废,终止,已完成,单任务完成等) * * @param flowCode 流程定义编码 * @param businessId 业务id @@ -44,23 +44,23 @@ public class FlowProcessEventHandler { } /** - * 执行办理任务监听 + * 执行创建任务监听 * * @param flowCode 流程定义编码 * @param nodeCode 审批节点编码 * @param taskId 任务id * @param businessId 业务id */ - public void processTaskHandler(String flowCode, String nodeCode, Long taskId, String businessId) { + public void processCreateTaskHandler(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); + ProcessCreateTaskEvent processCreateTaskEvent = new ProcessCreateTaskEvent(); + processCreateTaskEvent.setTenantId(tenantId); + processCreateTaskEvent.setFlowCode(flowCode); + processCreateTaskEvent.setNodeCode(nodeCode); + processCreateTaskEvent.setTaskId(taskId); + processCreateTaskEvent.setBusinessId(businessId); + SpringUtils.context().publishEvent(processCreateTaskEvent); } /** 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 index b18785484..272f9de92 100644 --- 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 @@ -52,7 +52,7 @@ public class WorkflowGlobalListener implements GlobalListener { Task task = listenerVariable.getTask(); if (task != null && BusinessStatusEnum.WAITING.getStatus().equals(flowStatus)) { // 判断流程状态(发布审批中事件) - flowProcessEventHandler.processTaskHandler(definition.getFlowCode(), task.getNodeCode(), task.getId(), businessId); + flowProcessEventHandler.processCreateTaskHandler(definition.getFlowCode(), task.getNodeCode(), task.getId(), businessId); } } diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwCommonService.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwCommonService.java new file mode 100644 index 000000000..73201f43f --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwCommonService.java @@ -0,0 +1,76 @@ +package org.dromara.workflow.service; + +import org.dromara.warm.flow.core.entity.User; +import org.dromara.warm.flow.core.service.UserService; + +import java.util.List; +import java.util.Set; + +/** + * 通用 工作流服务 + * + * @author LionLi + */ +public interface IFlwCommonService { + + /** + * 获取工作流用户service + * + * @return 工作流用户service + */ + UserService getFlowUserService(); + + /** + * 构建工作流用户 + * + * @param userList 办理用户 + * @param taskId 任务ID + * @return 用户 + */ + Set buildUser(List userList, Long taskId); + + /** + * 构建工作流用户 + * + * @param userIdList 办理用户 + * @param taskId 任务ID + * @return 用户 + */ + Set buildFlowUser(List userIdList, Long taskId); + + /** + * 发送消息 + * + * @param flowName 流程定义名称 + * @param instId 实例id + * @param messageType 消息类型 + * @param message 消息内容,为空则发送默认配置的消息内容 + */ + void sendMessage(String flowName, Long instId, List messageType, String message); + + /** + * 驳回 + * + * @param message 审批意见 + * @param instanceId 流程实例id + * @param targetNodeCode 目标节点 + * @param flowStatus 流程状态 + * @param flowHisStatus 节点操作状态 + */ + void backTask(String message, Long instanceId, String targetNodeCode, String flowStatus, String flowHisStatus); + + /** + * 申请人节点编码 + * + * @param definitionId 流程定义id + * @return 申请人节点编码 + */ + String applyNodeCode(Long definitionId); + + /** + * 删除运行中的任务 + * + * @param taskIds 任务id + */ + void deleteRunTask(List taskIds); +} 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 index 11034e753..fcb078295 100644 --- 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 @@ -6,6 +6,7 @@ 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.FlowNode; import org.dromara.warm.flow.orm.entity.FlowTask; import org.dromara.workflow.domain.bo.*; import org.dromara.workflow.domain.vo.FlowHisTaskVo; @@ -132,6 +133,14 @@ public interface IFlwTaskService { */ FlowTaskVo selectById(Long taskId); + /** + * 获取下一节点信息 + * + * @param bo 参数 + * @return 结果 + */ + List getNextNodeList(FlowNextNodeBo bo); + /** * 按照任务id查询任务 * @@ -188,4 +197,13 @@ public interface IFlwTaskService { * @return 结果 */ List currentTaskAllUser(Long taskId); + + /** + * 按照节点编码查询节点 + * + * @param nodeCode 节点编码 + * @param definitionId 流程定义id + * @return 节点 + */ + FlowNode getByNodeCode(String nodeCode, Long definitionId); } 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/service/impl/FlwCommonServiceImpl.java similarity index 66% rename from ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/utils/WorkflowUtils.java rename to ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwCommonServiceImpl.java index e48ffc820..bbc5734c9 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/service/impl/FlwCommonServiceImpl.java @@ -1,10 +1,10 @@ -package org.dromara.workflow.utils; +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.AccessLevel; -import lombok.NoArgsConstructor; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.dromara.common.core.domain.dto.UserDTO; import org.dromara.common.core.utils.SpringUtils; import org.dromara.common.core.utils.StreamUtils; @@ -28,9 +28,13 @@ 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.ConditionalOnEnable; import org.dromara.workflow.common.enums.MessageTypeEnum; +import org.dromara.workflow.common.enums.TaskAssigneeType; +import org.dromara.workflow.service.IFlwCommonService; import org.dromara.workflow.service.IFlwTaskAssigneeService; import org.dromara.workflow.service.IFlwTaskService; +import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.HashSet; @@ -42,24 +46,26 @@ import java.util.stream.Collectors; /** * 工作流工具 * - * @author may + * @author LionLi */ -@NoArgsConstructor(access = AccessLevel.PRIVATE) -public class WorkflowUtils { +@ConditionalOnEnable +@Slf4j +@RequiredArgsConstructor +@Service +public class FlwCommonServiceImpl implements IFlwCommonService { - 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); + private final FlowNodeMapper flowNodeMapper; + private final FlowTaskMapper flowTaskMapper; + private final UserService userService; + private final TaskService taskService; + private final NodeService nodeService; /** * 获取工作流用户service */ - public static UserService getFlowUserService() { - return USER_SERVICE; + @Override + public UserService getFlowUserService() { + return userService; } /** @@ -69,15 +75,17 @@ public class WorkflowUtils { * @param taskId 任务ID * @return 用户 */ - public static Set buildUser(List userList, Long taskId) { + @Override + public Set buildUser(List userList, Long taskId) { if (CollUtil.isEmpty(userList)) { return Set.of(); } Set list = new HashSet<>(); Set processedBySet = new HashSet<>(); + IFlwTaskAssigneeService taskAssigneeService = SpringUtils.getBean(IFlwTaskAssigneeService.class); for (User user : userList) { // 根据 processedBy 前缀判断处理人类型,分别获取用户列表 - List users = TASK_ASSIGNEE_SERVICE.fetchUsersByStorageId(user.getProcessedBy()); + List users = taskAssigneeService.fetchUsersByStorageId(user.getProcessedBy()); // 转换为 FlowUser 并添加到结果集合 if (CollUtil.isNotEmpty(users)) { users.forEach(dto -> { @@ -96,6 +104,33 @@ public class WorkflowUtils { return list; } + /** + * 构建工作流用户 + * + * @param userIdList 办理用户 + * @param taskId 任务ID + * @return 用户 + */ + @Override + public Set buildFlowUser(List userIdList, Long taskId) { + if (CollUtil.isEmpty(userIdList)) { + return Set.of(); + } + Set list = new HashSet<>(); + Set processedBySet = new HashSet<>(); + for (String userId : userIdList) { + if (!processedBySet.contains(userId)) { + FlowUser flowUser = new FlowUser(); + flowUser.setType(TaskAssigneeType.APPROVER.getCode()); + flowUser.setProcessedBy(String.valueOf(userId)); + flowUser.setAssociated(taskId); + list.add(flowUser); + processedBySet.add(String.valueOf(userId)); + } + } + return list; + } + /** * 发送消息 * @@ -103,14 +138,16 @@ public class WorkflowUtils { * @param messageType 消息类型 * @param message 消息内容,为空则发送默认配置的消息内容 */ - public static void sendMessage(String flowName, Long instId, List messageType, String message) { + @Override + public void sendMessage(String flowName, Long instId, List messageType, String message) { + IFlwTaskService flwTaskService = SpringUtils.getBean(IFlwTaskService.class); List userList = new ArrayList<>(); - List list = FLW_TASK_SERVICE.selectByInstId(instId); + List list = flwTaskService.selectByInstId(instId); if (StringUtils.isBlank(message)) { message = "有新的【" + flowName + "】单据已经提交至您,请您及时处理。"; } for (Task task : list) { - List users = FLW_TASK_SERVICE.currentTaskAllUser(task.getId()); + List users = flwTaskService.currentTaskAllUser(task.getId()); if (CollUtil.isNotEmpty(users)) { userList.addAll(users); } @@ -149,8 +186,10 @@ public class WorkflowUtils { * @param flowStatus 流程状态 * @param flowHisStatus 节点操作状态 */ - public static void backTask(String message, Long instanceId, String targetNodeCode, String flowStatus, String flowHisStatus) { - List list = FLW_TASK_SERVICE.selectByInstId(instanceId); + @Override + public void backTask(String message, Long instanceId, String targetNodeCode, String flowStatus, String flowHisStatus) { + IFlwTaskService flwTaskService = SpringUtils.getBean(IFlwTaskService.class); + List list = flwTaskService.selectByInstId(instanceId); if (CollUtil.isNotEmpty(list)) { List tasks = StreamUtils.filter(list, e -> e.getNodeCode().equals(targetNodeCode)); if (list.size() == tasks.size()) { @@ -158,7 +197,7 @@ public class WorkflowUtils { } } for (FlowTask task : list) { - List userList = FLW_TASK_SERVICE.currentTaskAllUser(task.getId()); + List userList = flwTaskService.currentTaskAllUser(task.getId()); FlowParams flowParams = FlowParams.build(); flowParams.nodeCode(targetNodeCode); flowParams.message(message); @@ -169,7 +208,7 @@ public class WorkflowUtils { if (CollUtil.isNotEmpty(userList)) { flowParams.handler(userList.get(0).getUserId().toString()); } - TASK_SERVICE.skip(task.getId(), flowParams); + taskService.skip(task.getId(), flowParams); } //解决会签多人审批问题 backTask(message, instanceId, targetNodeCode, flowStatus, flowHisStatus); @@ -181,13 +220,14 @@ public class WorkflowUtils { * @param definitionId 流程定义id * @return 申请人节点编码 */ - public static String applyNodeCode(Long definitionId) { + @Override + public String applyNodeCode(Long definitionId) { //获取已发布的流程节点 - List flowNodes = FLOW_NODE_MAPPER.selectList(new LambdaQueryWrapper().eq(FlowNode::getDefinitionId, definitionId)); + List flowNodes = flowNodeMapper.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()); + Node nextNode = nodeService.getNextNode(definitionId, startNode.getNodeCode(), null, SkipType.PASS.getKey()); return nextNode.getNodeCode(); } @@ -196,11 +236,12 @@ public class WorkflowUtils { * * @param taskIds 任务id */ - public static void deleteRunTask(List taskIds) { + @Override + public void deleteRunTask(List taskIds) { if (CollUtil.isEmpty(taskIds)) { return; } - USER_SERVICE.deleteByTaskIds(taskIds); - FLOW_TASK_MAPPER.deleteByIds(taskIds); + userService.deleteByTaskIds(taskIds); + flowTaskMapper.deleteByIds(taskIds); } } 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 index 591339b3e..7f0f67ec6 100644 --- 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 @@ -33,8 +33,8 @@ 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.IFlwCommonService; 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; @@ -64,6 +64,7 @@ public class FlwDefinitionServiceImpl implements IFlwDefinitionService { private final FlowNodeMapper flowNodeMapper; private final FlowSkipMapper flowSkipMapper; private final FlwCategoryMapper flwCategoryMapper; + private final IFlwCommonService flwCommonService; /** * 查询流程定义列表 @@ -125,7 +126,7 @@ public class FlwDefinitionServiceImpl implements IFlwDefinitionService { List errorMsg = new ArrayList<>(); if (CollUtil.isNotEmpty(flowNodes)) { for (FlowNode flowNode : flowNodes) { - String applyNodeCode = WorkflowUtils.applyNodeCode(id); + String applyNodeCode = flwCommonService.applyNodeCode(id); if (StringUtils.isBlank(flowNode.getPermissionFlag()) && !applyNodeCode.equals(flowNode.getNodeCode()) && NodeType.BETWEEN.getKey().equals(flowNode.getNodeType())) { errorMsg.add(flowNode.getNodeName()); } @@ -219,6 +220,11 @@ public class FlwDefinitionServiceImpl implements IFlwDefinitionService { .eq(FlowCategory::getTenantId, DEFAULT_TENANT_ID).eq(FlowCategory::getCategoryId, FlowConstant.FLOW_CATEGORY_ID)); flowCategory.setCategoryId(null); flowCategory.setTenantId(tenantId); + flowCategory.setCreateDept(null); + flowCategory.setCreateBy(null); + flowCategory.setCreateTime(null); + flowCategory.setUpdateBy(null); + flowCategory.setUpdateTime(null); flwCategoryMapper.insert(flowCategory); List defIds = StreamUtils.toList(flowDefinitions, FlowDefinition::getId); List flowNodes = flowNodeMapper.selectList(new LambdaQueryWrapper().in(FlowNode::getDefinitionId, defIds)); 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 index db8ab71b9..b5c943e90 100644 --- 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 @@ -46,9 +46,9 @@ 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.IFlwCommonService; 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; @@ -76,6 +76,7 @@ public class FlwInstanceServiceImpl implements IFlwInstanceService { private final IFlwTaskService flwTaskService; private final FlwInstanceMapper flwInstanceMapper; private final FlwCategoryMapper flwCategoryMapper; + private final IFlwCommonService flwCommonService; /** * 分页查询正在运行的流程实例 @@ -245,15 +246,15 @@ public class FlwInstanceServiceImpl implements IFlwInstanceService { } String message = bo.getMessage(); BusinessStatusEnum.checkCancelStatus(instance.getFlowStatus()); - String applyNodeCode = WorkflowUtils.applyNodeCode(definition.getId()); + String applyNodeCode = flwCommonService.applyNodeCode(definition.getId()); //撤销 - WorkflowUtils.backTask(message, instance.getId(), applyNodeCode, BusinessStatusEnum.CANCEL.getStatus(), BusinessStatusEnum.CANCEL.getStatus()); + flwCommonService.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)); + flwCommonService.deleteRunTask(StreamUtils.toList(currentTaskList, Task::getId)); } } @@ -373,6 +374,7 @@ public class FlwInstanceServiceImpl implements IFlwInstanceService { Instance instance = insService.getById(instanceId); if (instance != null) { taskService.mergeVariable(instance, variable); + insService.updateById(instance); } } diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwNodeExtServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwNodeExtServiceImpl.java new file mode 100644 index 000000000..4d8368a85 --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwNodeExtServiceImpl.java @@ -0,0 +1,190 @@ +package org.dromara.workflow.service.impl; + +import cn.hutool.core.convert.Convert; +import cn.hutool.core.util.ObjectUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.dromara.common.core.domain.dto.DictTypeDTO; +import org.dromara.common.core.service.DictService; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.warm.flow.ui.service.NodeExtService; +import org.dromara.warm.flow.ui.vo.NodeExt; +import org.dromara.workflow.common.ConditionalOnEnable; +import org.dromara.workflow.common.enums.ButtonPermissionEnum; +import org.dromara.workflow.common.enums.NodeExtEnum; +import org.springframework.stereotype.Service; + +import java.util.*; + +/** + * 流程设计器-节点扩展属性 + * + * @author AprilWind + */ +@ConditionalOnEnable +@Slf4j +@RequiredArgsConstructor +@Service +public class FlwNodeExtServiceImpl implements NodeExtService { + + /** + * 权限页code + */ + private static final String PERMISSION_TAB = "wf_button_tab"; + + /** + * 权限页名称 + */ + private static final String PERMISSION_TAB_NAME = "权限"; + + /** + * 枚举类型标识 + */ + private static final String ENUM_TYPE_PREFIX = "enum:"; + + /** + * 基础设置 + */ + private static final int TYPE_BASE_SETTING = 1; + + /** + * 新页签 + */ + private static final int TYPE_NEW_TAB = 2; + + /** + * 存储不同 dictType 对应的配置信息 + */ + private static final Map> CHILD_NODE_MAP = new HashMap<>(); + + static { + CHILD_NODE_MAP.put(ButtonPermissionEnum.class.getName(), + Map.of("label", "权限按钮", "type", 4, "must", false, "multiple", true)); + } + + private final DictService dictService; + + /** + * 获取节点扩展属性 + * + * @return 结果 + */ + @Override + public List getNodeExt() { + List nodeExtList = new ArrayList<>(); + // 构建按钮权限页面 + nodeExtList.add(buildNodeExt(PERMISSION_TAB, PERMISSION_TAB_NAME, TYPE_NEW_TAB, + ENUM_TYPE_PREFIX + ButtonPermissionEnum.class.getName())); + return nodeExtList; + } + + /** + * 构建一个 NodeExt 对象 + * + * @param code 编码,此json中唯一 + * @param name 名称,如果type为新页签时,作为页签名称 + * @param type 节点类型,1:基础设置,2:新页签 + * @param sourceTypes 字典/枚举类型来源(逗号分隔) + * @return 返回构建好的 NodeExt 对象 + */ + private NodeExt buildNodeExt(String code, String name, int type, String sourceTypes) { + NodeExt nodeExt = new NodeExt(); + nodeExt.setCode(code); + nodeExt.setType(type); + nodeExt.setName(name); + nodeExt.setChilds(StringUtils.splitList(sourceTypes) + .stream().map(this::buildChildNode) + .filter(ObjectUtil::isNotNull) + .toList() + ); + return nodeExt; + } + + /** + * 构建一个 ChildNode 对象 + * + * @param sourceType 字典类型 + * @return 返回构建好的 ChildNode 对象 + */ + private NodeExt.ChildNode buildChildNode(String sourceType) { + return sourceType.startsWith(ENUM_TYPE_PREFIX) ? + buildChildNodeFromEnum(sourceType.substring(ENUM_TYPE_PREFIX.length())) : buildChildNodeFromDict(sourceType); + } + + /** + * 根据枚举构建一个 ChildNode 对象 + * + * @param enumClassName 枚举名称 + * @return 返回构建好的 ChildNode 对象 + */ + private NodeExt.ChildNode buildChildNodeFromEnum(String enumClassName) { + try { + Class enumClass = Class.forName(enumClassName); + if (!enumClass.isEnum()) { + return null; + } + NodeExt.ChildNode childNode = buildChildNodeMap(enumClassName); + // 编码,此json中唯 + childNode.setCode(ENUM_TYPE_PREFIX + enumClassName); + // 字典,下拉框和复选框时用到 + childNode.setDict(Arrays.stream(enumClass.getEnumConstants()) + .filter(NodeExtEnum.class::isInstance) + .map(NodeExtEnum.class::cast) + .map(x -> + new NodeExt.DictItem(x.getLabel(), x.getValue(), x.isSelected()) + ).toList()); + return childNode; + } catch (ClassNotFoundException e) { + log.error("Enum class not found: {}", enumClassName, e); + } + return null; + } + + /** + * 根据字典构建一个 ChildNode 对象 + * + * @param dictType 字典类型 + * @return 返回构建好的 ChildNode 对象 + */ + private NodeExt.ChildNode buildChildNodeFromDict(String dictType) { + DictTypeDTO dictTypeDTO = dictService.getDictType(dictType); + if (ObjectUtil.isNull(dictTypeDTO)) { + return null; + } + NodeExt.ChildNode childNode = buildChildNodeMap(dictType); + // 编码,此json中唯一 + childNode.setCode(dictType); + // label名称 + childNode.setLabel(dictTypeDTO.getDictName()); + // 描述 + childNode.setDesc(dictTypeDTO.getRemark()); + // 字典,下拉框和复选框时用到 + childNode.setDict(dictService.getDictData(dictType) + .stream().map(x -> + new NodeExt.DictItem(x.getDictLabel(), x.getDictValue(), Convert.toBool(x.getIsDefault(), false)) + ).toList()); + return childNode; + } + + /** + * 根据 CHILD_NODE_MAP 中的配置信息,构建一个基本的 ChildNode 对象 + * 该方法用于设置 ChildNode 的常规属性,例如 label、type、是否必填、是否多选等 + * + * @param key CHILD_NODE_MAP 的 key + * @return 返回构建好的 ChildNode 对象 + */ + private NodeExt.ChildNode buildChildNodeMap(String key) { + NodeExt.ChildNode childNode = new NodeExt.ChildNode(); + Map map = CHILD_NODE_MAP.get(key); + // label名称 + childNode.setLabel((String) map.get("label")); + // 1:输入框 2:输入框 3:下拉框 4:选择框 + childNode.setType(Convert.toInt(map.get("type"), 1)); + // 是否必填 + childNode.setMust(Convert.toBool(map.get("must"), false)); + // 是否多选 + childNode.setMultiple(Convert.toBool(map.get("multiple"), true)); + return childNode; + } + +} 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 index 21a54d740..209073bdb 100644 --- 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 @@ -30,9 +30,12 @@ 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.core.utils.ExpressionUtil; +import org.dromara.warm.flow.core.utils.MapUtil; 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.FlowNodeMapper; import org.dromara.warm.flow.orm.mapper.FlowTaskMapper; import org.dromara.workflow.common.ConditionalOnEnable; import org.dromara.workflow.common.enums.TaskAssigneeType; @@ -44,8 +47,9 @@ 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.IFlwCommonService; +import org.dromara.workflow.service.IFlwTaskAssigneeService; import org.dromara.workflow.service.IFlwTaskService; -import org.dromara.workflow.utils.WorkflowUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -79,6 +83,9 @@ public class FlwTaskServiceImpl implements IFlwTaskService { private final UserService userService; private final FlwTaskMapper flwTaskMapper; private final FlwCategoryMapper flwCategoryMapper; + private final FlowNodeMapper flowNodeMapper; + private final IFlwTaskAssigneeService flwTaskAssigneeService; + private final IFlwCommonService flwCommonService; /** * 启动任务 @@ -103,6 +110,8 @@ public class FlwTaskServiceImpl implements IFlwTaskService { if (ObjectUtil.isNotNull(flowInstance)) { BusinessStatusEnum.checkStartStatus(flowInstance.getFlowStatus()); List taskList = taskService.list(new FlowTask().setInstanceId(flowInstance.getId())); + taskService.mergeVariable(flowInstance, variables); + insService.updateById(flowInstance); StartProcessReturnDTO dto = new StartProcessReturnDTO(); dto.setProcessInstanceId(taskList.get(0).getInstanceId()); dto.setTaskId(taskList.get(0).getId()); @@ -155,6 +164,11 @@ public class FlwTaskServiceImpl implements IFlwTaskService { if (BusinessStatusEnum.isDraftOrCancelOrBack(ins.getFlowStatus())) { flowProcessEventHandler.processHandler(definition.getFlowCode(), ins.getBusinessId(), ins.getFlowStatus(), null, true); } + // 设置弹窗处理人 + Map assigneeMap = setPopAssigneeMap(completeTaskBo.getAssigneeMap(), ins.getVariableMap()); + if (CollUtil.isNotEmpty(assigneeMap)) { + completeTaskBo.getVariables().putAll(assigneeMap); + } // 构建流程参数,包括变量、跳转类型、消息、处理人、权限等信息 FlowParams flowParams = new FlowParams(); flowParams.variable(completeTaskBo.getVariables()); @@ -167,7 +181,9 @@ public class FlwTaskServiceImpl implements IFlwTaskService { Instance instance = taskService.skip(taskId, flowParams); this.setHandler(instance, flowTask, flowCopyList); // 消息通知 - WorkflowUtils.sendMessage(definition.getFlowName(), ins.getId(), messageType, notice); + flwCommonService.sendMessage(definition.getFlowName(), ins.getId(), messageType, notice); + //设置下一环节处理人 + setNextHandler(ins.getId()); return true; } catch (Exception e) { log.error(e.getMessage(), e); @@ -175,6 +191,60 @@ public class FlwTaskServiceImpl implements IFlwTaskService { } } + /** + * 设置下一环节处理人 + * + * @param instanceId 实例ID + */ + private void setNextHandler(Long instanceId) { + Instance inst = insService.getById(instanceId); + List flowTaskList = selectByInstId(instanceId); + Map variableMap = inst.getVariableMap(); + for (FlowTask task : flowTaskList) { + if (variableMap != null && variableMap.containsKey(task.getNodeCode())) { + String userIds = variableMap.get(task.getNodeCode()).toString(); + // 批量删除现有任务的办理人记录 + flwCommonService.getFlowUserService().deleteByTaskIds(List.of(task.getId())); + // 批量新增任务办理人记录 + Set users = flwCommonService.buildFlowUser(List.of(userIds.split(StringUtils.SEPARATOR)), task.getId()); + flwCommonService.getFlowUserService().saveBatch(new ArrayList<>(users)); + variableMap.remove(task.getNodeCode()); + } + } + taskService.mergeVariable(inst, variableMap); + } + + /** + * 设置弹窗处理人 + * + * @param assigneeMap 处理人 + * @param variablesMap 变量 + */ + private Map setPopAssigneeMap(Map assigneeMap, Map variablesMap) { + Map map = new HashMap<>(); + if (CollUtil.isEmpty(assigneeMap)) { + return map; + } + for (Map.Entry entry : assigneeMap.entrySet()) { + if (variablesMap.containsKey(entry.getKey())) { + String userIds = variablesMap.get(entry.getKey()).toString(); + if (StringUtils.isNotBlank(userIds)) { + Set hashSet = new HashSet<>(); + //弹窗传入的选人 + List popUserIds = Arrays.asList(entry.getValue().toString().split(StringUtils.SEPARATOR)); + //已有的选人 + List variableUserIds = Arrays.asList(userIds.split(StringUtils.SEPARATOR)); + hashSet.addAll(popUserIds); + hashSet.addAll(variableUserIds); + map.put(entry.getKey(), String.join(StringUtils.SEPARATOR, hashSet)); + } + } else { + map.put(entry.getKey(), entry.getValue()); + } + } + return map; + } + /** * 设置办理人 * @@ -195,7 +265,7 @@ public class FlwTaskServiceImpl implements IFlwTaskService { } List taskIdList = StreamUtils.toList(flowTasks, FlowTask::getId); // 获取与当前任务关联的用户列表 - List associatedUsers = WorkflowUtils.getFlowUserService().getByAssociateds(taskIdList); + List associatedUsers = flwCommonService.getFlowUserService().getByAssociateds(taskIdList); if (CollUtil.isEmpty(associatedUsers)) { return; } @@ -204,16 +274,16 @@ public class FlwTaskServiceImpl implements IFlwTaskService { 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())); + userList.addAll(flwCommonService.buildUser(users, flowTask.getId())); } } // 批量删除现有任务的办理人记录 - WorkflowUtils.getFlowUserService().deleteByTaskIds(taskIdList); + flwCommonService.getFlowUserService().deleteByTaskIds(taskIdList); // 确保要保存的 userList 不为空 if (CollUtil.isEmpty(userList)) { return; } - WorkflowUtils.getFlowUserService().saveBatch(userList); + flwCommonService.getFlowUserService().saveBatch(userList); } /** @@ -253,7 +323,7 @@ public class FlwTaskServiceImpl implements IFlwTaskService { return flowUser; }).collect(Collectors.toList()); // 批量保存抄送人员 - WorkflowUtils.getFlowUserService().saveBatch(userList); + flwCommonService.getFlowUserService().saveBatch(userList); } /** @@ -381,7 +451,7 @@ public class FlwTaskServiceImpl implements IFlwTaskService { BusinessStatusEnum.checkBackStatus(inst.getFlowStatus()); Long definitionId = task.getDefinitionId(); Definition definition = defService.getById(definitionId); - String applyNodeCode = WorkflowUtils.applyNodeCode(definitionId); + String applyNodeCode = flwCommonService.applyNodeCode(definitionId); FlowParams flowParams = FlowParams.build(); flowParams.nodeCode(bo.getNodeCode()); flowParams.message(message); @@ -394,7 +464,7 @@ public class FlwTaskServiceImpl implements IFlwTaskService { Instance instance = insService.getById(inst.getId()); this.setHandler(instance, task, null); // 消息通知 - WorkflowUtils.sendMessage(definition.getFlowName(), instance.getId(), messageType, notice); + flwCommonService.sendMessage(definition.getFlowName(), instance.getId(), messageType, notice); return true; } catch (Exception e) { log.error(e.getMessage(), e); @@ -487,14 +557,52 @@ public class FlwTaskServiceImpl implements IFlwTaskService { 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()); + //设置按钮权限 + FlowNode flowNode = getByNodeCode(flowTaskVo.getNodeCode(), instance.getDefinitionId()); + if (ObjectUtil.isNull(flowNode)) { + throw new NullPointerException("当前【" + flowTaskVo.getNodeCode() + "】节点编码不存在"); } + flowTaskVo.setButtonList(flowTaskVo.getButtonList(flowNode.getExt())); + flowTaskVo.setNodeRatio(flowNode.getNodeRatio()); + flowTaskVo.setApplyNode(flowNode.getNodeCode().equals(flwCommonService.applyNodeCode(task.getDefinitionId()))); return flowTaskVo; } + /** + * 获取下一节点信息 + * + * @param bo 参数 + */ + @Override + public List getNextNodeList(FlowNextNodeBo bo) { + String taskId = bo.getTaskId(); + Map variables = bo.getVariables(); + Task task = taskService.getById(taskId); + Instance instance = insService.getById(task.getInstanceId()); + Definition definition = defService.getById(task.getDefinitionId()); + Map mergeVariable = MapUtil.mergeAll(instance.getVariableMap(), variables); + //获取下一节点列表 + List nextNodeList = nodeService.getNextNodeList(task.getDefinitionId(), task.getNodeCode(), null, SkipType.PASS.getKey(), mergeVariable); + List nextFlowNodes = BeanUtil.copyToList(nextNodeList, FlowNode.class); + if (CollUtil.isNotEmpty(nextNodeList)) { + //构建以下节点数据 + List buildNextTaskList = StreamUtils.toList(nextNodeList, node -> taskService.addTask(node, instance, definition, null)); + //办理人变量替换 + ExpressionUtil.evalVariable(buildNextTaskList, mergeVariable); + for (FlowNode flowNode : nextFlowNodes) { + buildNextTaskList.stream().filter(t -> t.getNodeCode().equals(flowNode.getNodeCode())).findFirst().ifPresent(t -> { + if (CollUtil.isNotEmpty(t.getPermissionList())) { + List users = flwTaskAssigneeService.fetchUsersByStorageId(String.join(StringUtils.SEPARATOR, t.getPermissionList())); + if (CollUtil.isNotEmpty(users)) { + flowNode.setPermissionFlag(StreamUtils.join(users, e -> String.valueOf(e.getUserId()))); + } + } + }); + } + } + return nextFlowNodes; + } + /** * 按照任务id查询任务 * @@ -577,10 +685,11 @@ public class FlwTaskServiceImpl implements IFlwTaskService { } Long taskId = bo.getTaskId(); - FlowTaskVo flowTaskVo = selectById(taskId); + Task task = taskService.getById(taskId); + FlowNode flowNode = getByNodeCode(task.getNodeCode(), task.getDefinitionId()); if ("addSignature".equals(taskOperation) || "reductionSignature".equals(taskOperation)) { - if (flowTaskVo.getNodeRatio().compareTo(BigDecimal.ZERO) == 0) { - throw new ServiceException(flowTaskVo.getNodeName() + "不是会签节点!"); + if (flowNode.getNodeRatio().compareTo(BigDecimal.ZERO) == 0) { + throw new ServiceException(task.getNodeName() + "不是会签节点!"); } } // 设置任务状态并执行对应的任务操作 @@ -628,7 +737,7 @@ public class FlwTaskServiceImpl implements IFlwTaskService { List flowTasks = this.selectByIdList(taskIdList); // 批量删除现有任务的办理人记录 if (CollUtil.isNotEmpty(flowTasks)) { - WorkflowUtils.getFlowUserService().deleteByTaskIds(StreamUtils.toList(flowTasks, FlowTask::getId)); + flwCommonService.getFlowUserService().deleteByTaskIds(StreamUtils.toList(flowTasks, FlowTask::getId)); List userList = flowTasks.stream() .map(flowTask -> { FlowUser flowUser = new FlowUser(); @@ -639,7 +748,7 @@ public class FlwTaskServiceImpl implements IFlwTaskService { }) .collect(Collectors.toList()); if (CollUtil.isNotEmpty(userList)) { - WorkflowUtils.getFlowUserService().saveBatch(userList); + flwCommonService.getFlowUserService().saveBatch(userList); } } } catch (Exception e) { @@ -658,7 +767,7 @@ public class FlwTaskServiceImpl implements IFlwTaskService { public Map> currentTaskAllUser(List taskIdList) { Map> map = new HashMap<>(); // 获取与当前任务关联的用户列表 - List associatedUsers = WorkflowUtils.getFlowUserService().getByAssociateds(taskIdList); + List associatedUsers = flwCommonService.getFlowUserService().getByAssociateds(taskIdList); Map> listMap = StreamUtils.groupByKey(associatedUsers, User::getAssociated); for (Map.Entry> entry : listMap.entrySet()) { List value = entry.getValue(); @@ -678,10 +787,24 @@ public class FlwTaskServiceImpl implements IFlwTaskService { @Override public List currentTaskAllUser(Long taskId) { // 获取与当前任务关联的用户列表 - List userList = WorkflowUtils.getFlowUserService().getByAssociateds(Collections.singletonList(taskId)); + List userList = flwCommonService.getFlowUserService().getByAssociateds(Collections.singletonList(taskId)); if (CollUtil.isEmpty(userList)) { return Collections.emptyList(); } return userService.selectListByIds(StreamUtils.toList(userList, e -> Long.valueOf(e.getProcessedBy()))); } + + /** + * 按照节点编码查询节点 + * + * @param nodeCode 节点编码 + * @param definitionId 流程定义id + */ + @Override + public FlowNode getByNodeCode(String nodeCode, Long definitionId) { + return flowNodeMapper.selectOne(new LambdaQueryWrapper() + .eq(FlowNode::getNodeCode, nodeCode) + .eq(FlowNode::getDefinitionId, definitionId)); + } + } 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 2c431737b..a1ac84595 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 @@ -9,9 +9,9 @@ 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.ProcessCreateTaskEvent; 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; @@ -47,6 +47,19 @@ public class TestLeaveServiceImpl implements ITestLeaveService { private final TestLeaveMapper baseMapper; private final WorkflowService workflowService; + /** + * spel条件表达:判断小于2 + * + * @param leaveDays 待判断的变量(可不传自行返回true或false) + * @return boolean + */ + public boolean eval(Integer leaveDays) { + if (leaveDays < 2) { + return true; + } + return false; + } + /** * 查询请假 */ @@ -123,7 +136,7 @@ public class TestLeaveServiceImpl implements ITestLeaveService { } /** - * 总体流程监听(例如: 草稿,撤销,退回,作废,终止,已完成等) + * 总体流程监听(例如: 草稿,撤销,退回,作废,终止,已完成,单任务完成等) * 正常使用只需#processEvent.flowCode=='leave1' * 示例为了方便则使用startsWith匹配了全部示例key * @@ -151,19 +164,19 @@ public class TestLeaveServiceImpl implements ITestLeaveService { } /** - * 执行办理任务监听 - * 示例:也可通过 @EventListener(condition = "#processTaskEvent.flowCode=='leave1'")进行判断 + * 执行任务创建监听 + * 示例:也可通过 @EventListener(condition = "#processCreateTaskEvent.flowCode=='leave1'")进行判断 * 在方法中判断流程节点key - * if ("xxx".equals(processTaskEvent.getNodeCode())) { + * if ("xxx".equals(processCreateTaskEvent.getNodeCode())) { * //执行业务逻辑 * } * - * @param processTaskEvent 参数 + * @param processCreateTaskEvent 参数 */ - @EventListener(condition = "#processTaskEvent.flowCode.startsWith('leave')") - public void processTaskHandler(ProcessTaskEvent processTaskEvent) { - log.info("当前任务执行了{}", processTaskEvent.toString()); - TestLeave testLeave = baseMapper.selectById(Long.valueOf(processTaskEvent.getBusinessId())); + @EventListener(condition = "#processCreateTaskEvent.flowCode.startsWith('leave')") + public void processCreateTaskHandler(ProcessCreateTaskEvent processCreateTaskEvent) { + log.info("当前任务创建了{}", processCreateTaskEvent.toString()); + TestLeave testLeave = baseMapper.selectById(Long.valueOf(processCreateTaskEvent.getBusinessId())); testLeave.setStatus(BusinessStatusEnum.WAITING.getStatus()); baseMapper.updateById(testLeave); } 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 index 73e4ec789..f539030b4 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/FlwTaskMapper.xml +++ b/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/FlwTaskMapper.xml @@ -31,7 +31,7 @@ d.version, uu.processed_by, uu.type - from flow_task as t + from flow_task t left join flow_user uu on uu.associated = t.id left join flow_definition d on t.definition_id = d.id left join flow_instance i on t.instance_id = i.id diff --git a/script/docker/docker-compose.yml b/script/docker/docker-compose.yml index 885c236ae..35979cb3a 100644 --- a/script/docker/docker-compose.yml +++ b/script/docker/docker-compose.yml @@ -98,7 +98,7 @@ services: network_mode: "host" ruoyi-server1: - image: ruoyi/ruoyi-server:5.3.0 + image: ruoyi/ruoyi-server:5.3.1-BETA container_name: ruoyi-server1 environment: # 时区上海 @@ -113,7 +113,7 @@ services: network_mode: "host" ruoyi-server2: - image: ruoyi/ruoyi-server:5.3.0 + image: ruoyi/ruoyi-server:5.3.1-BETA container_name: ruoyi-server2 environment: # 时区上海 @@ -128,7 +128,7 @@ services: network_mode: "host" ruoyi-monitor-admin: - image: ruoyi/ruoyi-monitor-admin:5.3.0 + image: ruoyi/ruoyi-monitor-admin:5.3.1-BETA container_name: ruoyi-monitor-admin environment: # 时区上海 @@ -140,7 +140,7 @@ services: network_mode: "host" ruoyi-snailjob-server: - image: ruoyi/ruoyi-snailjob-server:5.3.0 + image: ruoyi/ruoyi-snailjob-server:5.3.1-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..22b074f1d 100644 --- a/script/docker/nginx/conf/nginx.conf +++ b/script/docker/nginx/conf/nginx.conf @@ -14,6 +14,8 @@ http { keepalive_timeout 65; # 限制body大小 client_max_body_size 100m; + # 开启静态资源压缩 + gzip_static on; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' diff --git a/script/leave/leave6.json b/script/leave/leave6.json new file mode 100644 index 000000000..c0fb172ec --- /dev/null +++ b/script/leave/leave6.json @@ -0,0 +1,212 @@ +{ + "flowCode" : "leave6", + "flowName" : "请假申请-排他并行会签", + "category" : "100", + "version" : "4", + "formCustom" : "N", + "formPath" : "/workflow/leaveEdit/index", + "nodeList" : [ { + "nodeType" : 0, + "nodeCode" : "122b89a5-7c6f-40a3-aa09-7a263f902054", + "nodeName" : "开始", + "nodeRatio" : 0.000, + "coordinate" : "240,300|240,300", + "formCustom" : "N", + "ext" : "[]", + "skipList" : [ { + "nowNodeCode" : "122b89a5-7c6f-40a3-aa09-7a263f902054", + "nextNodeCode" : "c25a0e86-fdd1-4f03-8e22-14db70389dbd", + "skipType" : "PASS", + "coordinate" : "260,300;350,300" + } ] + }, { + "nodeType" : 1, + "nodeCode" : "c25a0e86-fdd1-4f03-8e22-14db70389dbd", + "nodeName" : "申请人", + "nodeRatio" : 0.000, + "coordinate" : "400,300|400,300", + "ext" : "[{\"code\":\"enum:org.dromara.workflow.common.enums.ButtonPermissionEnum\",\"value\":\"back,termination\"}]", + "skipList" : [ { + "nowNodeCode" : "c25a0e86-fdd1-4f03-8e22-14db70389dbd", + "nextNodeCode" : "07ecda1d-7a0a-47b5-8a91-6186c9473742", + "skipType" : "PASS", + "coordinate" : "450,300;510,300" + } ] + }, { + "nodeType" : 1, + "nodeCode" : "2bfa3919-78cf-4bc1-b59b-df463a4546f9", + "nodeName" : "副经理", + "permissionFlag" : "role:1@@role:3@@role:4", + "nodeRatio" : 0.000, + "coordinate" : "860,200|860,200", + "ext" : "[{\"code\":\"enum:org.dromara.workflow.common.enums.ButtonPermissionEnum\",\"value\":\"back,termination\"}]", + "skipList" : [ { + "nowNodeCode" : "2bfa3919-78cf-4bc1-b59b-df463a4546f9", + "nextNodeCode" : "394e1cc8-b8b2-4189-9f81-44448e88ac32", + "skipType" : "PASS", + "coordinate" : "910,200;1000,200;1000,275" + } ] + }, { + "nodeType" : 1, + "nodeCode" : "ec17f60e-94e0-4d96-a3ce-3417e9d32d60", + "nodeName" : "组长", + "permissionFlag" : "1", + "nodeRatio" : 0.000, + "coordinate" : "860,400|860,400", + "formCustom" : "N", + "ext" : "[{\"code\":\"enum:org.dromara.workflow.common.enums.ButtonPermissionEnum\",\"value\":\"back,termination\"}]", + "skipList" : [ { + "nowNodeCode" : "ec17f60e-94e0-4d96-a3ce-3417e9d32d60", + "nextNodeCode" : "394e1cc8-b8b2-4189-9f81-44448e88ac32", + "skipType" : "PASS", + "coordinate" : "910,400;1000,400;1000,325" + } ] + }, { + "nodeType" : 1, + "nodeCode" : "07ecda1d-7a0a-47b5-8a91-6186c9473742", + "nodeName" : "副组长", + "permissionFlag" : "1", + "nodeRatio" : 0.000, + "coordinate" : "560,300|560,300", + "ext" : "[{\"code\":\"enum:org.dromara.workflow.common.enums.ButtonPermissionEnum\",\"value\":\"back,termination,copy,trust,transfer\"}]", + "skipList" : [ { + "nowNodeCode" : "07ecda1d-7a0a-47b5-8a91-6186c9473742", + "nextNodeCode" : "48117e2c-6328-406b-b102-c4a9d115bb13", + "skipType" : "PASS", + "coordinate" : "610,300;675,300" + } ] + }, { + "nodeType" : 3, + "nodeCode" : "48117e2c-6328-406b-b102-c4a9d115bb13", + "nodeRatio" : 0.000, + "coordinate" : "700,300", + "formCustom" : "N", + "ext" : "[]", + "skipList" : [ { + "nowNodeCode" : "48117e2c-6328-406b-b102-c4a9d115bb13", + "nextNodeCode" : "2bfa3919-78cf-4bc1-b59b-df463a4546f9", + "skipName" : "大于两天", + "skipType" : "PASS", + "skipCondition" : "default@@${leaveDays > 2}", + "coordinate" : "700,275;700,200;810,200|700,237" + }, { + "nowNodeCode" : "48117e2c-6328-406b-b102-c4a9d115bb13", + "nextNodeCode" : "ec17f60e-94e0-4d96-a3ce-3417e9d32d60", + "skipType" : "PASS", + "skipCondition" : "spel@@#{@testLeaveServiceImpl.eval(#leaveDays)}", + "coordinate" : "700,325;700,400;810,400" + } ] + }, { + "nodeType" : 3, + "nodeCode" : "394e1cc8-b8b2-4189-9f81-44448e88ac32", + "nodeRatio" : 0.000, + "coordinate" : "1000,300", + "formCustom" : "N", + "ext" : "[]", + "skipList" : [ { + "nowNodeCode" : "394e1cc8-b8b2-4189-9f81-44448e88ac32", + "nextNodeCode" : "9c93a195-cff2-4e17-ab0a-a4f264191496", + "skipType" : "PASS", + "coordinate" : "1025,300;1130,300" + } ] + }, { + "nodeType" : 1, + "nodeCode" : "9c93a195-cff2-4e17-ab0a-a4f264191496", + "nodeName" : "经理会签", + "permissionFlag" : "1@@3", + "nodeRatio" : 100.000, + "coordinate" : "1180,300|1180,300", + "formCustom" : "N", + "ext" : "[{\"code\":\"enum:org.dromara.workflow.common.enums.ButtonPermissionEnum\",\"value\":\"back,termination,pop,addSign,subSign\"}]", + "skipList" : [ { + "nowNodeCode" : "9c93a195-cff2-4e17-ab0a-a4f264191496", + "nextNodeCode" : "a1a42056-afd1-4e90-88bc-36cbf5a66992", + "skipType" : "PASS", + "coordinate" : "1230,300;1315,300" + } ] + }, { + "nodeType" : 4, + "nodeCode" : "a1a42056-afd1-4e90-88bc-36cbf5a66992", + "nodeRatio" : 0.000, + "coordinate" : "1340,300", + "formCustom" : "N", + "ext" : "[]", + "skipList" : [ { + "nowNodeCode" : "a1a42056-afd1-4e90-88bc-36cbf5a66992", + "nextNodeCode" : "fcfdd9f6-f526-4c1a-b71d-88afa31aebc5", + "skipType" : "PASS", + "coordinate" : "1340,325;1340,400;1430,400" + }, { + "nowNodeCode" : "a1a42056-afd1-4e90-88bc-36cbf5a66992", + "nextNodeCode" : "350dfa0c-a77c-4efa-8527-10efa02d8be4", + "skipType" : "PASS", + "coordinate" : "1340,275;1340,200;1430,200" + } ] + }, { + "nodeType" : 1, + "nodeCode" : "350dfa0c-a77c-4efa-8527-10efa02d8be4", + "nodeName" : "总经理", + "permissionFlag" : "3@@1", + "nodeRatio" : 0.000, + "coordinate" : "1480,200|1480,200", + "formCustom" : "N", + "ext" : "[{\"code\":\"enum:org.dromara.workflow.common.enums.ButtonPermissionEnum\",\"value\":\"back,termination\"}]", + "skipList" : [ { + "nowNodeCode" : "350dfa0c-a77c-4efa-8527-10efa02d8be4", + "nextNodeCode" : "c36a46ef-04f9-463f-bad7-4b395c818519", + "skipType" : "PASS", + "coordinate" : "1530,200;1640,200;1640,275" + } ] + }, { + "nodeType" : 1, + "nodeCode" : "fcfdd9f6-f526-4c1a-b71d-88afa31aebc5", + "nodeName" : "副总经理", + "permissionFlag" : "1@@3", + "nodeRatio" : 0.000, + "coordinate" : "1480,400|1480,400", + "formCustom" : "N", + "ext" : "[{\"code\":\"enum:org.dromara.workflow.common.enums.ButtonPermissionEnum\",\"value\":\"back,termination\"}]", + "skipList" : [ { + "nowNodeCode" : "fcfdd9f6-f526-4c1a-b71d-88afa31aebc5", + "nextNodeCode" : "c36a46ef-04f9-463f-bad7-4b395c818519", + "skipType" : "PASS", + "coordinate" : "1530,400;1640,400;1640,325" + } ] + }, { + "nodeType" : 4, + "nodeCode" : "c36a46ef-04f9-463f-bad7-4b395c818519", + "nodeRatio" : 0.000, + "coordinate" : "1640,300", + "formCustom" : "N", + "ext" : "[]", + "skipList" : [ { + "nowNodeCode" : "c36a46ef-04f9-463f-bad7-4b395c818519", + "nextNodeCode" : "3fcea762-b53a-4ae1-8365-7bec90444828", + "skipType" : "PASS", + "coordinate" : "1665,300;1770,300" + } ] + }, { + "nodeType" : 1, + "nodeCode" : "3fcea762-b53a-4ae1-8365-7bec90444828", + "nodeName" : "董事", + "permissionFlag" : "1", + "nodeRatio" : 0.000, + "coordinate" : "1820,300|1820,300", + "formCustom" : "N", + "ext" : "[{\"code\":\"enum:org.dromara.workflow.common.enums.ButtonPermissionEnum\",\"value\":\"back,termination\"}]", + "skipList" : [ { + "nowNodeCode" : "3fcea762-b53a-4ae1-8365-7bec90444828", + "nextNodeCode" : "9cfbfd3e-6c04-41d6-9fc2-6787a7d2cd31", + "skipType" : "PASS", + "coordinate" : "1870,300;1960,300" + } ] + }, { + "nodeType" : 2, + "nodeCode" : "9cfbfd3e-6c04-41d6-9fc2-6787a7d2cd31", + "nodeName" : "结束", + "nodeRatio" : 0.000, + "coordinate" : "1980,300|1980,300", + "formCustom" : "N", + "ext" : "[]" + } ] +} \ No newline at end of file diff --git a/script/sql/oracle/oracle_ry_vue_5.X.sql b/script/sql/oracle/oracle_ry_vue_5.X.sql index 94024c999..7fff0b443 100644 --- a/script/sql/oracle/oracle_ry_vue_5.X.sql +++ b/script/sql/oracle/oracle_ry_vue_5.X.sql @@ -75,7 +75,7 @@ create table sys_tenant ( tenant_id varchar2(20) not null, contact_user_name varchar2(20) default '', contact_phone varchar2(20) default '', - company_name varchar2(50) default '', + company_name varchar2(30) default '', license_number varchar2(30) default '', address varchar2(200) default '', intro varchar2(200) default '', @@ -352,7 +352,7 @@ comment on column sys_role.tenant_id is '租户编号'; comment on column sys_role.role_name is '角色名称'; comment on column sys_role.role_key is '角色权限字符串'; comment on column sys_role.role_sort is '显示顺序'; -comment on column sys_role.data_scope is '数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限)'; +comment on column sys_role.data_scope is '数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限 5:仅本人数据权限 6:部门及以下或本人数据权限)'; 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停用)'; @@ -1159,6 +1159,7 @@ create table sys_oss ( file_suffix varchar2(10) not null, url varchar2(500) not null, service varchar2(20) default 'minio' not null, + ext1 varchar2(500) default '', create_dept number(20) default null, create_by number(20) default null, create_time date, @@ -1176,6 +1177,7 @@ comment on column sys_oss.original_name is '原名'; comment on column sys_oss.file_suffix is '文件后缀名'; comment on column sys_oss.url is 'URL地址'; comment on column sys_oss.service is '服务商'; +comment on column sys_oss.ext1 is '扩展字段'; comment on column sys_oss.create_dept is '创建部门'; comment on column sys_oss.create_time is '创建时间'; comment on column sys_oss.create_by is '上传者'; diff --git a/script/sql/oracle/oracle_ry_workflow.sql b/script/sql/oracle/oracle_ry_workflow.sql index b515b78ff..baecd91fa 100644 --- a/script/sql/oracle/oracle_ry_workflow.sql +++ b/script/sql/oracle/oracle_ry_workflow.sql @@ -47,7 +47,6 @@ create table FLOW_NODE 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), @@ -58,6 +57,7 @@ create table FLOW_NODE VERSION VARCHAR2(20), CREATE_TIME DATE, UPDATE_TIME DATE, + EXT VARCHAR2(500), DEL_FLAG VARCHAR2(1) default '0', TENANT_ID VARCHAR2(40), PERMISSION_FLAG VARCHAR2(200) @@ -73,7 +73,6 @@ 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 '监听器路径'; @@ -84,6 +83,7 @@ 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.EXT 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 '权限标识(权限类型:权限标识,可以多个,用逗号隔开)'; diff --git a/script/sql/postgres/postgres_ry_vue_5.X.sql b/script/sql/postgres/postgres_ry_vue_5.X.sql index d18cfebd4..523cbe266 100644 --- a/script/sql/postgres/postgres_ry_vue_5.X.sql +++ b/script/sql/postgres/postgres_ry_vue_5.X.sql @@ -75,7 +75,7 @@ create table if not exists sys_tenant tenant_id varchar(20) not null, contact_user_name varchar(20) default null::varchar, contact_phone varchar(20) default null::varchar, - company_name varchar(50) default null::varchar, + company_name varchar(30) default null::varchar, license_number varchar(30) default null::varchar, address varchar(200) default null::varchar, intro varchar(200) default null::varchar, @@ -353,7 +353,7 @@ comment on column sys_role.tenant_id is '租户编号'; comment on column sys_role.role_name is '角色名称'; comment on column sys_role.role_key is '角色权限字符串'; comment on column sys_role.role_sort is '显示顺序'; -comment on column sys_role.data_scope is '数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限)'; +comment on column sys_role.data_scope is '数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限 5:仅本人数据权限 6:部门及以下或本人数据权限)'; 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停用)'; @@ -1160,6 +1160,7 @@ create table if not exists sys_oss original_name varchar(255) default ''::varchar not null, file_suffix varchar(10) default ''::varchar not null, url varchar(500) default ''::varchar not null, + ext1 varchar(500) default ''::varchar, create_dept int8, create_by int8, create_time timestamp, @@ -1176,6 +1177,7 @@ comment on column sys_oss.file_name is '文件名'; comment on column sys_oss.original_name is '原名'; comment on column sys_oss.file_suffix is '文件后缀名'; comment on column sys_oss.url is 'URL地址'; +comment on column sys_oss.ext1 is '扩展字段'; comment on column sys_oss.create_by is '上传人'; comment on column sys_oss.create_dept is '创建部门'; comment on column sys_oss.create_time is '创建时间'; diff --git a/script/sql/postgres/postgres_ry_workflow.sql b/script/sql/postgres/postgres_ry_workflow.sql index 80cd414c3..3fbd70f05 100644 --- a/script/sql/postgres/postgres_ry_workflow.sql +++ b/script/sql/postgres/postgres_ry_workflow.sql @@ -50,7 +50,6 @@ CREATE TABLE flow_node 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, -- 监听器路径 @@ -61,6 +60,7 @@ CREATE TABLE flow_node "version" varchar(20) NOT NULL, -- 版本 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_node_pkey PRIMARY KEY (id) @@ -75,7 +75,6 @@ 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 '监听器路径'; @@ -86,6 +85,7 @@ 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.ext IS '扩展属性'; COMMENT ON COLUMN flow_node.del_flag IS '删除标志'; COMMENT ON COLUMN flow_node.tenant_id IS '租户id'; diff --git a/script/sql/ry_vue_5.X.sql b/script/sql/ry_vue_5.X.sql index 48e5f35b5..c17e4a01a 100644 --- a/script/sql/ry_vue_5.X.sql +++ b/script/sql/ry_vue_5.X.sql @@ -45,7 +45,7 @@ create table sys_tenant tenant_id varchar(20) not null comment '租户编号', contact_user_name varchar(20) comment '联系人', contact_phone varchar(20) comment '联系电话', - company_name varchar(50) comment '企业名称', + company_name varchar(30) comment '企业名称', license_number varchar(30) comment '统一社会信用代码', address varchar(200) comment '地址', intro varchar(200) comment '企业简介', @@ -208,7 +208,7 @@ create table sys_role ( role_name varchar(30) not null comment '角色名称', role_key varchar(100) not null comment '角色权限字符串', role_sort int(4) not null comment '显示顺序', - data_scope char(1) default '1' comment '数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限)', + data_scope char(1) default '1' comment '数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限 5:仅本人数据权限 6:部门及以下或本人数据权限)', menu_check_strictly tinyint(1) default 1 comment '菜单树选择项是否关联显示', dept_check_strictly tinyint(1) default 1 comment '部门树选择项是否关联显示', status char(1) not null comment '角色状态(0正常 1停用)', @@ -828,6 +828,7 @@ create table sys_oss ( original_name varchar(255) not null default '' comment '原名', file_suffix varchar(10) not null default '' comment '文件后缀名', url varchar(500) not null comment 'URL地址', + ext1 text default null comment '扩展字段', create_dept bigint(20) default null comment '创建部门', create_time datetime default null comment '创建时间', create_by bigint(20) default null comment '上传人', diff --git a/script/sql/ry_workflow.sql b/script/sql/ry_workflow.sql index 9455636a0..652f4c084 100644 --- a/script/sql/ry_workflow.sql +++ b/script/sql/ry_workflow.sql @@ -24,7 +24,7 @@ CREATE TABLE `flow_definition` CREATE TABLE `flow_node` ( - `id` bigint unsigned NOT NULL COMMENT '主键id', + `id` bigint 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 '流程节点编码', @@ -32,7 +32,6 @@ CREATE TABLE `flow_node` `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 '监听器路径', @@ -43,6 +42,7 @@ CREATE TABLE `flow_node` `version` varchar(20) NOT NULL COMMENT '版本', `create_time` datetime DEFAULT NULL COMMENT '创建时间', `update_time` datetime DEFAULT NULL COMMENT '更新时间', + `ext` text COMMENT '扩展属性', `del_flag` char(1) DEFAULT '0' COMMENT '删除标志', `tenant_id` varchar(40) DEFAULT NULL COMMENT '租户id', PRIMARY KEY (`id`) USING BTREE diff --git a/script/sql/sqlserver/sqlserver_ry_vue_5.X.sql b/script/sql/sqlserver/sqlserver_ry_vue_5.X.sql index 9f8481a22..0567f31d9 100644 --- a/script/sql/sqlserver/sqlserver_ry_vue_5.X.sql +++ b/script/sql/sqlserver/sqlserver_ry_vue_5.X.sql @@ -222,7 +222,7 @@ CREATE TABLE sys_tenant tenant_id nvarchar(20) NOT NULL, contact_user_name nvarchar(20) NULL, contact_phone nvarchar(20) NULL, - company_name nvarchar(50) NULL, + company_name nvarchar(30) NULL, license_number nvarchar(30) NULL, address nvarchar(200) NULL, intro nvarchar(200) NULL, @@ -2318,7 +2318,7 @@ EXEC sys.sp_addextendedproperty 'COLUMN', N'role_sort' GO EXEC sys.sp_addextendedproperty - 'MS_Description', N'数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限)' , + 'MS_Description', N'数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限 5:仅本人数据权限 6:部门及以下或本人数据权限)' , 'SCHEMA', N'dbo', 'TABLE', N'sys_role', 'COLUMN', N'data_scope' @@ -2923,6 +2923,7 @@ CREATE TABLE sys_oss original_name nvarchar(255) DEFAULT '' NOT NULL, file_suffix nvarchar(10) DEFAULT '' NOT NULL, url nvarchar(500) NOT NULL, + ext1 nvarchar(500) DEFAULT '' NULL, create_dept bigint NULL, create_time datetime2(7) NULL, create_by bigint NULL, @@ -2972,6 +2973,12 @@ EXEC sp_addextendedproperty 'TABLE', N'sys_oss', 'COLUMN', N'url' GO +EXEC sp_addextendedproperty + 'MS_Description', N'扩展字段', + 'SCHEMA', N'dbo', + 'TABLE', N'sys_oss', + 'COLUMN', N'ext1' +GO EXEC sys.sp_addextendedproperty 'MS_Description', N'创建部门' , 'SCHEMA', N'dbo', diff --git a/script/sql/sqlserver/sqlserver_ry_workflow.sql b/script/sql/sqlserver/sqlserver_ry_workflow.sql index ea4b7205a..f376e8485 100644 --- a/script/sql/sqlserver/sqlserver_ry_workflow.sql +++ b/script/sql/sqlserver/sqlserver_ry_workflow.sql @@ -149,7 +149,6 @@ CREATE TABLE flow_node ( 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, @@ -160,6 +159,7 @@ CREATE TABLE flow_node ( version nvarchar(20) NOT 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_nod__3213E83F372470DE PRIMARY KEY CLUSTERED (id) @@ -225,13 +225,6 @@ EXEC sp_addextendedproperty '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', @@ -302,6 +295,13 @@ EXEC sp_addextendedproperty 'COLUMN', N'update_time' GO +EXEC sp_addextendedproperty +'MS_Description', N'扩展属性', +'SCHEMA', N'dbo', +'TABLE', N'flow_node', +'COLUMN', N'ext' +GO + EXEC sp_addextendedproperty 'MS_Description', N'删除标志', 'SCHEMA', N'dbo', diff --git a/script/sql/update/oracle/update_5.3.0-5.3.1.sql b/script/sql/update/oracle/update_5.3.0-5.3.1.sql new file mode 100644 index 000000000..143c909d3 --- /dev/null +++ b/script/sql/update/oracle/update_5.3.0-5.3.1.sql @@ -0,0 +1,6 @@ +ALTER TABLE flow_node DROP COLUMN skip_any_node; +ALTER TABLE flow_node ADD (ext VARCHAR2(500)); +COMMENT ON COLUMN flow_node.ext IS '扩展属性'; + +ALTER TABLE sys_oss ADD (ext1 VARCHAR2(500)); +COMMENT ON COLUMN sys_oss.ext1 IS '扩展属性'; diff --git a/script/sql/update/postgres/update_5.3.0-5.3.1.sql b/script/sql/update/postgres/update_5.3.0-5.3.1.sql new file mode 100644 index 000000000..31bf7465e --- /dev/null +++ b/script/sql/update/postgres/update_5.3.0-5.3.1.sql @@ -0,0 +1,6 @@ +ALTER TABLE flow_node DROP COLUMN skip_any_node; +ALTER TABLE flow_node ADD COLUMN ext varchar(500); +COMMENT ON COLUMN flow_node.ext IS '扩展属性'; + +ALTER TABLE sys_oss ADD COLUMN ext1 varchar(500)); +COMMENT ON COLUMN sys_oss.ext1 IS '扩展属性'; diff --git a/script/sql/update/sqlserver/update_5.3.0-5.3.1.sql b/script/sql/update/sqlserver/update_5.3.0-5.3.1.sql new file mode 100644 index 000000000..8a22c00bb --- /dev/null +++ b/script/sql/update/sqlserver/update_5.3.0-5.3.1.sql @@ -0,0 +1,18 @@ +ALTER TABLE flow_node DROP COLUMN skip_any_node; +ALTER TABLE flow_node ADD ext nvarchar(500) NULL; + +EXEC sp_addextendedproperty +'MS_Description', N'扩展属性', +'SCHEMA', N'dbo', +'TABLE', N'flow_node', +'COLUMN', N'ext' +GO + +ALTER TABLE sys_oss ADD ext1 nvarchar(500) NULL; + +EXEC sp_addextendedproperty +'MS_Description', N'扩展属性', +'SCHEMA', N'dbo', +'TABLE', N'sys_oss', +'COLUMN', N'ext1' +GO diff --git a/script/sql/update/update_5.3.0-5.3.1.sql b/script/sql/update/update_5.3.0-5.3.1.sql new file mode 100644 index 000000000..f1a0efd7b --- /dev/null +++ b/script/sql/update/update_5.3.0-5.3.1.sql @@ -0,0 +1,6 @@ +ALTER TABLE `flow_node` DROP COLUMN `skip_any_node`; +ALTER TABLE `flow_node` + ADD COLUMN `ext` text NULL COMMENT '扩展属性' AFTER `update_time`; + +ALTER TABLE `sys_oss` + ADD COLUMN `ext1` text NULL COMMENT '扩展属性' AFTER `url`;