From 6ae9bbdb317f919e85edba687f599922c364abe4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Fri, 25 Oct 2024 11:30:56 +0800 Subject: [PATCH 001/175] =?UTF-8?q?fix=20=E4=BF=AE=E5=A4=8D=20=E6=B3=A8?= =?UTF-8?q?=E5=86=8C=E6=97=A5=E5=BF=97=E8=AE=B0=E5=BD=95=E7=8A=B6=E6=80=81?= =?UTF-8?q?=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/org/dromara/web/service/SysRegisterService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ruoyi-admin/src/main/java/org/dromara/web/service/SysRegisterService.java b/ruoyi-admin/src/main/java/org/dromara/web/service/SysRegisterService.java index ddab279bc..9ec08132e 100644 --- a/ruoyi-admin/src/main/java/org/dromara/web/service/SysRegisterService.java +++ b/ruoyi-admin/src/main/java/org/dromara/web/service/SysRegisterService.java @@ -84,11 +84,11 @@ public class SysRegisterService { String captcha = RedisUtils.getCacheObject(verifyKey); RedisUtils.deleteObject(verifyKey); if (captcha == null) { - recordLogininfor(tenantId, username, Constants.REGISTER, MessageUtils.message("user.jcaptcha.expire")); + recordLogininfor(tenantId, username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire")); throw new CaptchaExpireException(); } if (!code.equalsIgnoreCase(captcha)) { - recordLogininfor(tenantId, username, Constants.REGISTER, MessageUtils.message("user.jcaptcha.error")); + recordLogininfor(tenantId, username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error")); throw new CaptchaException(); } } From ddc8bd1139980f75b8eab632a430752b8f880989 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Sun, 27 Oct 2024 23:25:22 +0800 Subject: [PATCH 002/175] =?UTF-8?q?[=E9=87=8D=E5=A4=A7=E6=9B=B4=E6=96=B0]?= =?UTF-8?q?=20update=20(=E5=AE=9E=E9=AA=8C=E6=80=A7=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=E6=85=8E=E6=9B=B4)=E9=87=8D=E6=9E=84=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E6=9D=83=E9=99=90=E5=AE=9E=E7=8E=B0=E9=80=BB=E8=BE=91=20?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E4=BB=BB=E6=84=8Fmapper=E6=96=B9=E6=B3=95?= =?UTF-8?q?=E6=A0=87=E6=B3=A8=E6=B3=A8=E8=A7=A3=20=E6=97=A0=E9=9C=80?= =?UTF-8?q?=E5=86=8D=E6=89=BE=E7=9C=9F=E5=AE=9Emapper=E6=A0=87=E6=B3=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mybatis/aspect/DataPermissionAspect.java | 50 ++++++ .../mybatis/config/MybatisPlusConfig.java | 11 +- .../handler/PlusDataPermissionHandler.java | 146 +++--------------- .../mybatis/helper/DataPermissionHelper.java | 28 ++++ .../PlusDataPermissionInterceptor.java | 10 +- .../dromara/demo/mapper/TestDemoMapper.java | 8 +- 6 files changed, 123 insertions(+), 130 deletions(-) create mode 100644 ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/aspect/DataPermissionAspect.java diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/aspect/DataPermissionAspect.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/aspect/DataPermissionAspect.java new file mode 100644 index 000000000..1c83cc392 --- /dev/null +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/aspect/DataPermissionAspect.java @@ -0,0 +1,50 @@ +package org.dromara.common.mybatis.aspect; + +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.AfterReturning; +import org.aspectj.lang.annotation.AfterThrowing; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.dromara.common.mybatis.annotation.DataPermission; +import org.dromara.common.mybatis.helper.DataPermissionHelper; + +/** + * 数据权限处理 + * + * @author Lion Li + */ +@Slf4j +@Aspect +public class DataPermissionAspect { + + /** + * 处理请求前执行 + */ + @Before(value = "@annotation(dataPermission)") + public void doBefore(JoinPoint joinPoint, DataPermission dataPermission) { + DataPermissionHelper.setPermission(dataPermission); + } + + /** + * 处理完请求后执行 + * + * @param joinPoint 切点 + */ + @AfterReturning(pointcut = "@annotation(dataPermission)") + public void doAfterReturning(JoinPoint joinPoint, DataPermission dataPermission) { + DataPermissionHelper.removePermission(); + } + + /** + * 拦截异常操作 + * + * @param joinPoint 切点 + * @param e 异常 + */ + @AfterThrowing(value = "@annotation(dataPermission)", throwing = "e") + public void doAfterThrowing(JoinPoint joinPoint, DataPermission dataPermission, Exception e) { + DataPermissionHelper.removePermission(); + } + +} diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/config/MybatisPlusConfig.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/config/MybatisPlusConfig.java index 0bc5b66a1..f7d14ee97 100644 --- a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/config/MybatisPlusConfig.java +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/config/MybatisPlusConfig.java @@ -10,6 +10,7 @@ import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerIntercept import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor; import org.dromara.common.core.factory.YmlPropertySourceFactory; import org.dromara.common.core.utils.SpringUtils; +import org.dromara.common.mybatis.aspect.DataPermissionAspect; import org.dromara.common.mybatis.handler.InjectionMetaObjectHandler; import org.dromara.common.mybatis.handler.MybatisExceptionHandler; import org.dromara.common.mybatis.interceptor.PlusDataPermissionInterceptor; @@ -51,7 +52,15 @@ public class MybatisPlusConfig { * 数据权限拦截器 */ public PlusDataPermissionInterceptor dataPermissionInterceptor() { - return new PlusDataPermissionInterceptor(SpringUtils.getProperty("mybatis-plus.mapperPackage")); + return new PlusDataPermissionInterceptor(); + } + + /** + * 数据权限切面处理器 + */ + @Bean + public DataPermissionAspect dataPermissionAspect() { + return new DataPermissionAspect(); } /** diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/PlusDataPermissionHandler.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/PlusDataPermissionHandler.java index ab7e0f6e4..f46ec6922 100644 --- a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/PlusDataPermissionHandler.java +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/PlusDataPermissionHandler.java @@ -1,6 +1,5 @@ package org.dromara.common.mybatis.handler; -import cn.hutool.core.annotation.AnnotationUtil; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; import lombok.extern.slf4j.Slf4j; @@ -9,7 +8,6 @@ import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.operators.conditional.AndExpression; import net.sf.jsqlparser.expression.operators.relational.ParenthesedExpressionList; import net.sf.jsqlparser.parser.CCJSqlParserUtil; -import org.apache.ibatis.io.Resources; import org.dromara.common.core.domain.dto.RoleDTO; import org.dromara.common.core.domain.model.LoginUser; import org.dromara.common.core.exception.ServiceException; @@ -21,27 +19,17 @@ import org.dromara.common.mybatis.annotation.DataPermission; import org.dromara.common.mybatis.enums.DataScopeType; import org.dromara.common.mybatis.helper.DataPermissionHelper; import org.dromara.common.satoken.utils.LoginHelper; -import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.expression.BeanFactoryResolver; -import org.springframework.core.io.Resource; -import org.springframework.core.io.support.PathMatchingResourcePatternResolver; -import org.springframework.core.io.support.ResourcePatternResolver; -import org.springframework.core.type.ClassMetadata; -import org.springframework.core.type.classreading.CachingMetadataReaderFactory; import org.springframework.expression.BeanResolver; import org.springframework.expression.ExpressionParser; import org.springframework.expression.ParserContext; import org.springframework.expression.common.TemplateParserContext; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.expression.spel.support.StandardEvaluationContext; -import org.springframework.util.ClassUtils; -import java.lang.reflect.Method; import java.util.Arrays; import java.util.HashSet; -import java.util.Map; import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; import java.util.function.Function; /** @@ -53,11 +41,6 @@ import java.util.function.Function; @Slf4j public class PlusDataPermissionHandler { - /** - * 方法或类(名称) 与 注解的映射关系缓存 - */ - private final Map dataPermissionCacheMap = new ConcurrentHashMap<>(); - /** * spel 解析器 */ @@ -68,15 +51,6 @@ public class PlusDataPermissionHandler { */ private final BeanResolver beanResolver = new BeanFactoryResolver(SpringUtils.getBeanFactory()); - /** - * 构造方法,扫描指定包下的 Mapper 类并初始化缓存 - * - * @param mapperPackage Mapper 类所在的包路径 - */ - public PlusDataPermissionHandler(String mapperPackage) { - scanMapperClasses(mapperPackage); - } - /** * 获取数据过滤条件的 SQL 片段 * @@ -86,24 +60,24 @@ public class PlusDataPermissionHandler { * @return 数据过滤条件的 SQL 片段 */ public Expression getSqlSegment(Expression where, String mappedStatementId, boolean isSelect) { - // 获取数据权限配置 - DataPermission dataPermission = getDataPermission(mappedStatementId); - // 获取当前登录用户信息 - LoginUser currentUser = DataPermissionHelper.getVariable("user"); - if (ObjectUtil.isNull(currentUser)) { - currentUser = LoginHelper.getLoginUser(); - DataPermissionHelper.setVariable("user", currentUser); - } - // 如果是超级管理员或租户管理员,则不过滤数据 - if (LoginHelper.isSuperAdmin() || LoginHelper.isTenantAdmin()) { - return where; - } - // 构造数据过滤条件的 SQL 片段 - String dataFilterSql = buildDataFilter(dataPermission, isSelect); - if (StringUtils.isBlank(dataFilterSql)) { - return where; - } try { + // 获取数据权限配置 + DataPermission dataPermission = DataPermissionHelper.getPermission(); + // 获取当前登录用户信息 + LoginUser currentUser = DataPermissionHelper.getVariable("user"); + if (ObjectUtil.isNull(currentUser)) { + currentUser = LoginHelper.getLoginUser(); + DataPermissionHelper.setVariable("user", currentUser); + } + // 如果是超级管理员或租户管理员,则不过滤数据 + if (LoginHelper.isSuperAdmin() || LoginHelper.isTenantAdmin()) { + return where; + } + // 构造数据过滤条件的 SQL 片段 + String dataFilterSql = buildDataFilter(dataPermission, isSelect); + if (StringUtils.isBlank(dataFilterSql)) { + return where; + } Expression expression = CCJSqlParserUtil.parseExpression(dataFilterSql); // 数据权限使用单独的括号 防止与其他条件冲突 ParenthesedExpressionList parenthesis = new ParenthesedExpressionList<>(expression); @@ -114,6 +88,8 @@ public class PlusDataPermissionHandler { } } catch (JSQLParserException e) { throw new ServiceException("数据权限解析异常 => " + e.getMessage()); + } finally { + DataPermissionHelper.removePermission(); } } @@ -170,8 +146,11 @@ public class PlusDataPermissionHandler { context.setVariable(dataColumn.key()[i], dataColumn.value()[i]); } + // 忽略数据权限 防止spel表达式内有其他sql查询导致死循环调用 + String sql = DataPermissionHelper.ignore(() -> + parser.parseExpression(type.getSqlTemplate(), parserContext).getValue(context, String.class) + ); // 解析sql模板并填充 - String sql = parser.parseExpression(type.getSqlTemplate(), parserContext).getValue(context, String.class); conditions.add(joinStr + sql); isSuccess = true; } @@ -188,87 +167,12 @@ public class PlusDataPermissionHandler { return ""; } - /** - * 扫描指定包下的 Mapper 类,并查找其中带有特定注解的方法或类 - * - * @param mapperPackage Mapper 类所在的包路径 - */ - private void scanMapperClasses(String mapperPackage) { - // 创建资源解析器和元数据读取工厂 - PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); - CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory(); - // 将 Mapper 包路径按分隔符拆分为数组 - String[] packagePatternArray = StringUtils.splitPreserveAllTokens(mapperPackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS); - String classpath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX; - try { - for (String packagePattern : packagePatternArray) { - // 将包路径转换为资源路径 - String path = ClassUtils.convertClassNameToResourcePath(packagePattern); - // 获取指定路径下的所有 .class 文件资源 - Resource[] resources = resolver.getResources(classpath + path + "/*.class"); - for (Resource resource : resources) { - // 获取资源的类元数据 - ClassMetadata classMetadata = factory.getMetadataReader(resource).getClassMetadata(); - // 获取资源对应的类对象 - Class clazz = Resources.classForName(classMetadata.getClassName()); - // 查找类中的特定注解 - findAnnotation(clazz); - } - } - } catch (Exception e) { - log.error("初始化数据安全缓存时出错:{}", e.getMessage()); - } - } - - /** - * 在指定的类中查找特定的注解 DataPermission,并将带有这个注解的方法或类存储到 dataPermissionCacheMap 中 - * - * @param clazz 要查找的类 - */ - private void findAnnotation(Class clazz) { - DataPermission dataPermission; - for (Method method : clazz.getMethods()) { - if (method.isDefault() || method.isVarArgs()) { - continue; - } - String mappedStatementId = clazz.getName() + "." + method.getName(); - if (AnnotationUtil.hasAnnotation(method, DataPermission.class)) { - dataPermission = AnnotationUtil.getAnnotation(method, DataPermission.class); - dataPermissionCacheMap.put(mappedStatementId, dataPermission); - } - } - if (AnnotationUtil.hasAnnotation(clazz, DataPermission.class)) { - dataPermission = AnnotationUtil.getAnnotation(clazz, DataPermission.class); - dataPermissionCacheMap.put(clazz.getName(), dataPermission); - } - } - - /** - * 根据映射语句 ID 或类名获取对应的 DataPermission 注解对象 - * - * @param mapperId 映射语句 ID - * @return DataPermission 注解对象,如果不存在则返回 null - */ - public DataPermission getDataPermission(String mapperId) { - // 检查缓存中是否包含映射语句 ID 对应的 DataPermission 注解对象 - if (dataPermissionCacheMap.containsKey(mapperId)) { - return dataPermissionCacheMap.get(mapperId); - } - // 如果缓存中不包含映射语句 ID 对应的 DataPermission 注解对象,则尝试使用类名作为键查找 - String clazzName = mapperId.substring(0, mapperId.lastIndexOf(".")); - if (dataPermissionCacheMap.containsKey(clazzName)) { - return dataPermissionCacheMap.get(clazzName); - } - return null; - } - /** * 检查给定的映射语句 ID 是否有效,即是否能够找到对应的 DataPermission 注解对象 * - * @param mapperId 映射语句 ID * @return 如果找到对应的 DataPermission 注解对象,则返回 false;否则返回 true */ - public boolean invalid(String mapperId) { - return getDataPermission(mapperId) == null; + public boolean invalid() { + return DataPermissionHelper.getPermission() == null; } } diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/helper/DataPermissionHelper.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/helper/DataPermissionHelper.java index 932f17388..f03d74e83 100644 --- a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/helper/DataPermissionHelper.java +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/helper/DataPermissionHelper.java @@ -9,6 +9,7 @@ import com.baomidou.mybatisplus.core.plugins.InterceptorIgnoreHelper; import lombok.AccessLevel; import lombok.NoArgsConstructor; import org.dromara.common.core.utils.reflect.ReflectUtils; +import org.dromara.common.mybatis.annotation.DataPermission; import java.util.HashMap; import java.util.Map; @@ -29,6 +30,33 @@ public class DataPermissionHelper { private static final ThreadLocal> REENTRANT_IGNORE = ThreadLocal.withInitial(Stack::new); + private static final ThreadLocal PERMISSION_CACHE = new ThreadLocal<>(); + + /** + * 获取当前执行mapper权限注解 + * + * @return 返回当前执行mapper权限注解 + */ + public static DataPermission getPermission() { + return PERMISSION_CACHE.get(); + } + + /** + * 设置当前执行mapper权限注解 + * + * @param dataPermission 数据权限注解 + */ + public static void setPermission(DataPermission dataPermission) { + PERMISSION_CACHE.set(dataPermission); + } + + /** + * 删除当前执行mapper权限注解 + */ + public static void removePermission() { + PERMISSION_CACHE.remove(); + } + /** * 从上下文中获取指定键的变量值,并将其转换为指定的类型 * diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/interceptor/PlusDataPermissionInterceptor.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/interceptor/PlusDataPermissionInterceptor.java index 85a4d0abc..587a99886 100644 --- a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/interceptor/PlusDataPermissionInterceptor.java +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/interceptor/PlusDataPermissionInterceptor.java @@ -39,11 +39,9 @@ public class PlusDataPermissionInterceptor extends BaseMultiTableInnerIntercepto /** * 构造函数,初始化 PlusDataPermissionHandler 实例 - * - * @param mapperPackage 扫描的映射器包 */ - public PlusDataPermissionInterceptor(String mapperPackage) { - this.dataPermissionHandler = new PlusDataPermissionHandler(mapperPackage); + public PlusDataPermissionInterceptor() { + this.dataPermissionHandler = new PlusDataPermissionHandler(); } /** @@ -64,7 +62,7 @@ public class PlusDataPermissionInterceptor extends BaseMultiTableInnerIntercepto return; } // 检查是否缺少有效的数据权限注解 - if (dataPermissionHandler.invalid(ms.getId())) { + if (dataPermissionHandler.invalid()) { return; } // 解析 sql 分配对应方法 @@ -92,7 +90,7 @@ public class PlusDataPermissionInterceptor extends BaseMultiTableInnerIntercepto return; } // 检查是否缺少有效的数据权限注解 - if (dataPermissionHandler.invalid(ms.getId())) { + if (dataPermissionHandler.invalid()) { return; } PluginUtils.MPBoundSql mpBs = mpSh.mPBoundSql(); diff --git a/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/mapper/TestDemoMapper.java b/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/mapper/TestDemoMapper.java index 57efdc7da..19b2d52df 100644 --- a/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/mapper/TestDemoMapper.java +++ b/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/mapper/TestDemoMapper.java @@ -34,14 +34,18 @@ public interface TestDemoMapper extends BaseMapperPlus { @DataColumn(key = "deptName", value = "dept_id"), @DataColumn(key = "userName", value = "user_id") }) - List selectList(IPage page, @Param(Constants.WRAPPER) Wrapper queryWrapper); + default

> P selectVoPage(IPage page, Wrapper wrapper) { + return selectVoPage(page, wrapper, this.currentVoClass()); + } @Override @DataPermission({ @DataColumn(key = "deptName", value = "dept_id"), @DataColumn(key = "userName", value = "user_id") }) - List selectList(@Param(Constants.WRAPPER) Wrapper queryWrapper); + default List selectVoList(Wrapper wrapper) { + return selectVoList(wrapper, this.currentVoClass()); + } @Override @DataPermission(value = { From 6731b7947b06fd5fcc266f87769728243fe82e5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Mon, 28 Oct 2024 10:21:45 +0800 Subject: [PATCH 003/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E8=A7=92?= =?UTF-8?q?=E8=89=B2=E6=B8=85=E7=90=86=E5=9C=A8=E7=BA=BF=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../system/service/ISysRoleService.java | 2 + .../service/impl/SysRoleServiceImpl.java | 41 ++++++++++++++++--- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysRoleService.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysRoleService.java index 64740aeff..cec4bf775 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysRoleService.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysRoleService.java @@ -197,4 +197,6 @@ public interface ISysRoleService { void cleanOnlineUserByRole(Long roleId); + void cleanOnlineUser(List userIds); + } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysRoleServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysRoleServiceImpl.java index 9b8b0ecbe..fee0a5b77 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysRoleServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysRoleServiceImpl.java @@ -435,7 +435,7 @@ public class SysRoleServiceImpl implements ISysRoleService { .eq(SysUserRole::getRoleId, userRole.getRoleId()) .eq(SysUserRole::getUserId, userRole.getUserId())); if (rows > 0) { - cleanOnlineUserByRole(userRole.getRoleId()); + cleanOnlineUser(List.of(userRole.getUserId())); } return rows; } @@ -449,11 +449,12 @@ public class SysRoleServiceImpl implements ISysRoleService { */ @Override public int deleteAuthUsers(Long roleId, Long[] userIds) { + List ids = List.of(userIds); int rows = userRoleMapper.delete(new LambdaQueryWrapper() .eq(SysUserRole::getRoleId, roleId) - .in(SysUserRole::getUserId, Arrays.asList(userIds))); + .in(SysUserRole::getUserId, ids)); if (rows > 0) { - cleanOnlineUserByRole(roleId); + cleanOnlineUser(ids); } return rows; } @@ -469,7 +470,8 @@ public class SysRoleServiceImpl implements ISysRoleService { public int insertAuthUsers(Long roleId, Long[] userIds) { // 新增用户与角色管理 int rows = 1; - List list = StreamUtils.toList(List.of(userIds), userId -> { + List ids = List.of(userIds); + List list = StreamUtils.toList(ids, userId -> { SysUserRole ur = new SysUserRole(); ur.setUserId(userId); ur.setRoleId(roleId); @@ -479,7 +481,7 @@ public class SysRoleServiceImpl implements ISysRoleService { rows = userRoleMapper.insertBatch(list) ? list.size() : 0; } if (rows > 0) { - cleanOnlineUserByRole(roleId); + cleanOnlineUser(ids); } return rows; } @@ -503,6 +505,9 @@ public class SysRoleServiceImpl implements ISysRoleService { return; } LoginUser loginUser = LoginHelper.getLoginUser(token); + if (ObjectUtil.isNull(loginUser) || CollUtil.isEmpty(loginUser.getRoles())) { + return; + } if (loginUser.getRoles().stream().anyMatch(r -> r.getRoleId().equals(roleId))) { try { StpUtil.logoutByTokenValue(token); @@ -511,4 +516,30 @@ public class SysRoleServiceImpl implements ISysRoleService { } }); } + + @Override + public void cleanOnlineUser(List userIds) { + List keys = StpUtil.searchTokenValue("", 0, -1, false); + if (CollUtil.isEmpty(keys)) { + return; + } + // 角色关联的在线用户量过大会导致redis阻塞卡顿 谨慎操作 + keys.parallelStream().forEach(key -> { + String token = StringUtils.substringAfterLast(key, ":"); + // 如果已经过期则跳过 + if (StpUtil.stpLogic.getTokenActiveTimeoutByToken(token) < -1) { + return; + } + LoginUser loginUser = LoginHelper.getLoginUser(token); + if (ObjectUtil.isNull(loginUser)) { + return; + } + if (userIds.contains(loginUser.getUserId())) { + try { + StpUtil.logoutByTokenValue(token); + } catch (NotLoginException ignored) { + } + } + }); + } } From 761586cc3c7ed0f581350c917483208949dc66b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Mon, 28 Oct 2024 17:44:21 +0800 Subject: [PATCH 004/175] =?UTF-8?q?reset=20=E5=9B=9E=E6=BB=9A=E9=94=99?= =?UTF-8?q?=E8=AF=AF=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/org/dromara/common/oss/core/OssClient.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 900536b56..ba924c0bb 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 @@ -83,10 +83,10 @@ public class OssClient { StaticCredentialsProvider credentialsProvider = StaticCredentialsProvider.create( AwsBasicCredentials.create(properties.getAccessKey(), properties.getSecretKey())); - //使用对象存储服务时要求明确配置访问样式(路径样式或虚拟托管样式)。需要启用路径样式访问 - boolean isStyle = true; + // MinIO 使用 HTTPS 限制使用域名访问,站点填域名。需要启用路径样式访问 + boolean isStyle = !StringUtils.containsAny(properties.getEndpoint(), OssConstant.CLOUD_SERVICE); - //创建AWS基于 CRT 的 S3 客户端 + // 创建AWS基于 CRT 的 S3 客户端 this.client = S3AsyncClient.crtBuilder() .credentialsProvider(credentialsProvider) .endpointOverride(URI.create(getEndpoint())) From 2a9f245b395a122dfb9fe4e7ff0d5352f252c25f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Mon, 28 Oct 2024 18:09:32 +0800 Subject: [PATCH 005/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E5=88=A0?= =?UTF-8?q?=E9=99=A4=E6=A1=B6=E8=87=AA=E5=8A=A8=E5=88=9B=E5=BB=BA=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E9=80=BB=E8=BE=91(=E4=BA=91=E5=8E=82=E5=95=86?= =?UTF-8?q?=E9=99=90=E5=88=B6=E4=B8=8D=E5=85=81=E8=AE=B8=E6=93=8D=E4=BD=9C?= =?UTF-8?q?=E6=A1=B6)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dromara/common/oss/core/OssClient.java | 104 +----------------- .../common/oss/enumd/AccessPolicyType.java | 11 +- 2 files changed, 8 insertions(+), 107 deletions(-) diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/core/OssClient.java b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/core/OssClient.java index ba924c0bb..f7b3e8a4d 100644 --- a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/core/OssClient.java +++ b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/core/OssClient.java @@ -9,7 +9,6 @@ import org.dromara.common.core.utils.file.FileUtils; import org.dromara.common.oss.constant.OssConstant; import org.dromara.common.oss.entity.UploadResult; import org.dromara.common.oss.enumd.AccessPolicyType; -import org.dromara.common.oss.enumd.PolicyType; import org.dromara.common.oss.exception.OssException; import org.dromara.common.oss.properties.OssProperties; import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; @@ -23,7 +22,6 @@ import software.amazon.awssdk.services.s3.S3Configuration; import software.amazon.awssdk.services.s3.crt.S3CrtHttpConfiguration; import software.amazon.awssdk.services.s3.model.GetObjectResponse; import software.amazon.awssdk.services.s3.model.NoSuchBucketException; -import software.amazon.awssdk.services.s3.model.S3Exception; import software.amazon.awssdk.services.s3.presigner.S3Presigner; import software.amazon.awssdk.transfer.s3.S3TransferManager; import software.amazon.awssdk.transfer.s3.model.*; @@ -115,8 +113,7 @@ public class OssClient { .serviceConfiguration(config) .build(); - // 创建存储桶 - createBucket(); + checkBucket(); } catch (Exception e) { if (e instanceof OssException) { throw e; @@ -126,36 +123,18 @@ public class OssClient { } /** - * 同步创建存储桶 - * 如果存储桶不存在,会进行创建;如果存储桶存在,不执行任何操作 + * 检查桶是否存在 * * @throws OssException 当创建存储桶时发生异常时抛出 */ - public void createBucket() { + public void checkBucket() { String bucketName = properties.getBucketName(); try { // 尝试获取存储桶的信息 - client.headBucket( - x -> x.bucket(bucketName) - .build()) - .join(); + client.headBucket(x -> x.bucket(bucketName).build()).join(); } catch (Exception ex) { if (ex.getCause() instanceof NoSuchBucketException) { - try { - // 存储桶不存在,尝试创建存储桶 - client.createBucket( - x -> x.bucket(bucketName)) - .join(); - - // 设置存储桶的访问策略(Bucket Policy) - client.putBucketPolicy( - x -> x.bucket(bucketName) - .policy(getPolicy(bucketName, getAccessPolicy().getPolicyType()))) - .join(); - } catch (S3Exception e) { - // 存储桶创建或策略设置失败 - throw new OssException("创建Bucket失败, 请核对配置信息:[" + e.getMessage() + "]"); - } + throw new OssException("Bucket桶是不存在的,请核对配置信息:[" + ex.getMessage() + "]"); } else { throw new OssException("判断Bucket是否存在失败,请核对配置信息:[" + ex.getMessage() + "]"); } @@ -529,77 +508,4 @@ public class OssClient { return AccessPolicyType.getByType(properties.getAccessPolicy()); } - /** - * 生成 AWS S3 存储桶访问策略 - * - * @param bucketName 存储桶 - * @param policyType 桶策略类型 - * @return 符合 AWS S3 存储桶访问策略格式的字符串 - */ - private static String getPolicy(String bucketName, PolicyType policyType) { - String policy = switch (policyType) { - case WRITE -> """ - { - "Version": "2012-10-17", - "Statement": [] - } - """; - case READ_WRITE -> """ - { - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Principal": "*", - "Action": [ - "s3:GetBucketLocation", - "s3:ListBucket", - "s3:ListBucketMultipartUploads" - ], - "Resource": "arn:aws:s3:::bucketName" - }, - { - "Effect": "Allow", - "Principal": "*", - "Action": [ - "s3:AbortMultipartUpload", - "s3:DeleteObject", - "s3:GetObject", - "s3:ListMultipartUploadParts", - "s3:PutObject" - ], - "Resource": "arn:aws:s3:::bucketName/*" - } - ] - } - """; - case READ -> """ - { - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Principal": "*", - "Action": ["s3:GetBucketLocation"], - "Resource": "arn:aws:s3:::bucketName" - }, - { - "Effect": "Deny", - "Principal": "*", - "Action": ["s3:ListBucket"], - "Resource": "arn:aws:s3:::bucketName" - }, - { - "Effect": "Allow", - "Principal": "*", - "Action": "s3:GetObject", - "Resource": "arn:aws:s3:::bucketName/*" - } - ] - } - """; - }; - return policy.replaceAll("bucketName", bucketName); - } - } diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/enumd/AccessPolicyType.java b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/enumd/AccessPolicyType.java index 6d39133d5..a257bbae0 100644 --- a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/enumd/AccessPolicyType.java +++ b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/enumd/AccessPolicyType.java @@ -17,17 +17,17 @@ public enum AccessPolicyType { /** * private */ - PRIVATE("0", BucketCannedACL.PRIVATE, ObjectCannedACL.PRIVATE, PolicyType.WRITE), + PRIVATE("0", BucketCannedACL.PRIVATE, ObjectCannedACL.PRIVATE), /** * public */ - PUBLIC("1", BucketCannedACL.PUBLIC_READ_WRITE, ObjectCannedACL.PUBLIC_READ_WRITE, PolicyType.READ_WRITE), + PUBLIC("1", BucketCannedACL.PUBLIC_READ_WRITE, ObjectCannedACL.PUBLIC_READ_WRITE), /** * custom */ - CUSTOM("2", BucketCannedACL.PUBLIC_READ, ObjectCannedACL.PUBLIC_READ, PolicyType.READ); + CUSTOM("2", BucketCannedACL.PUBLIC_READ, ObjectCannedACL.PUBLIC_READ); /** * 桶 权限类型(数据库值) @@ -44,11 +44,6 @@ public enum AccessPolicyType { */ private final ObjectCannedACL objectCannedACL; - /** - * 桶策略类型 - */ - private final PolicyType policyType; - public static AccessPolicyType getByType(String type) { for (AccessPolicyType value : values()) { if (value.getType().equals(type)) { From 5f31efd33e07fc815795e961b1fc5a8c7f347e0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Mon, 28 Oct 2024 18:10:49 +0800 Subject: [PATCH 006/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E5=88=A0?= =?UTF-8?q?=E9=99=A4=E6=A1=B6=E8=87=AA=E5=8A=A8=E5=88=9B=E5=BB=BA=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E9=80=BB=E8=BE=91(=E4=BA=91=E5=8E=82=E5=95=86?= =?UTF-8?q?=E9=99=90=E5=88=B6=E4=B8=8D=E5=85=81=E8=AE=B8=E6=93=8D=E4=BD=9C?= =?UTF-8?q?=E6=A1=B6)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dromara/common/oss/enumd/PolicyType.java | 35 ------------------- 1 file changed, 35 deletions(-) delete mode 100644 ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/enumd/PolicyType.java diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/enumd/PolicyType.java b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/enumd/PolicyType.java deleted file mode 100644 index fe96341df..000000000 --- a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/enumd/PolicyType.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.dromara.common.oss.enumd; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * minio策略配置 - * - * @author Lion Li - */ -@Getter -@AllArgsConstructor -public enum PolicyType { - - /** - * 只读 - */ - READ("read-only"), - - /** - * 只写 - */ - WRITE("write-only"), - - /** - * 读写 - */ - READ_WRITE("read-write"); - - /** - * 类型 - */ - private final String type; - -} From df9a57c379f383129e8fc33c7d886f8c8fdd9b35 Mon Sep 17 00:00:00 2001 From: Lucien_Lu Date: Tue, 29 Oct 2024 01:29:15 +0000 Subject: [PATCH 007/175] =?UTF-8?q?!592=20=E6=9B=BF=E6=8D=A2RedisUtils?= =?UTF-8?q?=E4=B8=AD=E7=9A=84=E8=BF=87=E6=97=B6=E6=96=B9=E6=B3=95=20*=20up?= =?UTF-8?q?date:=E6=9B=BF=E6=8D=A2RedisUtils=E4=B8=AD=E7=9A=84=E5=BA=9F?= =?UTF-8?q?=E5=BC=83=E6=96=B9=E6=B3=95getKeysStreamByPattern=E5=8F=8AtrySe?= =?UTF-8?q?tRate?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/redis/utils/RedisUtils.java | 30 ++++++++++++++++--- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/RedisUtils.java b/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/RedisUtils.java index 6fa3b7485..a0efde600 100644 --- a/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/RedisUtils.java +++ b/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/RedisUtils.java @@ -4,6 +4,7 @@ import lombok.AccessLevel; import lombok.NoArgsConstructor; import org.dromara.common.core.utils.SpringUtils; import org.redisson.api.*; +import org.redisson.api.options.KeysScanOptions; import java.time.Duration; import java.util.Collection; @@ -37,7 +38,7 @@ public class RedisUtils { */ public static long rateLimiter(String key, RateType rateType, int rate, int rateInterval) { RRateLimiter rateLimiter = CLIENT.getRateLimiter(key); - rateLimiter.trySetRate(rateType, rate, rateInterval, RateIntervalUnit.SECONDS); + rateLimiter.trySetRate(rateType, rate, Duration.ofSeconds(rateInterval)); if (rateLimiter.tryAcquire()) { return rateLimiter.availablePermits(); } else { @@ -518,13 +519,34 @@ public class RedisUtils { /** * 获得缓存的基本对象列表(全局匹配忽略租户 自行拼接租户id) - * + *

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

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

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

+ * @see KeysScanOptions + */ + public static Collection keys(final KeysScanOptions keysScanOptions) { + Stream keysStream = CLIENT.getKeys().getKeysStream(keysScanOptions); + return keysStream.collect(Collectors.toList()); } /** From a21fa666fda1c9f2333ebbe7c5e32b093a3037cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Tue, 29 Oct 2024 09:39:45 +0800 Subject: [PATCH 008/175] update springboot 3.2.11 => 3.3.5 update springboot-admin 3.2.3 => 3.3.4 --- README.md | 2 +- pom.xml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 3ef0ea03a..f0fdd4a99 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ [![使用IntelliJ IDEA开发维护](https://img.shields.io/badge/IntelliJ%20IDEA-提供支持-blue.svg)](https://www.jetbrains.com/?from=RuoYi-Vue-Plus)
[![RuoYi-Vue-Plus](https://img.shields.io/badge/RuoYi_Vue_Plus-5.2.3-success.svg)](https://gitee.com/dromara/RuoYi-Vue-Plus) -[![Spring Boot](https://img.shields.io/badge/Spring%20Boot-3.2-blue.svg)]() +[![Spring Boot](https://img.shields.io/badge/Spring%20Boot-3.3-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 7b92aa7e7..95a14c4cc 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ 5.2.3 - 3.2.11 + 3.3.5 UTF-8 UTF-8 17 @@ -27,7 +27,7 @@ 3.5.8 3.9.1 5.8.31 - 3.2.3 + 3.3.4 3.37.0 2.2.7 4.3.1 From 1757e5519daacdc2ced207b5de617956c267dd91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Tue, 29 Oct 2024 11:19:08 +0800 Subject: [PATCH 009/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E5=8E=BB?= =?UTF-8?q?=E9=99=A4GenUtils=E8=AE=BE=E7=BD=AEcreateby=E9=80=BB=E8=BE=91?= =?UTF-8?q?=20=E7=BB=9F=E4=B8=80=E8=B5=B0=E8=87=AA=E5=8A=A8=E6=B3=A8?= =?UTF-8?q?=E5=85=A5=E8=AE=BE=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/dromara/generator/service/GenTableServiceImpl.java | 4 +--- .../src/main/java/org/dromara/generator/util/GenUtils.java | 3 +-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java b/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java index bb8b444fc..38caa5c6e 100644 --- a/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java +++ b/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java @@ -29,7 +29,6 @@ import org.dromara.common.core.utils.file.FileUtils; import org.dromara.common.json.utils.JsonUtils; import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.TableDataInfo; -import org.dromara.common.satoken.utils.LoginHelper; import org.dromara.generator.constant.GenConstants; import org.dromara.generator.domain.GenTable; import org.dromara.generator.domain.GenTableColumn; @@ -269,11 +268,10 @@ public class GenTableServiceImpl implements IGenTableService { @DSTransactional @Override public void importGenTable(List tableList, String dataName) { - Long operId = LoginHelper.getUserId(); try { for (GenTable table : tableList) { String tableName = table.getTableName(); - GenUtils.initTable(table, operId); + GenUtils.initTable(table); table.setDataName(dataName); int row = baseMapper.insert(table); if (row > 0) { diff --git a/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/util/GenUtils.java b/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/util/GenUtils.java index 2e6b37b6d..c9357c0c4 100644 --- a/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/util/GenUtils.java +++ b/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/util/GenUtils.java @@ -22,14 +22,13 @@ public class GenUtils { /** * 初始化表信息 */ - public static void initTable(GenTable genTable, Long operId) { + public static void initTable(GenTable genTable) { genTable.setClassName(convertClassName(genTable.getTableName())); genTable.setPackageName(GenConfig.getPackageName()); genTable.setModuleName(getModuleName(GenConfig.getPackageName())); genTable.setBusinessName(getBusinessName(genTable.getTableName())); genTable.setFunctionName(replaceText(genTable.getTableComment())); genTable.setFunctionAuthor(GenConfig.getAuthor()); - genTable.setCreateBy(operId); } /** From 9b6b288e735ee19761cdb05c863579714f5b86b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Tue, 29 Oct 2024 16:42:04 +0800 Subject: [PATCH 010/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E5=A4=9A?= =?UTF-8?q?=E7=A7=9F=E6=88=B7=E6=8F=92=E4=BB=B6=E5=88=9D=E5=A7=8B=E5=8C=96?= =?UTF-8?q?=E6=B5=81=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mybatis/config/MybatisPlusConfig.java | 1 + .../common/tenant/config/TenantConfig.java | 22 +++++++------------ 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/config/MybatisPlusConfig.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/config/MybatisPlusConfig.java index f7d14ee97..805c3d0d6 100644 --- a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/config/MybatisPlusConfig.java +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/config/MybatisPlusConfig.java @@ -38,6 +38,7 @@ public class MybatisPlusConfig { TenantLineInnerInterceptor tenant = SpringUtils.getBean(TenantLineInnerInterceptor.class); interceptor.addInnerInterceptor(tenant); } catch (BeansException ignore) { + ignore.printStackTrace(); } // 数据权限处理 interceptor.addInnerInterceptor(dataPermissionInterceptor()); diff --git a/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/config/TenantConfig.java b/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/config/TenantConfig.java index 07302bc81..010e1e411 100644 --- a/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/config/TenantConfig.java +++ b/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/config/TenantConfig.java @@ -4,7 +4,6 @@ import cn.dev33.satoken.dao.SaTokenDao; import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor; import org.dromara.common.core.utils.reflect.ReflectUtils; -import org.dromara.common.mybatis.config.MybatisPlusConfig; import org.dromara.common.redis.config.RedisConfig; import org.dromara.common.redis.config.properties.RedissonProperties; import org.dromara.common.tenant.core.TenantSaTokenDao; @@ -16,7 +15,7 @@ import org.redisson.config.ClusterServersConfig; import org.redisson.config.SingleServerConfig; import org.redisson.spring.starter.RedissonAutoConfigurationCustomizer; import org.springframework.boot.autoconfigure.AutoConfiguration; -import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.cache.CacheManager; @@ -33,18 +32,13 @@ import org.springframework.context.annotation.Primary; @ConditionalOnProperty(value = "tenant.enable", havingValue = "true") public class TenantConfig { - @ConditionalOnBean(MybatisPlusConfig.class) - @AutoConfiguration(after = {MybatisPlusConfig.class}) - static class MybatisPlusConfiguration { - - /** - * 多租户插件 - */ - @Bean - public TenantLineInnerInterceptor tenantLineInnerInterceptor(TenantProperties tenantProperties) { - return new TenantLineInnerInterceptor(new PlusTenantLineHandler(tenantProperties)); - } - + /** + * 多租户插件 + */ + @ConditionalOnClass(TenantLineInnerInterceptor.class) + @Bean + public TenantLineInnerInterceptor tenantLineInnerInterceptor(TenantProperties tenantProperties) { + return new TenantLineInnerInterceptor(new PlusTenantLineHandler(tenantProperties)); } @Bean From 8cd30ae86b0aab3fc3a3a8ab19dfd3c22aba5a7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Tue, 29 Oct 2024 16:42:53 +0800 Subject: [PATCH 011/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E5=A4=9A?= =?UTF-8?q?=E7=A7=9F=E6=88=B7=E6=8F=92=E4=BB=B6=E5=88=9D=E5=A7=8B=E5=8C=96?= =?UTF-8?q?=E6=B5=81=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/dromara/common/mybatis/config/MybatisPlusConfig.java | 1 - 1 file changed, 1 deletion(-) diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/config/MybatisPlusConfig.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/config/MybatisPlusConfig.java index 805c3d0d6..f7d14ee97 100644 --- a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/config/MybatisPlusConfig.java +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/config/MybatisPlusConfig.java @@ -38,7 +38,6 @@ public class MybatisPlusConfig { TenantLineInnerInterceptor tenant = SpringUtils.getBean(TenantLineInnerInterceptor.class); interceptor.addInnerInterceptor(tenant); } catch (BeansException ignore) { - ignore.printStackTrace(); } // 数据权限处理 interceptor.addInnerInterceptor(dataPermissionInterceptor()); From 112157ade0e33e6406ede5a0d1c38fa165f5989e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Tue, 29 Oct 2024 16:55:41 +0800 Subject: [PATCH 012/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E5=A4=9A?= =?UTF-8?q?=E7=A7=9F=E6=88=B7=E6=8F=92=E4=BB=B6=E5=88=9D=E5=A7=8B=E5=8C=96?= =?UTF-8?q?=E6=B5=81=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/tenant/config/TenantConfig.java | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/config/TenantConfig.java b/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/config/TenantConfig.java index 010e1e411..2513aac92 100644 --- a/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/config/TenantConfig.java +++ b/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/config/TenantConfig.java @@ -32,13 +32,18 @@ import org.springframework.context.annotation.Primary; @ConditionalOnProperty(value = "tenant.enable", havingValue = "true") public class TenantConfig { - /** - * 多租户插件 - */ @ConditionalOnClass(TenantLineInnerInterceptor.class) - @Bean - public TenantLineInnerInterceptor tenantLineInnerInterceptor(TenantProperties tenantProperties) { - return new TenantLineInnerInterceptor(new PlusTenantLineHandler(tenantProperties)); + @AutoConfiguration + static class MybatisPlusConfiguration { + + /** + * 多租户插件 + */ + @Bean + public TenantLineInnerInterceptor tenantLineInnerInterceptor(TenantProperties tenantProperties) { + return new TenantLineInnerInterceptor(new PlusTenantLineHandler(tenantProperties)); + } + } @Bean From 3b5858b1148ee8c5b158daeb9d2e97423120aeeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Tue, 29 Oct 2024 19:12:07 +0800 Subject: [PATCH 013/175] update mybatis-plus 3.5.8 => 3.5.9 --- pom.xml | 8 +++++++- ruoyi-common/ruoyi-common-mybatis/pom.xml | 5 +++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 95a14c4cc..9c9abd0ed 100644 --- a/pom.xml +++ b/pom.xml @@ -24,7 +24,7 @@ 4.0.3 2.3 1.39.0 - 3.5.8 + 3.5.9 3.9.1 5.8.31 3.3.4 @@ -216,6 +216,12 @@ ${mybatis-plus.version} + + com.baomidou + mybatis-plus-jsqlparser + ${mybatis-plus.version} + + com.baomidou mybatis-plus-annotation diff --git a/ruoyi-common/ruoyi-common-mybatis/pom.xml b/ruoyi-common/ruoyi-common-mybatis/pom.xml index a58064a8a..d79ba284a 100644 --- a/ruoyi-common/ruoyi-common-mybatis/pom.xml +++ b/ruoyi-common/ruoyi-common-mybatis/pom.xml @@ -37,6 +37,11 @@ mybatis-plus-spring-boot3-starter + + com.baomidou + mybatis-plus-jsqlparser + + p6spy From 2d190cfb192d73480206452f40e5c9ccb8fd5951 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Tue, 29 Oct 2024 19:12:19 +0800 Subject: [PATCH 014/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20jackson?= =?UTF-8?q?=20=E8=BF=87=E6=9C=9F=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/translation/core/handler/TranslationHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruoyi-common/ruoyi-common-translation/src/main/java/org/dromara/common/translation/core/handler/TranslationHandler.java b/ruoyi-common/ruoyi-common-translation/src/main/java/org/dromara/common/translation/core/handler/TranslationHandler.java index bb9615bfd..a90f1e1ec 100644 --- a/ruoyi-common/ruoyi-common-translation/src/main/java/org/dromara/common/translation/core/handler/TranslationHandler.java +++ b/ruoyi-common/ruoyi-common-translation/src/main/java/org/dromara/common/translation/core/handler/TranslationHandler.java @@ -39,7 +39,7 @@ public class TranslationHandler extends JsonSerializer implements Contex if (ObjectUtil.isNotNull(trans)) { // 如果映射字段不为空 则取映射字段的值 if (StringUtils.isNotBlank(translation.mapper())) { - value = ReflectUtils.invokeGetter(gen.getCurrentValue(), translation.mapper()); + value = ReflectUtils.invokeGetter(gen.currentValue(), translation.mapper()); } // 如果为 null 直接写出 if (ObjectUtil.isNull(value)) { From b0548f9a567276ffdf14ab6e8d4db286ec447aad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Tue, 29 Oct 2024 20:21:58 +0800 Subject: [PATCH 015/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20sys=5Fsoc?= =?UTF-8?q?ial=E8=A1=A8=20=E7=A7=9F=E6=88=B7id=E5=A2=9E=E5=8A=A0=E9=BB=98?= =?UTF-8?q?=E8=AE=A4=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- script/sql/oracle/oracle_ry_vue_5.X.sql | 2 +- script/sql/postgres/postgres_ry_vue_5.X.sql | 2 +- script/sql/ry_vue_5.X.sql | 2 +- script/sql/sqlserver/sqlserver_ry_vue_5.X.sql | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/script/sql/oracle/oracle_ry_vue_5.X.sql b/script/sql/oracle/oracle_ry_vue_5.X.sql index 0aed89d74..02311997e 100644 --- a/script/sql/oracle/oracle_ry_vue_5.X.sql +++ b/script/sql/oracle/oracle_ry_vue_5.X.sql @@ -5,7 +5,7 @@ create table sys_social ( id number(20) not null, user_id number(20) not null, - tenant_id varchar2(20) default null, + tenant_id varchar2(20) default '000000', auth_id varchar2(255) not null, source varchar2(255) not null, open_id varchar2(255) default null, diff --git a/script/sql/postgres/postgres_ry_vue_5.X.sql b/script/sql/postgres/postgres_ry_vue_5.X.sql index fabea6048..74063e6c1 100644 --- a/script/sql/postgres/postgres_ry_vue_5.X.sql +++ b/script/sql/postgres/postgres_ry_vue_5.X.sql @@ -5,7 +5,7 @@ create table sys_social ( id int8 not null, user_id int8 not null, - tenant_id varchar(20) default null::varchar, + tenant_id varchar(20) default '000000'::varchar, auth_id varchar(255) not null, source varchar(255) not null, open_id varchar(255) default null::varchar, diff --git a/script/sql/ry_vue_5.X.sql b/script/sql/ry_vue_5.X.sql index 3e3562d27..9e6a1d999 100644 --- a/script/sql/ry_vue_5.X.sql +++ b/script/sql/ry_vue_5.X.sql @@ -5,7 +5,7 @@ create table sys_social ( id bigint not null comment '主键', user_id bigint not null comment '用户ID', - tenant_id varchar(20) default null comment '租户id', + tenant_id varchar(20) default '000000' comment '租户id', auth_id varchar(255) not null comment '平台+平台唯一id', source varchar(255) not null comment '用户来源', open_id varchar(255) default null comment '平台编号唯一id', diff --git a/script/sql/sqlserver/sqlserver_ry_vue_5.X.sql b/script/sql/sqlserver/sqlserver_ry_vue_5.X.sql index ad9a0b5f1..b1f084440 100644 --- a/script/sql/sqlserver/sqlserver_ry_vue_5.X.sql +++ b/script/sql/sqlserver/sqlserver_ry_vue_5.X.sql @@ -2,7 +2,7 @@ create table sys_social ( id bigint NOT NULL, user_id bigint NOT NULL, - tenant_id nvarchar(20) NULL, + tenant_id nvarchar(20) DEFAULT ('000000') NULL, auth_id nvarchar(255) NOT NULL, source nvarchar(255) NOT NULL, open_id nvarchar(255) NULL, From 0baf2c5861a039403385a7e41da79c43a136cdd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Wed, 30 Oct 2024 10:51:45 +0800 Subject: [PATCH 016/175] =?UTF-8?q?fix=20=E4=BF=AE=E5=A4=8D=20=E6=96=B0?= =?UTF-8?q?=E7=89=88=E6=9C=ACmp=E9=BB=98=E8=AE=A4=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=E6=9C=80=E6=96=B0=20sqlserver=20=E8=AF=AD=E6=B3=95=E5=AF=BC?= =?UTF-8?q?=E8=87=B4=E4=BB=A3=E7=A0=81=E7=94=9F=E6=88=90=E5=88=86=E9=A1=B5?= =?UTF-8?q?=E6=8A=A5=E9=94=99=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/dromara/generator/service/GenTableServiceImpl.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java b/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java index 38caa5c6e..3f9ef1920 100644 --- a/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java +++ b/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java @@ -105,7 +105,8 @@ public class GenTableServiceImpl implements IGenTableService { .like(StringUtils.isNotBlank(genTable.getTableName()), "lower(table_name)", StringUtils.lowerCase(genTable.getTableName())) .like(StringUtils.isNotBlank(genTable.getTableComment()), "lower(table_comment)", StringUtils.lowerCase(genTable.getTableComment())) .between(params.get("beginTime") != null && params.get("endTime") != null, - "create_time", params.get("beginTime"), params.get("endTime")); + "create_time", params.get("beginTime"), params.get("endTime")) + .orderByAsc("table_id"); return wrapper; } From 8cd7e3c924b9cef4eef3b0cf35539b53c5ba82f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Wed, 30 Oct 2024 16:43:30 +0800 Subject: [PATCH 017/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E9=99=90?= =?UTF-8?q?=E6=B5=81=E6=B3=A8=E8=A7=A3=E5=A2=9E=E5=8A=A0=E5=9B=BA=E5=AE=9A?= =?UTF-8?q?=E6=B8=85=E7=90=86=E6=97=B6=E9=97=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ratelimiter/annotation/RateLimiter.java | 6 ++++++ .../ratelimiter/aspectj/RateLimiterAspect.java | 3 ++- .../dromara/common/redis/utils/RedisUtils.java | 16 +++++++++++++++- 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/ruoyi-common/ruoyi-common-ratelimiter/src/main/java/org/dromara/common/ratelimiter/annotation/RateLimiter.java b/ruoyi-common/ruoyi-common-ratelimiter/src/main/java/org/dromara/common/ratelimiter/annotation/RateLimiter.java index de09752a7..79272d41e 100644 --- a/ruoyi-common/ruoyi-common-ratelimiter/src/main/java/org/dromara/common/ratelimiter/annotation/RateLimiter.java +++ b/ruoyi-common/ruoyi-common-ratelimiter/src/main/java/org/dromara/common/ratelimiter/annotation/RateLimiter.java @@ -38,4 +38,10 @@ public @interface RateLimiter { * 提示消息 支持国际化 格式为 {code} */ String message() default "{rate.limiter.message}"; + + /** + * 限流策略超时时间 默认一天(策略存活时间 会清除已存在的策略数据) + */ + int timeout() default 86400; + } diff --git a/ruoyi-common/ruoyi-common-ratelimiter/src/main/java/org/dromara/common/ratelimiter/aspectj/RateLimiterAspect.java b/ruoyi-common/ruoyi-common-ratelimiter/src/main/java/org/dromara/common/ratelimiter/aspectj/RateLimiterAspect.java index 1f4904a3e..2d6d82ea3 100644 --- a/ruoyi-common/ruoyi-common-ratelimiter/src/main/java/org/dromara/common/ratelimiter/aspectj/RateLimiterAspect.java +++ b/ruoyi-common/ruoyi-common-ratelimiter/src/main/java/org/dromara/common/ratelimiter/aspectj/RateLimiterAspect.java @@ -54,13 +54,14 @@ public class RateLimiterAspect { public void doBefore(JoinPoint point, RateLimiter rateLimiter) { int time = rateLimiter.time(); int count = rateLimiter.count(); + int timeout = rateLimiter.timeout(); try { String combineKey = getCombineKey(rateLimiter, point); RateType rateType = RateType.OVERALL; if (rateLimiter.limitType() == LimitType.CLUSTER) { rateType = RateType.PER_CLIENT; } - long number = RedisUtils.rateLimiter(combineKey, rateType, count, time); + long number = RedisUtils.rateLimiter(combineKey, rateType, count, time, timeout); if (number == -1) { String message = rateLimiter.message(); if (StringUtils.startsWith(message, "{") && StringUtils.endsWith(message, "}")) { diff --git a/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/RedisUtils.java b/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/RedisUtils.java index a0efde600..355cd2931 100644 --- a/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/RedisUtils.java +++ b/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/RedisUtils.java @@ -37,8 +37,22 @@ public class RedisUtils { * @return -1 表示失败 */ public static long rateLimiter(String key, RateType rateType, int rate, int rateInterval) { + return rateLimiter(key, rateType, rate, rateInterval, 0); + } + + /** + * 限流 + * + * @param key 限流key + * @param rateType 限流类型 + * @param rate 速率 + * @param rateInterval 速率间隔 + * @param timeout 超时时间 + * @return -1 表示失败 + */ + public static long rateLimiter(String key, RateType rateType, int rate, int rateInterval, int timeout) { RRateLimiter rateLimiter = CLIENT.getRateLimiter(key); - rateLimiter.trySetRate(rateType, rate, Duration.ofSeconds(rateInterval)); + rateLimiter.trySetRate(rateType, rate, Duration.ofSeconds(rateInterval), Duration.ofSeconds(timeout)); if (rateLimiter.tryAcquire()) { return rateLimiter.availablePermits(); } else { From d89727725b31991e7c35d999609b0bc4cdf17189 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Thu, 31 Oct 2024 15:55:28 +0800 Subject: [PATCH 018/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E5=88=A0?= =?UTF-8?q?=E9=99=A4=E6=97=A0=E7=94=A8=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ruoyi-admin/src/main/resources/application.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml index 82d0f1e50..f05bdaf85 100644 --- a/ruoyi-admin/src/main/resources/application.yml +++ b/ruoyi-admin/src/main/resources/application.yml @@ -110,15 +110,12 @@ sa-token: security: # 排除路径 excludes: - # 静态资源 - /*.html - /**/*.html - /**/*.css - /**/*.js - # 公共路径 - /favicon.ico - /error - # swagger 文档配置 - /*/api-docs - /*/api-docs/** From 5e7fb887620b4cfeb17cb74868efd68c68559bbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Thu, 31 Oct 2024 17:59:56 +0800 Subject: [PATCH 019/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E5=8E=BB?= =?UTF-8?q?=E9=99=A4OSS=E6=A1=B6=E6=A3=80=E6=B5=8B=20=E6=A1=B6=E4=B8=8D?= =?UTF-8?q?=E5=AD=98=E5=9C=A8=E8=87=AA=E7=84=B6=E4=BC=9A=E6=8A=A5=E9=94=99?= =?UTF-8?q?=E6=97=A0=E9=9C=80=E9=A2=9D=E5=A4=96=E6=A3=80=E6=B5=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dromara/common/oss/core/OssClient.java | 21 ------------------- 1 file changed, 21 deletions(-) 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 f7b3e8a4d..1261b4777 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 @@ -21,7 +21,6 @@ import software.amazon.awssdk.services.s3.S3AsyncClient; import software.amazon.awssdk.services.s3.S3Configuration; import software.amazon.awssdk.services.s3.crt.S3CrtHttpConfiguration; import software.amazon.awssdk.services.s3.model.GetObjectResponse; -import software.amazon.awssdk.services.s3.model.NoSuchBucketException; import software.amazon.awssdk.services.s3.presigner.S3Presigner; import software.amazon.awssdk.transfer.s3.S3TransferManager; import software.amazon.awssdk.transfer.s3.model.*; @@ -113,7 +112,6 @@ public class OssClient { .serviceConfiguration(config) .build(); - checkBucket(); } catch (Exception e) { if (e instanceof OssException) { throw e; @@ -122,25 +120,6 @@ public class OssClient { } } - /** - * 检查桶是否存在 - * - * @throws OssException 当创建存储桶时发生异常时抛出 - */ - public void checkBucket() { - String bucketName = properties.getBucketName(); - try { - // 尝试获取存储桶的信息 - client.headBucket(x -> x.bucket(bucketName).build()).join(); - } catch (Exception ex) { - if (ex.getCause() instanceof NoSuchBucketException) { - throw new OssException("Bucket桶是不存在的,请核对配置信息:[" + ex.getMessage() + "]"); - } else { - throw new OssException("判断Bucket是否存在失败,请核对配置信息:[" + ex.getMessage() + "]"); - } - } - } - /** * 上传文件到 Amazon S3,并返回上传结果 * From 53635da55219281174d2ec871cd69f5b9fb88e87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Sat, 2 Nov 2024 20:02:08 +0800 Subject: [PATCH 020/175] =?UTF-8?q?fix=20=E4=BF=AE=E5=A4=8D=20=E6=9F=90?= =?UTF-8?q?=E4=BA=9B=E6=A8=A1=E5=9D=97=E4=B8=8D=E5=AD=98=E5=9C=A8=20mp=20?= =?UTF-8?q?=E4=BE=9D=E8=B5=96=E5=AF=BC=E8=87=B4=E6=96=B9=E6=B3=95=E6=8A=A5?= =?UTF-8?q?=E9=94=99=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tenant/handle/TenantKeyPrefixHandler.java | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/handle/TenantKeyPrefixHandler.java b/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/handle/TenantKeyPrefixHandler.java index 65f523395..fbf210df1 100644 --- a/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/handle/TenantKeyPrefixHandler.java +++ b/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/handle/TenantKeyPrefixHandler.java @@ -27,8 +27,12 @@ public class TenantKeyPrefixHandler extends KeyPrefixHandler { if (StringUtils.isBlank(name)) { return null; } - if (InterceptorIgnoreHelper.willIgnoreTenantLine("")) { - return super.map(name); + try { + if (InterceptorIgnoreHelper.willIgnoreTenantLine("")) { + return super.map(name); + } + } catch (NoClassDefFoundError ignore) { + // 有些服务不需要mp导致类不存在 忽略即可 } if (StringUtils.contains(name, GlobalConstants.GLOBAL_REDIS_KEY)) { return super.map(name); @@ -54,8 +58,12 @@ public class TenantKeyPrefixHandler extends KeyPrefixHandler { if (StringUtils.isBlank(unmap)) { return null; } - if (InterceptorIgnoreHelper.willIgnoreTenantLine("")) { - return super.unmap(name); + try { + if (InterceptorIgnoreHelper.willIgnoreTenantLine("")) { + return super.unmap(name); + } + } catch (NoClassDefFoundError ignore) { + // 有些服务不需要mp导致类不存在 忽略即可 } if (StringUtils.contains(name, GlobalConstants.GLOBAL_REDIS_KEY)) { return super.unmap(name); From 2ffdd56301ef38187983f7ab6c0008a1548e15de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Mon, 4 Nov 2024 11:38:45 +0800 Subject: [PATCH 021/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E9=83=A8?= =?UTF-8?q?=E9=97=A8=E6=A0=91=E5=A4=9A=E5=9F=BA=E7=82=B9=E5=B1=95=E7=A4=BA?= =?UTF-8?q?=E9=97=AE=E9=A2=98=20=E6=94=AF=E6=8C=81=E7=9B=B8=E5=90=8C?= =?UTF-8?q?=E5=90=8D=E7=A7=B0=E8=8A=82=E7=82=B9=E5=B9=B6=E6=8E=92=E5=B1=95?= =?UTF-8?q?=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/core/utils/TreeBuildUtils.java | 17 +++++++++++++++ .../service/impl/SysDeptServiceImpl.java | 21 ++++++++++++++----- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/TreeBuildUtils.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/TreeBuildUtils.java index 8e501dfea..2ab42cbc1 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/TreeBuildUtils.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/TreeBuildUtils.java @@ -43,6 +43,23 @@ public class TreeBuildUtils extends TreeUtil { return TreeUtil.build(list, k, DEFAULT_CONFIG, nodeParser); } + /** + * 构建树形结构 + * + * @param 输入节点的类型 + * @param 节点ID的类型 + * @param parentId 顶级节点 + * @param list 节点列表,其中包含了要构建树形结构的所有节点 + * @param nodeParser 解析器,用于将输入节点转换为树节点 + * @return 构建好的树形结构列表 + */ + public static List> build(List list, K parentId, NodeParser nodeParser) { + if (CollUtil.isEmpty(list)) { + return CollUtil.newArrayList(); + } + return TreeUtil.build(list, parentId, DEFAULT_CONFIG, nodeParser); + } + /** * 获取节点列表中所有节点的叶子节点 * diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDeptServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDeptServiceImpl.java index 49b18b7ab..dcdd7fcd3 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 @@ -102,11 +102,22 @@ public class SysDeptServiceImpl implements ISysDeptService, DeptService { if (CollUtil.isEmpty(depts)) { return CollUtil.newArrayList(); } - return TreeBuildUtils.build(depts, (dept, tree) -> - tree.setId(dept.getDeptId()) - .setParentId(dept.getParentId()) - .setName(dept.getDeptName()) - .setWeight(dept.getOrderNum())); + // 获取当前列表中每一个节点的parentId,然后在列表中查找是否有id与其parentId对应,若无对应,则表明此时节点列表中,该节点在当前列表中属于顶级节点 + List> treeList = CollUtil.newArrayList(); + for (SysDeptVo d : depts) { + Long parentId = d.getParentId(); + SysDeptVo sysDeptVo = depts.stream().filter(it -> it.getDeptId().longValue() == parentId).findFirst().orElse(null); + if (sysDeptVo == null) { + List> trees = TreeBuildUtils.build(depts, parentId, (dept, tree) -> + tree.setId(dept.getDeptId()) + .setParentId(dept.getParentId()) + .setName(dept.getDeptName()) + .setWeight(dept.getOrderNum())); + Tree tree = trees.stream().filter(it -> it.getId().longValue() == d.getDeptId()).findFirst().get(); + treeList.add(tree); + } + } + return treeList; } /** From 80e6943d2e79c73eca67645ac80b1a04b79be379 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Mon, 4 Nov 2024 14:08:46 +0800 Subject: [PATCH 022/175] =?UTF-8?q?add=20=E5=A2=9E=E5=8A=A0=20gitcode=20?= =?UTF-8?q?=E9=93=BE=E6=8E=A5=E5=9C=B0=E5=9D=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index f0fdd4a99..40636ab94 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,7 @@ [![码云Gitee](https://gitee.com/dromara/RuoYi-Vue-Plus/badge/star.svg?theme=blue)](https://gitee.com/dromara/RuoYi-Vue-Plus) [![GitHub](https://img.shields.io/github/stars/dromara/RuoYi-Vue-Plus.svg?style=social&label=Stars)](https://github.com/dromara/RuoYi-Vue-Plus) +[![Star](https://gitcode.com/dromara/RuoYi-Vue-Plus/star/badge.svg)](https://gitcode.com/dromara/RuoYi-Vue-Plus) [![License](https://img.shields.io/badge/License-MIT-blue.svg)](https://gitee.com/dromara/RuoYi-Vue-Plus/blob/master/LICENSE) [![使用IntelliJ IDEA开发维护](https://img.shields.io/badge/IntelliJ%20IDEA-提供支持-blue.svg)](https://www.jetbrains.com/?from=RuoYi-Vue-Plus)
From baef55ae1b297e257777e510760acfd0028054ba Mon Sep 17 00:00:00 2001 From: cxh Date: Mon, 4 Nov 2024 17:42:37 +0800 Subject: [PATCH 023/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 删除内部if对部门不为null的多余判断,可以提前判断 2. 使用内部工具类StreamUtils --- .../system/service/impl/SysDeptServiceImpl.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) 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 dcdd7fcd3..c17391674 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 @@ -15,6 +15,7 @@ import org.dromara.common.core.service.DeptService; import org.dromara.common.core.utils.MapstructUtils; import org.dromara.common.core.utils.SpringUtils; import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.core.utils.StreamUtils; import org.dromara.common.core.utils.TreeBuildUtils; import org.dromara.common.mybatis.helper.DataBaseHelper; import org.dromara.common.redis.utils.CacheUtils; @@ -106,8 +107,8 @@ public class SysDeptServiceImpl implements ISysDeptService, DeptService { List> treeList = CollUtil.newArrayList(); for (SysDeptVo d : depts) { Long parentId = d.getParentId(); - SysDeptVo sysDeptVo = depts.stream().filter(it -> it.getDeptId().longValue() == parentId).findFirst().orElse(null); - if (sysDeptVo == null) { + SysDeptVo sysDeptVo = StreamUtils.findFirst(depts, it -> it.getDeptId().longValue() == parentId); + if (ObjectUtil.isNull(sysDeptVo)) { List> trees = TreeBuildUtils.build(depts, parentId, (dept, tree) -> tree.setId(dept.getDeptId()) .setParentId(dept.getParentId()) @@ -276,11 +277,14 @@ public class SysDeptServiceImpl implements ISysDeptService, DeptService { public int updateDept(SysDeptBo bo) { SysDept dept = MapstructUtils.convert(bo, SysDept.class); SysDept oldDept = baseMapper.selectById(dept.getDeptId()); + if (ObjectUtil.isNull(oldDept)) { + throw new ServiceException("部门不存在,无法修改"); + } if (!oldDept.getParentId().equals(dept.getParentId())) { // 如果是新父部门 则校验是否具有新父部门权限 避免越权 this.checkDeptDataScope(dept.getParentId()); SysDept newParentDept = baseMapper.selectById(dept.getParentId()); - if (ObjectUtil.isNotNull(newParentDept) && ObjectUtil.isNotNull(oldDept)) { + if (ObjectUtil.isNotNull(newParentDept)) { String newAncestors = newParentDept.getAncestors() + StringUtils.SEPARATOR + newParentDept.getDeptId(); String oldAncestors = oldDept.getAncestors(); dept.setAncestors(newAncestors); From 7d856b030b0c784adb4d9c59d22543e6c5d56dc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Tue, 5 Nov 2024 16:52:01 +0800 Subject: [PATCH 024/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E4=B8=8D?= =?UTF-8?q?=E4=BC=A0=E7=94=A8=E6=88=B7id=E4=B8=8D=E6=A0=A1=E9=AA=8C?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E6=9D=83=E9=99=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../system/controller/system/SysUserController.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysUserController.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysUserController.java index 36104d627..025800de9 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysUserController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysUserController.java @@ -128,13 +128,9 @@ public class SysUserController extends BaseController { @SaCheckPermission("system:user:query") @GetMapping(value = {"/", "/{userId}"}) public R getInfo(@PathVariable(value = "userId", required = false) Long userId) { - userService.checkUserDataScope(userId); SysUserInfoVo userInfoVo = new SysUserInfoVo(); - SysRoleBo roleBo = new SysRoleBo(); - roleBo.setStatus(UserConstants.ROLE_NORMAL); - List roles = roleService.selectRoleList(roleBo); - userInfoVo.setRoles(LoginHelper.isSuperAdmin(userId) ? roles : StreamUtils.filter(roles, r -> !r.isSuperAdmin())); if (ObjectUtil.isNotNull(userId)) { + userService.checkUserDataScope(userId); SysUserVo sysUser = userService.selectUserById(userId); userInfoVo.setUser(sysUser); userInfoVo.setRoleIds(roleService.selectRoleListByUserId(userId)); @@ -146,6 +142,10 @@ public class SysUserController extends BaseController { userInfoVo.setPostIds(postService.selectPostListByUserId(userId)); } } + SysRoleBo roleBo = new SysRoleBo(); + roleBo.setStatus(UserConstants.ROLE_NORMAL); + List roles = roleService.selectRoleList(roleBo); + userInfoVo.setRoles(LoginHelper.isSuperAdmin(userId) ? roles : StreamUtils.filter(roles, r -> !r.isSuperAdmin())); return R.ok(userInfoVo); } From 0385a444c27f907ef2082205cc75a4ae43ad0abf Mon Sep 17 00:00:00 2001 From: "Emil.Zhang" <356141959@qq.com> Date: Wed, 6 Nov 2024 15:01:38 +0800 Subject: [PATCH 025/175] =?UTF-8?q?fixed(=E7=BA=A7=E8=81=94=E4=B8=8B?= =?UTF-8?q?=E6=8B=89=E6=A1=86=E6=95=B0=E6=8D=AE=E9=94=99=E8=AF=AF)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1.修复过多级联下拉选项导致的无法写入问题 --- .../common/excel/core/ExcelDownHandler.java | 108 +++++++++++------- .../service/impl/ExportExcelServiceImpl.java | 48 +++++--- 2 files changed, 98 insertions(+), 58 deletions(-) diff --git a/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/core/ExcelDownHandler.java b/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/core/ExcelDownHandler.java index b3f68ed1e..32fee7a6c 100644 --- a/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/core/ExcelDownHandler.java +++ b/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/core/ExcelDownHandler.java @@ -55,6 +55,7 @@ public class ExcelDownHandler implements SheetWriteHandler { * 下拉可选项 */ private final List dropDownOptions; + private final DictService dictService; /** * 当前单选进度 */ @@ -63,7 +64,6 @@ public class ExcelDownHandler implements SheetWriteHandler { * 当前联动选择进度 */ private int currentLinkedOptionsSheetIndex; - private final DictService dictService; public ExcelDownHandler(List options) { this.dropDownOptions = options; @@ -139,8 +139,8 @@ public class ExcelDownHandler implements SheetWriteHandler { } else if (everyOptions.getOptions().size() > 10) { // 当一级选项参数个数大于10,使用额外表的形式 dropDownWithSheet(helper, workbook, sheet, everyOptions.getIndex(), everyOptions.getOptions()); - } else if (everyOptions.getOptions().size() != 0) { - // 当一级选项个数不为空,使用默认形式 + } else { + // 否则使用默认形式 dropDownWithSimple(helper, sheet, everyOptions.getIndex(), everyOptions.getOptions()); } }); @@ -171,10 +171,24 @@ public class ExcelDownHandler implements SheetWriteHandler { Sheet linkedOptionsDataSheet = workbook.createSheet(WorkbookUtil.createSafeSheetName(linkedOptionsSheetName)); // 将下拉表隐藏 workbook.setSheetHidden(workbook.getSheetIndex(linkedOptionsDataSheet), true); - // 完善横向的一级选项数据表 + // 选项数据 List firstOptions = options.getOptions(); Map> secoundOptionsMap = options.getNextOptions(); + // 采用按行填充数据的方式,避免EasyExcel出现数据无法写入的问题 + // Attempting to write a row in the range that is already written to disk + + // 使用ArrayList记载数据,防止乱序 + List columnNames = new ArrayList<>(); + // 写入第一行,即第一级的数据 + Row firstRow = linkedOptionsDataSheet.createRow(0); + for (int columnIndex = 0; columnIndex < firstOptions.size(); columnIndex++) { + String columnName = firstOptions.get(columnIndex); + firstRow.createCell(columnIndex) + .setCellValue(columnName); + columnNames.add(columnName); + } + // 创建名称管理器 Name name = workbook.createName(); // 设置名称管理器的别名 @@ -190,28 +204,12 @@ public class ExcelDownHandler implements SheetWriteHandler { // 设置数据校验为序列模式,引用的是名称管理器中的别名 this.markOptionsToSheet(helper, sheet, options.getIndex(), helper.createFormulaListConstraint(linkedOptionsSheetName)); - for (int columIndex = 0; columIndex < firstOptions.size(); columIndex++) { - // 先提取主表中一级下拉的列名 + // 创建二级选项的名称管理器 + for (int columIndex = 0; columIndex < columnNames.size(); columIndex++) { + // 列名 String firstOptionsColumnName = getExcelColumnName(columIndex); - // 一次循环是每一个一级选项 - int finalI = columIndex; - // 本次循环的一级选项值 - String thisFirstOptionsValue = firstOptions.get(columIndex); - // 创建第一行的数据 - Optional.ofNullable(linkedOptionsDataSheet.getRow(0)) - // 如果不存在则创建第一行 - .orElseGet(() -> linkedOptionsDataSheet.createRow(finalI)) - // 第一行当前列 - .createCell(columIndex) - // 设置值为当前一级选项值 - .setCellValue(thisFirstOptionsValue); - - // 第二行开始,设置第二级别选项参数 - List secondOptions = secoundOptionsMap.get(thisFirstOptionsValue); - if (CollUtil.isEmpty(secondOptions)) { - // 必须保证至少有一个关联选项,否则将导致Excel解析错误 - secondOptions = Collections.singletonList("暂无_0"); - } + // 对应的一级值 + String thisFirstOptionsValue = columnNames.get(columIndex); // 以该一级选项值创建子名称管理器 Name sonName = workbook.createName(); @@ -222,7 +220,9 @@ public class ExcelDownHandler implements SheetWriteHandler { linkedOptionsSheetName, firstOptionsColumnName, firstOptionsColumnName, - secondOptions.size() + 1 + // 二级选项存在则设置为(选项个数+1)行,否则设置为2行 + Math.max(Optional.ofNullable(secoundOptionsMap.get(thisFirstOptionsValue)) + .orElseGet(ArrayList::new).size(), 1) + 1 ); // 设置名称管理器的引用位置 sonName.setRefersToFormula(sonFunction); @@ -235,25 +235,51 @@ public class ExcelDownHandler implements SheetWriteHandler { // 二级只能主表每一行的每一列添加二级校验 markLinkedOptionsToSheet(helper, sheet, i, options.getNextIndex(), helper.createFormulaListConstraint(secondOptionsFunction)); } + } - for (int rowIndex = 0; rowIndex < secondOptions.size(); rowIndex++) { - // 从第二行开始填充二级选项 - int finalRowIndex = rowIndex + 1; - int finalColumIndex = columIndex; - - Row row = Optional.ofNullable(linkedOptionsDataSheet.getRow(finalRowIndex)) - // 没有则创建 - .orElseGet(() -> linkedOptionsDataSheet.createRow(finalRowIndex)); - Optional - // 在本级一级选项所在的列 - .ofNullable(row.getCell(finalColumIndex)) - // 不存在则创建 - .orElseGet(() -> row.createCell(finalColumIndex)) - // 设置二级选项值 - .setCellValue(secondOptions.get(rowIndex)); + // 将二级数据处理为按行区分 + Map> columnValueMap = new HashMap<>(); + int currentRow = 1; + while (currentRow >= 0) { + boolean flag = false; + List rowData = new ArrayList<>(); + for (String columnName : columnNames) { + List data = secoundOptionsMap.get(columnName); + if (CollUtil.isEmpty(data)) { + // 添加空字符串填充位置 + rowData.add(" "); + continue; + } + // 取第一个 + String str = data.get(0); + rowData.add(str); + // 通过移除的方式避免重复 + data.remove(0); + // 设置可以继续 + flag = true; + } + columnValueMap.put(currentRow, rowData); + // 可以继续,则增加行数,否则置为负数跳出循环 + if (flag) { + currentRow++; + } else { + currentRow = -1; } } + // 填充第二级选项数据 + columnValueMap.forEach((rowIndex, rowValues) -> { + Row row = linkedOptionsDataSheet.createRow(rowIndex); + for (int columnIndex = 0; columnIndex < rowValues.size(); columnIndex++) { + String rowValue = rowValues.get(columnIndex); + // 填充位置的部分不渲染 + if (StrUtil.isNotBlank(rowValue)) { + row.createCell(columnIndex) + .setCellValue(rowValue); + } + } + }); + currentLinkedOptionsSheetIndex++; } diff --git a/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/service/impl/ExportExcelServiceImpl.java b/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/service/impl/ExportExcelServiceImpl.java index 0240e02f2..ebb6ac688 100644 --- a/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/service/impl/ExportExcelServiceImpl.java +++ b/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/service/impl/ExportExcelServiceImpl.java @@ -1,5 +1,6 @@ package org.dromara.demo.service.impl; +import cn.hutool.core.util.RandomUtil; import cn.hutool.core.util.StrUtil; import jakarta.servlet.http.HttpServletResponse; import lombok.Data; @@ -121,8 +122,9 @@ public class ExportExcelServiceImpl implements IExportExcelService { List provinceList = new ArrayList<>(); // 实际业务中一般采用数据库读取的形式,这里直接拼接创建 - provinceList.add(new DemoCityData(0, null, "安徽省")); - provinceList.add(new DemoCityData(1, null, "江苏省")); + provinceList.add(new DemoCityData(0, null, "P100000")); + provinceList.add(new DemoCityData(1, null, "P200000")); + provinceList.add(new DemoCityData(2, null, "P300000")); return provinceList; } @@ -137,11 +139,11 @@ public class ExportExcelServiceImpl implements IExportExcelService { List cityList = new ArrayList<>(); // 实际业务中一般采用数据库读取的形式,这里直接拼接创建 - cityList.add(new DemoCityData(0, 0, "合肥市")); - cityList.add(new DemoCityData(1, 0, "芜湖市")); - cityList.add(new DemoCityData(2, 1, "南京市")); - cityList.add(new DemoCityData(3, 1, "无锡市")); - cityList.add(new DemoCityData(4, 1, "徐州市")); + cityList.add(new DemoCityData(0, 0, "C110000")); + cityList.add(new DemoCityData(1, 0, "C120000")); + cityList.add(new DemoCityData(2, 1, "C210000")); + cityList.add(new DemoCityData(3, 1, "C220000")); + cityList.add(new DemoCityData(4, 1, "C230000")); selectParentData(provinceList, cityList); @@ -157,17 +159,29 @@ public class ExportExcelServiceImpl implements IExportExcelService { private List getAreaList(List cityList) { List areaList = new ArrayList<>(); + int minCount = 500; + int maxCount = 10000; + // 实际业务中一般采用数据库读取的形式,这里直接拼接创建 - areaList.add(new DemoCityData(0, 0, "瑶海区")); - areaList.add(new DemoCityData(1, 0, "庐江区")); - areaList.add(new DemoCityData(2, 1, "南宁县")); - areaList.add(new DemoCityData(3, 1, "镜湖区")); - areaList.add(new DemoCityData(4, 2, "玄武区")); - areaList.add(new DemoCityData(5, 2, "秦淮区")); - areaList.add(new DemoCityData(6, 3, "宜兴市")); - areaList.add(new DemoCityData(7, 3, "新吴区")); - areaList.add(new DemoCityData(8, 4, "鼓楼区")); - areaList.add(new DemoCityData(9, 4, "丰县")); + for (int i = 0; i < RandomUtil.randomInt(minCount, maxCount); i++) { + areaList.add(new DemoCityData(areaList.size(), 0, String.format("A11%04d", i))); + } + + for (int i = 0; i < RandomUtil.randomInt(minCount, maxCount); i++) { + areaList.add(new DemoCityData(areaList.size(), 1, String.format("A12%04d", i))); + } + + for (int i = 0; i < RandomUtil.randomInt(minCount, maxCount); i++) { + areaList.add(new DemoCityData(areaList.size(), 2, String.format("A21%04d", i))); + } + + for (int i = 0; i < RandomUtil.randomInt(minCount, maxCount); i++) { + areaList.add(new DemoCityData(areaList.size(), 3, String.format("A22%04d", i))); + } + + for (int i = 0; i < RandomUtil.randomInt(minCount, maxCount); i++) { + areaList.add(new DemoCityData(areaList.size(), 4, String.format("A23%04d", i))); + } selectParentData(cityList, areaList); From 73d5fbd085bb8729b7a8eb26aa0e2744c6452a42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Wed, 6 Nov 2024 22:13:56 +0800 Subject: [PATCH 026/175] =?UTF-8?q?fix=20=E4=BF=AE=E5=A4=8D=20PlusSmsDao#c?= =?UTF-8?q?lean=20=E6=96=B9=E6=B3=95=E4=B9=A6=E5=86=99=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/org/dromara/common/sms/core/dao/PlusSmsDao.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruoyi-common/ruoyi-common-sms/src/main/java/org/dromara/common/sms/core/dao/PlusSmsDao.java b/ruoyi-common/ruoyi-common-sms/src/main/java/org/dromara/common/sms/core/dao/PlusSmsDao.java index 91d8d243a..a757655ce 100644 --- a/ruoyi-common/ruoyi-common-sms/src/main/java/org/dromara/common/sms/core/dao/PlusSmsDao.java +++ b/ruoyi-common/ruoyi-common-sms/src/main/java/org/dromara/common/sms/core/dao/PlusSmsDao.java @@ -66,7 +66,7 @@ public class PlusSmsDao implements SmsDao { */ @Override public void clean() { - RedisUtils.deleteObject(GlobalConstants.GLOBAL_REDIS_KEY + "sms:"); + RedisUtils.deleteKeys(GlobalConstants.GLOBAL_REDIS_KEY + "sms:*"); } } From 0a0a16f9698d0fca4379e5551163483186765df4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Thu, 7 Nov 2024 15:48:24 +0800 Subject: [PATCH 027/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E5=B0=81?= =?UTF-8?q?=E8=A3=85=E9=83=A8=E9=97=A8=E5=9F=BA=E4=BA=8E=E7=88=B6id?= =?UTF-8?q?=E6=9F=A5=E8=AF=A2=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/org/dromara/system/mapper/SysDeptMapper.java | 8 ++++++++ .../system/service/impl/SysDataScopeServiceImpl.java | 5 +---- .../system/service/impl/SysPostServiceImpl.java | 10 ++-------- .../system/service/impl/SysUserServiceImpl.java | 5 +---- 4 files changed, 12 insertions(+), 16 deletions(-) diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysDeptMapper.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysDeptMapper.java index 08dda662c..048d2fa45 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysDeptMapper.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysDeptMapper.java @@ -1,10 +1,12 @@ package org.dromara.system.mapper; import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Constants; import org.dromara.common.mybatis.annotation.DataColumn; import org.dromara.common.mybatis.annotation.DataPermission; import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; +import org.dromara.common.mybatis.helper.DataBaseHelper; import org.dromara.system.domain.SysDept; import org.dromara.system.domain.vo.SysDeptVo; import org.apache.ibatis.annotations.Param; @@ -34,6 +36,12 @@ public interface SysDeptMapper extends BaseMapperPlus { }) long countDeptById(Long deptId); + default List selectListByParentId(Long parentId) { + return this.selectList(new LambdaQueryWrapper() + .select(SysDept::getDeptId) + .apply(DataBaseHelper.findInSet(parentId, "ancestors"))); + } + /** * 根据角色ID查询部门树信息 * diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDataScopeServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDataScopeServiceImpl.java index 018f9a07a..0c07f7f67 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDataScopeServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDataScopeServiceImpl.java @@ -6,7 +6,6 @@ import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import lombok.RequiredArgsConstructor; import org.dromara.common.core.utils.StreamUtils; -import org.dromara.common.mybatis.helper.DataBaseHelper; import org.dromara.system.domain.SysDept; import org.dromara.system.domain.SysRoleDept; import org.dromara.system.mapper.SysDeptMapper; @@ -63,9 +62,7 @@ public class SysDataScopeServiceImpl implements ISysDataScopeService { if (ObjectUtil.isNull(deptId)) { return "-1"; } - List deptList = deptMapper.selectList(new LambdaQueryWrapper() - .select(SysDept::getDeptId) - .apply(DataBaseHelper.findInSet(deptId, "ancestors"))); + List deptList = deptMapper.selectListByParentId(deptId); List ids = StreamUtils.toList(deptList, SysDept::getDeptId); ids.add(deptId); if (CollUtil.isNotEmpty(ids)) { diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysPostServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysPostServiceImpl.java index 2c38129ac..e3f4145b4 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 @@ -13,7 +13,6 @@ import org.dromara.common.core.utils.StreamUtils; import org.dromara.common.core.utils.StringUtils; import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.TableDataInfo; -import org.dromara.common.mybatis.helper.DataBaseHelper; import org.dromara.system.domain.SysDept; import org.dromara.system.domain.SysPost; import org.dromara.system.domain.SysUserPost; @@ -27,7 +26,6 @@ import org.springframework.stereotype.Service; import java.util.Arrays; import java.util.List; -import java.util.stream.Collectors; /** * 岗位信息 服务层处理 @@ -78,12 +76,8 @@ public class SysPostServiceImpl implements ISysPostService { } else if (ObjectUtil.isNotNull(bo.getBelongDeptId())) { //部门树搜索 wrapper.and(x -> { - List deptIds = deptMapper.selectList(new LambdaQueryWrapper() - .select(SysDept::getDeptId) - .apply(DataBaseHelper.findInSet(bo.getBelongDeptId(), "ancestors"))) - .stream() - .map(SysDept::getDeptId) - .collect(Collectors.toList()); + List deptList = deptMapper.selectListByParentId(bo.getBelongDeptId()); + List deptIds = StreamUtils.toList(deptList, SysDept::getDeptId); deptIds.add(bo.getBelongDeptId()); x.in(SysPost::getDeptId, deptIds); }); diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysUserServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysUserServiceImpl.java index 8c6d1d5f5..cd69767cc 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 @@ -24,7 +24,6 @@ import org.dromara.common.core.utils.StreamUtils; import org.dromara.common.core.utils.StringUtils; import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.TableDataInfo; -import org.dromara.common.mybatis.helper.DataBaseHelper; import org.dromara.common.satoken.utils.LoginHelper; import org.dromara.system.domain.*; import org.dromara.system.domain.bo.SysUserBo; @@ -89,9 +88,7 @@ public class SysUserServiceImpl implements ISysUserService, UserService { .between(params.get("beginTime") != null && params.get("endTime") != null, "u.create_time", params.get("beginTime"), params.get("endTime")) .and(ObjectUtil.isNotNull(user.getDeptId()), w -> { - List deptList = deptMapper.selectList(new LambdaQueryWrapper() - .select(SysDept::getDeptId) - .apply(DataBaseHelper.findInSet(user.getDeptId(), "ancestors"))); + List deptList = deptMapper.selectListByParentId(user.getDeptId()); List ids = StreamUtils.toList(deptList, SysDept::getDeptId); ids.add(user.getDeptId()); w.in("u.dept_id", ids); From 8a5d8cc9b9e02e24685e0ebbcb6d8d28b1eae5c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Thu, 7 Nov 2024 22:26:12 +0800 Subject: [PATCH 028/175] =?UTF-8?q?add=20=E5=A2=9E=E5=8A=A0=20=E9=82=AE?= =?UTF-8?q?=E4=BB=B6=E5=A4=9A=E9=99=84=E4=BB=B6demo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../demo/controller/MailController.java | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/MailController.java b/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/MailController.java index 47b4349da..01f50449f 100644 --- a/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/MailController.java +++ b/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/MailController.java @@ -1,14 +1,16 @@ package org.dromara.demo.controller; +import cn.dev33.satoken.annotation.SaIgnore; +import lombok.RequiredArgsConstructor; import org.dromara.common.core.domain.R; import org.dromara.common.mail.utils.MailUtils; -import lombok.RequiredArgsConstructor; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.io.File; +import java.util.Arrays; /** @@ -16,6 +18,7 @@ import java.io.File; * * @author Michelle.Chung */ +@SaIgnore @Validated @RequiredArgsConstructor @RestController @@ -49,4 +52,19 @@ public class MailController { return R.ok(); } + /** + * 发送邮件(多附件) + * + * @param to 接收人 + * @param subject 标题 + * @param text 内容 + * @param paths 附件路径 + */ + @GetMapping("/sendMessageWithAttachments") + public R sendMessageWithAttachments(String to, String subject, String text, String[] paths) { + File[] array = Arrays.stream(paths).map(File::new).toArray(File[]::new); + MailUtils.sendText(to, subject, text, array); + return R.ok(); + } + } From 70a5077291dbd6e8953ecee8740333f5b862d1bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Fri, 8 Nov 2024 00:30:43 +0800 Subject: [PATCH 029/175] =?UTF-8?q?fix=20=E4=BF=AE=E5=A4=8D=20sse=20?= =?UTF-8?q?=E5=85=B3=E9=97=AD=E6=8E=A5=E5=8F=A3=E6=97=A0=E6=B3=95=E6=96=AD?= =?UTF-8?q?=E8=BF=9E=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/org/dromara/common/sse/core/SseEmitterManager.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ruoyi-common/ruoyi-common-sse/src/main/java/org/dromara/common/sse/core/SseEmitterManager.java b/ruoyi-common/ruoyi-common-sse/src/main/java/org/dromara/common/sse/core/SseEmitterManager.java index 0bfe0ca76..c26adca50 100644 --- a/ruoyi-common/ruoyi-common-sse/src/main/java/org/dromara/common/sse/core/SseEmitterManager.java +++ b/ruoyi-common/ruoyi-common-sse/src/main/java/org/dromara/common/sse/core/SseEmitterManager.java @@ -67,7 +67,9 @@ public class SseEmitterManager { Map emitters = USER_TOKEN_EMITTERS.get(userId); if (emitters != null) { try { - emitters.get(token).send(SseEmitter.event().comment("disconnected")); + SseEmitter sseEmitter = emitters.get(token); + sseEmitter.send(SseEmitter.event().comment("disconnected")); + sseEmitter.complete(); } catch (Exception ignore) { } emitters.remove(token); From 8e749c472aeec4f7a6b411118d713468c63b0e3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Sat, 9 Nov 2024 21:01:40 +0800 Subject: [PATCH 030/175] =?UTF-8?q?fix=20=E4=BF=AE=E5=A4=8D=20PageQuery=20?= =?UTF-8?q?=E8=BD=ACjson=E6=8A=A5=E9=94=99=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/org/dromara/common/mybatis/core/page/PageQuery.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/core/page/PageQuery.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/core/page/PageQuery.java index 6ca9b2756..3f7797d6b 100644 --- a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/core/page/PageQuery.java +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/core/page/PageQuery.java @@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.metadata.OrderItem; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.fasterxml.jackson.annotation.JsonIgnore; import lombok.Data; import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.utils.StringUtils; @@ -113,6 +114,7 @@ public class PageQuery implements Serializable { return list; } + @JsonIgnore public Integer getFirstNum() { return (pageNum - 1) * pageSize; } From b820a98c6cece449e6822a0ef39047c5503e2d3f Mon Sep 17 00:00:00 2001 From: AprilWind <2100166581@qq.com> Date: Mon, 11 Nov 2024 10:05:52 +0800 Subject: [PATCH 031/175] =?UTF-8?q?docs=EF=BC=9A=E8=A1=A5=E5=85=85Mapper?= =?UTF-8?q?=E5=B1=82=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dromara/system/mapper/SysDeptMapper.java | 14 +++++++- .../system/mapper/SysDictDataMapper.java | 6 ++++ .../dromara/system/mapper/SysPostMapper.java | 7 ++++ .../dromara/system/mapper/SysRoleMapper.java | 13 ++++++++ .../dromara/system/mapper/SysUserMapper.java | 32 +++++++++++++++++++ .../system/mapper/SysUserRoleMapper.java | 6 ++++ 6 files changed, 77 insertions(+), 1 deletion(-) diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysDeptMapper.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysDeptMapper.java index 048d2fa45..0f2c90667 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysDeptMapper.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysDeptMapper.java @@ -3,13 +3,13 @@ package org.dromara.system.mapper; import com.baomidou.mybatisplus.core.conditions.Wrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Constants; +import org.apache.ibatis.annotations.Param; import org.dromara.common.mybatis.annotation.DataColumn; import org.dromara.common.mybatis.annotation.DataPermission; import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; import org.dromara.common.mybatis.helper.DataBaseHelper; import org.dromara.system.domain.SysDept; import org.dromara.system.domain.vo.SysDeptVo; -import org.apache.ibatis.annotations.Param; import java.util.List; @@ -31,11 +31,23 @@ public interface SysDeptMapper extends BaseMapperPlus { }) List selectDeptList(@Param(Constants.WRAPPER) Wrapper queryWrapper); + /** + * 统计指定部门ID的部门数量 + * + * @param deptId 部门ID + * @return 该部门ID的部门数量 + */ @DataPermission({ @DataColumn(key = "deptName", value = "dept_id") }) long countDeptById(Long deptId); + /** + * 根据父部门ID查询其所有子部门的列表 + * + * @param parentId 父部门ID + * @return 包含子部门的列表 + */ default List selectListByParentId(Long parentId) { return this.selectList(new LambdaQueryWrapper() .select(SysDept::getDeptId) diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysDictDataMapper.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysDictDataMapper.java index c2f1a7cbe..7298db3d0 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysDictDataMapper.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysDictDataMapper.java @@ -14,6 +14,12 @@ import java.util.List; */ public interface SysDictDataMapper extends BaseMapperPlus { + /** + * 根据字典类型查询字典数据列表 + * + * @param dictType 字典类型 + * @return 符合条件的字典数据列表 + */ default List selectDictDataByType(String dictType) { return selectVoList( new LambdaQueryWrapper() diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysPostMapper.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysPostMapper.java index f9bf13485..60da074c7 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysPostMapper.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysPostMapper.java @@ -19,6 +19,13 @@ import java.util.List; */ public interface SysPostMapper extends BaseMapperPlus { + /** + * 分页查询岗位列表 + * + * @param page 分页对象 + * @param queryWrapper 查询条件 + * @return 包含岗位信息的分页结果 + */ @DataPermission({ @DataColumn(key = "deptName", value = "dept_id"), @DataColumn(key = "userName", value = "create_by") diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysRoleMapper.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysRoleMapper.java index ac5a47e54..9cb1ea509 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysRoleMapper.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysRoleMapper.java @@ -19,6 +19,13 @@ import java.util.List; */ public interface SysRoleMapper extends BaseMapperPlus { + /** + * 分页查询角色列表 + * + * @param page 分页对象 + * @param queryWrapper 查询条件 + * @return 包含角色信息的分页结果 + */ @DataPermission({ @DataColumn(key = "deptName", value = "d.dept_id"), @DataColumn(key = "userName", value = "r.create_by") @@ -37,6 +44,12 @@ public interface SysRoleMapper extends BaseMapperPlus { }) List selectRoleList(@Param(Constants.WRAPPER) Wrapper queryWrapper); + /** + * 根据角色ID查询角色信息 + * + * @param roleId 角色ID + * @return 对应的角色信息 + */ @DataPermission({ @DataColumn(key = "deptName", value = "d.dept_id"), @DataColumn(key = "userName", value = "r.create_by") diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysUserMapper.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysUserMapper.java index fc7fc6e16..46695aa4c 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysUserMapper.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysUserMapper.java @@ -20,12 +20,25 @@ import java.util.List; */ public interface SysUserMapper extends BaseMapperPlus { + /** + * 分页查询用户列表,并进行数据权限控制 + * + * @param page 分页参数 + * @param queryWrapper 查询条件 + * @return 分页的用户信息 + */ @DataPermission({ @DataColumn(key = "deptName", value = "u.dept_id"), @DataColumn(key = "userName", value = "u.user_id") }) Page selectPageUserList(@Param("page") Page page, @Param(Constants.WRAPPER) Wrapper queryWrapper); + /** + * 查询用户列表,并进行数据权限控制 + * + * @param queryWrapper 查询条件 + * @return 用户信息集合 + */ @DataPermission({ @DataColumn(key = "deptName", value = "dept_id"), @DataColumn(key = "userName", value = "user_id") @@ -68,12 +81,25 @@ public interface SysUserMapper extends BaseMapperPlus { }) Page selectUnallocatedList(@Param("page") Page page, @Param(Constants.WRAPPER) Wrapper queryWrapper); + /** + * 根据用户ID统计用户数量 + * + * @param userId 用户ID + * @return 用户数量 + */ @DataPermission({ @DataColumn(key = "deptName", value = "dept_id"), @DataColumn(key = "userName", value = "user_id") }) long countUserById(Long userId); + /** + * 根据条件更新用户数据 + * + * @param user 要更新的用户实体 + * @param updateWrapper 更新条件封装器 + * @return 更新操作影响的行数 + */ @Override @DataPermission({ @DataColumn(key = "deptName", value = "dept_id"), @@ -81,6 +107,12 @@ public interface SysUserMapper extends BaseMapperPlus { }) int update(@Param(Constants.ENTITY) SysUser user, @Param(Constants.WRAPPER) Wrapper updateWrapper); + /** + * 根据用户ID更新用户数据 + * + * @param user 要更新的用户实体 + * @return 更新操作影响的行数 + */ @Override @DataPermission({ @DataColumn(key = "deptName", value = "dept_id"), diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysUserRoleMapper.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysUserRoleMapper.java index e2f706c89..83403480e 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysUserRoleMapper.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysUserRoleMapper.java @@ -12,6 +12,12 @@ import java.util.List; */ public interface SysUserRoleMapper extends BaseMapperPlus { + /** + * 根据角色ID查询关联的用户ID列表 + * + * @param roleId 角色ID + * @return 关联到指定角色的用户ID列表 + */ List selectUserIdsByRoleId(Long roleId); } From 9cdcbbccbf4b8752504d11e3379a7156492b07f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Mon, 11 Nov 2024 10:25:31 +0800 Subject: [PATCH 032/175] =?UTF-8?q?update=20=E9=87=8D=E6=9E=84=20=E5=B0=86?= =?UTF-8?q?UserConstants=E6=94=B9=E4=B8=BASystemConstants=20=E7=BB=9F?= =?UTF-8?q?=E4=B8=80=E5=B8=B8=E9=87=8F=E4=BD=BF=E7=94=A8=20=E9=99=8D?= =?UTF-8?q?=E4=BD=8E=E4=BD=BF=E7=94=A8=E9=9A=BE=E5=BA=A6=E9=81=BF=E5=85=8D?= =?UTF-8?q?=E8=AF=AF=E8=A7=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/controller/AuthController.java | 4 +- .../dromara/web/service/SysLoginService.java | 4 +- .../web/service/impl/EmailAuthStrategy.java | 4 +- .../service/impl/PasswordAuthStrategy.java | 4 +- .../web/service/impl/SmsAuthStrategy.java | 4 +- .../web/service/impl/SocialAuthStrategy.java | 4 +- .../web/service/impl/XcxAuthStrategy.java | 5 +- .../common/core/constant/Constants.java | 5 - .../common/core/constant/SystemConstants.java | 70 ++++++++ .../common/core/constant/TenantConstants.java | 10 -- .../common/core/constant/UserConstants.java | 152 ------------------ .../core/domain/model/PasswordLoginBody.java | 6 +- .../core/domain/model/RegisterBody.java | 6 +- .../common/core/enums/TenantStatus.java | 30 ---- .../common/satoken/utils/LoginHelper.java | 4 +- .../dromara/demo/domain/vo/ExportDemoVo.java | 6 +- .../service/impl/ExportExcelServiceImpl.java | 4 +- .../controller/system/SysDeptController.java | 4 +- .../controller/system/SysMenuController.java | 8 +- .../controller/system/SysPostController.java | 4 +- .../controller/system/SysUserController.java | 4 +- .../dromara/system/domain/SysDictData.java | 6 +- .../org/dromara/system/domain/SysMenu.java | 24 +-- .../org/dromara/system/domain/SysUser.java | 6 +- .../dromara/system/domain/bo/SysRoleBo.java | 4 +- .../dromara/system/domain/bo/SysUserBo.java | 4 +- .../dromara/system/domain/vo/SysRoleVo.java | 8 +- .../dromara/system/mapper/SysMenuMapper.java | 12 +- .../service/impl/SysConfigServiceImpl.java | 4 +- .../service/impl/SysDeptServiceImpl.java | 24 ++- .../service/impl/SysMenuServiceImpl.java | 6 +- .../service/impl/SysPostServiceImpl.java | 4 +- .../service/impl/SysRoleServiceImpl.java | 10 +- .../impl/SysTenantPackageServiceImpl.java | 4 +- .../service/impl/SysTenantServiceImpl.java | 5 +- .../service/impl/SysUserServiceImpl.java | 16 +- 36 files changed, 174 insertions(+), 305 deletions(-) create mode 100644 ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/SystemConstants.java delete mode 100644 ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/UserConstants.java delete mode 100644 ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/enums/TenantStatus.java diff --git a/ruoyi-admin/src/main/java/org/dromara/web/controller/AuthController.java b/ruoyi-admin/src/main/java/org/dromara/web/controller/AuthController.java index b561693d6..89fe607f6 100644 --- a/ruoyi-admin/src/main/java/org/dromara/web/controller/AuthController.java +++ b/ruoyi-admin/src/main/java/org/dromara/web/controller/AuthController.java @@ -12,7 +12,7 @@ import me.zhyd.oauth.model.AuthResponse; import me.zhyd.oauth.model.AuthUser; import me.zhyd.oauth.request.AuthRequest; import me.zhyd.oauth.utils.AuthStateUtils; -import org.dromara.common.core.constant.UserConstants; +import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.core.domain.R; import org.dromara.common.core.domain.model.LoginBody; import org.dromara.common.core.domain.model.RegisterBody; @@ -92,7 +92,7 @@ public class AuthController { if (ObjectUtil.isNull(client) || !StringUtils.contains(client.getGrantType(), grantType)) { log.info("客户端id: {} 认证类型:{} 异常!.", clientId, grantType); return R.fail(MessageUtils.message("auth.grant.type.error")); - } else if (!UserConstants.NORMAL.equals(client.getStatus())) { + } else if (!SystemConstants.NORMAL.equals(client.getStatus())) { return R.fail(MessageUtils.message("auth.grant.type.blocked")); } // 校验租户 diff --git a/ruoyi-admin/src/main/java/org/dromara/web/service/SysLoginService.java b/ruoyi-admin/src/main/java/org/dromara/web/service/SysLoginService.java index c7ad9179c..0fdd521a0 100644 --- a/ruoyi-admin/src/main/java/org/dromara/web/service/SysLoginService.java +++ b/ruoyi-admin/src/main/java/org/dromara/web/service/SysLoginService.java @@ -12,11 +12,11 @@ import lombok.extern.slf4j.Slf4j; import me.zhyd.oauth.model.AuthUser; import org.dromara.common.core.constant.CacheConstants; import org.dromara.common.core.constant.Constants; +import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.core.constant.TenantConstants; import org.dromara.common.core.domain.dto.RoleDTO; import org.dromara.common.core.domain.model.LoginUser; import org.dromara.common.core.enums.LoginType; -import org.dromara.common.core.enums.TenantStatus; import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.exception.user.UserException; import org.dromara.common.core.utils.*; @@ -233,7 +233,7 @@ public class SysLoginService { if (ObjectUtil.isNull(tenant)) { log.info("登录租户:{} 不存在.", tenantId); throw new TenantException("tenant.not.exists"); - } else if (TenantStatus.DISABLE.getCode().equals(tenant.getStatus())) { + } else if (SystemConstants.DISABLE.equals(tenant.getStatus())) { log.info("登录租户:{} 已被停用.", tenantId); throw new TenantException("tenant.blocked"); } else if (ObjectUtil.isNotNull(tenant.getExpireTime()) diff --git a/ruoyi-admin/src/main/java/org/dromara/web/service/impl/EmailAuthStrategy.java b/ruoyi-admin/src/main/java/org/dromara/web/service/impl/EmailAuthStrategy.java index b5a24976e..1bed4f3e5 100644 --- a/ruoyi-admin/src/main/java/org/dromara/web/service/impl/EmailAuthStrategy.java +++ b/ruoyi-admin/src/main/java/org/dromara/web/service/impl/EmailAuthStrategy.java @@ -8,10 +8,10 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.dromara.common.core.constant.Constants; import org.dromara.common.core.constant.GlobalConstants; +import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.core.domain.model.EmailLoginBody; import org.dromara.common.core.domain.model.LoginUser; import org.dromara.common.core.enums.LoginType; -import org.dromara.common.core.enums.UserStatus; import org.dromara.common.core.exception.user.CaptchaExpireException; import org.dromara.common.core.exception.user.UserException; import org.dromara.common.core.utils.MessageUtils; @@ -92,7 +92,7 @@ public class EmailAuthStrategy implements IAuthStrategy { if (ObjectUtil.isNull(user)) { log.info("登录用户:{} 不存在.", email); throw new UserException("user.not.exists", email); - } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) { + } else if (SystemConstants.DISABLE.equals(user.getStatus())) { log.info("登录用户:{} 已被停用.", email); throw new UserException("user.blocked", email); } diff --git a/ruoyi-admin/src/main/java/org/dromara/web/service/impl/PasswordAuthStrategy.java b/ruoyi-admin/src/main/java/org/dromara/web/service/impl/PasswordAuthStrategy.java index f28024f35..e8e60e1c4 100644 --- a/ruoyi-admin/src/main/java/org/dromara/web/service/impl/PasswordAuthStrategy.java +++ b/ruoyi-admin/src/main/java/org/dromara/web/service/impl/PasswordAuthStrategy.java @@ -9,10 +9,10 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.dromara.common.core.constant.Constants; import org.dromara.common.core.constant.GlobalConstants; +import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.core.domain.model.LoginUser; import org.dromara.common.core.domain.model.PasswordLoginBody; import org.dromara.common.core.enums.LoginType; -import org.dromara.common.core.enums.UserStatus; import org.dromara.common.core.exception.user.CaptchaException; import org.dromara.common.core.exception.user.CaptchaExpireException; import org.dromara.common.core.exception.user.UserException; @@ -113,7 +113,7 @@ public class PasswordAuthStrategy implements IAuthStrategy { if (ObjectUtil.isNull(user)) { log.info("登录用户:{} 不存在.", username); throw new UserException("user.not.exists", username); - } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) { + } else if (SystemConstants.DISABLE.equals(user.getStatus())) { log.info("登录用户:{} 已被停用.", username); throw new UserException("user.blocked", username); } diff --git a/ruoyi-admin/src/main/java/org/dromara/web/service/impl/SmsAuthStrategy.java b/ruoyi-admin/src/main/java/org/dromara/web/service/impl/SmsAuthStrategy.java index 89f846244..2ffda353e 100644 --- a/ruoyi-admin/src/main/java/org/dromara/web/service/impl/SmsAuthStrategy.java +++ b/ruoyi-admin/src/main/java/org/dromara/web/service/impl/SmsAuthStrategy.java @@ -8,10 +8,10 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.dromara.common.core.constant.Constants; import org.dromara.common.core.constant.GlobalConstants; +import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.core.domain.model.LoginUser; import org.dromara.common.core.domain.model.SmsLoginBody; import org.dromara.common.core.enums.LoginType; -import org.dromara.common.core.enums.UserStatus; import org.dromara.common.core.exception.user.CaptchaExpireException; import org.dromara.common.core.exception.user.UserException; import org.dromara.common.core.utils.MessageUtils; @@ -92,7 +92,7 @@ public class SmsAuthStrategy implements IAuthStrategy { if (ObjectUtil.isNull(user)) { log.info("登录用户:{} 不存在.", phonenumber); throw new UserException("user.not.exists", phonenumber); - } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) { + } else if (SystemConstants.DISABLE.equals(user.getStatus())) { log.info("登录用户:{} 已被停用.", phonenumber); throw new UserException("user.blocked", phonenumber); } diff --git a/ruoyi-admin/src/main/java/org/dromara/web/service/impl/SocialAuthStrategy.java b/ruoyi-admin/src/main/java/org/dromara/web/service/impl/SocialAuthStrategy.java index 84630260f..419dbd6ba 100644 --- a/ruoyi-admin/src/main/java/org/dromara/web/service/impl/SocialAuthStrategy.java +++ b/ruoyi-admin/src/main/java/org/dromara/web/service/impl/SocialAuthStrategy.java @@ -11,9 +11,9 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import me.zhyd.oauth.model.AuthResponse; import me.zhyd.oauth.model.AuthUser; +import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.core.domain.model.LoginUser; import org.dromara.common.core.domain.model.SocialLoginBody; -import org.dromara.common.core.enums.UserStatus; import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.exception.user.UserException; import org.dromara.common.core.utils.StreamUtils; @@ -121,7 +121,7 @@ public class SocialAuthStrategy implements IAuthStrategy { if (ObjectUtil.isNull(user)) { log.info("登录用户:{} 不存在.", ""); throw new UserException("user.not.exists", ""); - } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) { + } else if (SystemConstants.DISABLE.equals(user.getStatus())) { log.info("登录用户:{} 已被停用.", ""); throw new UserException("user.blocked", ""); } diff --git a/ruoyi-admin/src/main/java/org/dromara/web/service/impl/XcxAuthStrategy.java b/ruoyi-admin/src/main/java/org/dromara/web/service/impl/XcxAuthStrategy.java index aa8be73a7..948ed9acb 100644 --- a/ruoyi-admin/src/main/java/org/dromara/web/service/impl/XcxAuthStrategy.java +++ b/ruoyi-admin/src/main/java/org/dromara/web/service/impl/XcxAuthStrategy.java @@ -5,13 +5,12 @@ import cn.dev33.satoken.stp.StpUtil; import cn.hutool.core.util.ObjectUtil; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.core.domain.model.XcxLoginBody; import org.dromara.common.core.domain.model.XcxLoginUser; -import org.dromara.common.core.enums.UserStatus; import org.dromara.common.core.utils.ValidatorUtils; import org.dromara.common.json.utils.JsonUtils; import org.dromara.common.satoken.utils.LoginHelper; -import org.dromara.system.domain.SysClient; import org.dromara.system.domain.vo.SysClientVo; import org.dromara.system.domain.vo.SysUserVo; import org.dromara.web.domain.vo.LoginVo; @@ -82,7 +81,7 @@ public class XcxAuthStrategy implements IAuthStrategy { if (ObjectUtil.isNull(user)) { log.info("登录用户:{} 不存在.", openid); // todo 用户不存在 业务逻辑自行实现 - } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) { + } else if (SystemConstants.DISABLE.equals(user.getStatus())) { log.info("登录用户:{} 已被停用.", openid); // todo 用户已被停用 业务逻辑自行实现 } diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/Constants.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/Constants.java index cdbda89f6..d031921bd 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/Constants.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/Constants.java @@ -67,11 +67,6 @@ public interface Constants { */ Integer CAPTCHA_EXPIRATION = 2; - /** - * 令牌 - */ - String TOKEN = "token"; - /** * 顶级部门id */ diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/SystemConstants.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/SystemConstants.java new file mode 100644 index 000000000..79afb951f --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/SystemConstants.java @@ -0,0 +1,70 @@ +package org.dromara.common.core.constant; + +/** + * 用户常量信息 + * + * @author Lion Li + */ +public interface SystemConstants { + + /** + * 正常状态 + */ + String NORMAL = "0"; + + /** + * 异常状态 + */ + String DISABLE = "1"; + + /** + * 是否为系统默认(是) + */ + String YES = "Y"; + + /** + * 是否菜单外链(是) + */ + String YES_FRAME = "0"; + + /** + * 是否菜单外链(否) + */ + String NO_FRAME = "1"; + + /** + * 菜单类型(目录) + */ + String TYPE_DIR = "M"; + + /** + * 菜单类型(菜单) + */ + String TYPE_MENU = "C"; + + /** + * 菜单类型(按钮) + */ + String TYPE_BUTTON = "F"; + + /** + * Layout组件标识 + */ + String LAYOUT = "Layout"; + + /** + * ParentView组件标识 + */ + String PARENT_VIEW = "ParentView"; + + /** + * InnerLink组件标识 + */ + String INNER_LINK = "InnerLink"; + + /** + * 超级管理员ID + */ + Long SUPER_ADMIN_ID = 1L; + +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/TenantConstants.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/TenantConstants.java index 86b63c97a..33ce0cf6c 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/TenantConstants.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/TenantConstants.java @@ -7,16 +7,6 @@ package org.dromara.common.core.constant; */ public interface TenantConstants { - /** - * 租户正常状态 - */ - String NORMAL = "0"; - - /** - * 租户封禁状态 - */ - String DISABLE = "1"; - /** * 超级管理员ID */ diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/UserConstants.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/UserConstants.java deleted file mode 100644 index 76f6dd4ad..000000000 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/UserConstants.java +++ /dev/null @@ -1,152 +0,0 @@ -package org.dromara.common.core.constant; - -/** - * 用户常量信息 - * - * @author ruoyi - */ -public interface UserConstants { - - /** - * 平台内系统用户的唯一标志 - */ - String SYS_USER = "SYS_USER"; - - /** - * 正常状态 - */ - String NORMAL = "0"; - - /** - * 异常状态 - */ - String EXCEPTION = "1"; - - /** - * 用户正常状态 - */ - String USER_NORMAL = "0"; - - /** - * 用户封禁状态 - */ - String USER_DISABLE = "1"; - - /** - * 角色正常状态 - */ - String ROLE_NORMAL = "0"; - - /** - * 角色封禁状态 - */ - String ROLE_DISABLE = "1"; - - /** - * 部门正常状态 - */ - String DEPT_NORMAL = "0"; - - /** - * 部门停用状态 - */ - String DEPT_DISABLE = "1"; - - /** - * 岗位正常状态 - */ - String POST_NORMAL = "0"; - - /** - * 岗位停用状态 - */ - String POST_DISABLE = "1"; - - /** - * 字典正常状态 - */ - String DICT_NORMAL = "0"; - - /** - * 通用存在标志 - */ - String DEL_FLAG_NORMAL = "0"; - - /** - * 通用删除标志 - */ - String DEL_FLAG_REMOVED = "2"; - - /** - * 是否为系统默认(是) - */ - String YES = "Y"; - - /** - * 是否菜单外链(是) - */ - String YES_FRAME = "0"; - - /** - * 是否菜单外链(否) - */ - String NO_FRAME = "1"; - - /** - * 菜单正常状态 - */ - String MENU_NORMAL = "0"; - - /** - * 菜单停用状态 - */ - String MENU_DISABLE = "1"; - - /** - * 菜单类型(目录) - */ - String TYPE_DIR = "M"; - - /** - * 菜单类型(菜单) - */ - String TYPE_MENU = "C"; - - /** - * 菜单类型(按钮) - */ - String TYPE_BUTTON = "F"; - - /** - * Layout组件标识 - */ - String LAYOUT = "Layout"; - - /** - * ParentView组件标识 - */ - String PARENT_VIEW = "ParentView"; - - /** - * InnerLink组件标识 - */ - String INNER_LINK = "InnerLink"; - - /** - * 用户名长度限制 - */ - int USERNAME_MIN_LENGTH = 2; - int USERNAME_MAX_LENGTH = 20; - - /** - * 密码长度限制 - */ - int PASSWORD_MIN_LENGTH = 5; - int PASSWORD_MAX_LENGTH = 20; - - /** - * 超级管理员ID - */ - Long SUPER_ADMIN_ID = 1L; - -} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/model/PasswordLoginBody.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/model/PasswordLoginBody.java index 22de8f2c4..87d0e8e73 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/model/PasswordLoginBody.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/model/PasswordLoginBody.java @@ -5,8 +5,6 @@ import lombok.Data; import lombok.EqualsAndHashCode; import org.hibernate.validator.constraints.Length; -import static org.dromara.common.core.constant.UserConstants.*; - /** * 密码登录对象 * @@ -20,14 +18,14 @@ public class PasswordLoginBody extends LoginBody { * 用户名 */ @NotBlank(message = "{user.username.not.blank}") - @Length(min = USERNAME_MIN_LENGTH, max = USERNAME_MAX_LENGTH, message = "{user.username.length.valid}") + @Length(min = 2, max = 20, message = "{user.username.length.valid}") private String username; /** * 用户密码 */ @NotBlank(message = "{user.password.not.blank}") - @Length(min = PASSWORD_MIN_LENGTH, max = PASSWORD_MAX_LENGTH, message = "{user.password.length.valid}") + @Length(min = 5, max = 20, message = "{user.password.length.valid}") private String password; } diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/model/RegisterBody.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/model/RegisterBody.java index 440422bb6..6ea8a764a 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/model/RegisterBody.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/model/RegisterBody.java @@ -5,8 +5,6 @@ import lombok.Data; import lombok.EqualsAndHashCode; import org.hibernate.validator.constraints.Length; -import static org.dromara.common.core.constant.UserConstants.*; - /** * 用户注册对象 * @@ -20,14 +18,14 @@ public class RegisterBody extends LoginBody { * 用户名 */ @NotBlank(message = "{user.username.not.blank}") - @Length(min = USERNAME_MIN_LENGTH, max = USERNAME_MAX_LENGTH, message = "{user.username.length.valid}") + @Length(min = 2, max = 20, message = "{user.username.length.valid}") private String username; /** * 用户密码 */ @NotBlank(message = "{user.password.not.blank}") - @Length(min = PASSWORD_MIN_LENGTH, max = PASSWORD_MAX_LENGTH, message = "{user.password.length.valid}") + @Length(min = 5, max = 20, message = "{user.password.length.valid}") private String password; private String userType; diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/enums/TenantStatus.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/enums/TenantStatus.java deleted file mode 100644 index 400a3996a..000000000 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/enums/TenantStatus.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.dromara.common.core.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * 用户状态 - * - * @author LionLi - */ -@Getter -@AllArgsConstructor -public enum TenantStatus { - /** - * 正常 - */ - OK("0", "正常"), - /** - * 停用 - */ - DISABLE("1", "停用"), - /** - * 删除 - */ - DELETED("2", "删除"); - - private final String code; - private final String info; - -} diff --git a/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/utils/LoginHelper.java b/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/utils/LoginHelper.java index 4ab7d4eeb..cdc5684fa 100644 --- a/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/utils/LoginHelper.java +++ b/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/utils/LoginHelper.java @@ -8,8 +8,8 @@ import cn.hutool.core.convert.Convert; import cn.hutool.core.util.ObjectUtil; import lombok.AccessLevel; import lombok.NoArgsConstructor; +import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.core.constant.TenantConstants; -import org.dromara.common.core.constant.UserConstants; import org.dromara.common.core.domain.model.LoginUser; import org.dromara.common.core.enums.UserType; @@ -152,7 +152,7 @@ public class LoginHelper { * @return 结果 */ public static boolean isSuperAdmin(Long userId) { - return UserConstants.SUPER_ADMIN_ID.equals(userId); + return SystemConstants.SUPER_ADMIN_ID.equals(userId); } /** diff --git a/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/vo/ExportDemoVo.java b/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/vo/ExportDemoVo.java index 95fa0d140..ef9058ed5 100644 --- a/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/vo/ExportDemoVo.java +++ b/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/vo/ExportDemoVo.java @@ -15,6 +15,9 @@ import org.dromara.common.excel.annotation.ExcelEnumFormat; import org.dromara.common.excel.convert.ExcelDictConvert; import org.dromara.common.excel.convert.ExcelEnumConvert; +import java.io.Serial; +import java.io.Serializable; + /** * 带有下拉选的Excel导出 * @@ -24,8 +27,9 @@ import org.dromara.common.excel.convert.ExcelEnumConvert; @ExcelIgnoreUnannotated @AllArgsConstructor @NoArgsConstructor -public class ExportDemoVo { +public class ExportDemoVo implements Serializable { + @Serial private static final long serialVersionUID = 1L; /** diff --git a/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/service/impl/ExportExcelServiceImpl.java b/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/service/impl/ExportExcelServiceImpl.java index ebb6ac688..69cf0a8af 100644 --- a/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/service/impl/ExportExcelServiceImpl.java +++ b/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/service/impl/ExportExcelServiceImpl.java @@ -5,7 +5,7 @@ import cn.hutool.core.util.StrUtil; import jakarta.servlet.http.HttpServletResponse; import lombok.Data; import lombok.RequiredArgsConstructor; -import org.dromara.common.core.enums.UserStatus; +import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.core.utils.StreamUtils; import org.dromara.common.excel.core.DropDownOptions; import org.dromara.common.excel.utils.ExcelUtil; @@ -35,7 +35,7 @@ public class ExportExcelServiceImpl implements IExportExcelService { // 模拟数据库中的一条数据 ExportDemoVo everyRowData = new ExportDemoVo(); everyRowData.setNickName("用户-" + i); - everyRowData.setUserStatus(UserStatus.OK.getCode()); + everyRowData.setUserStatus(SystemConstants.NORMAL); everyRowData.setGender("1"); everyRowData.setPhoneNumber(String.format("175%08d", i)); everyRowData.setEmail(String.format("175%08d", i) + "@163.com"); diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysDeptController.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysDeptController.java index 968bbe906..45b841850 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysDeptController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysDeptController.java @@ -3,7 +3,7 @@ package org.dromara.system.controller.system; import cn.dev33.satoken.annotation.SaCheckPermission; import cn.hutool.core.convert.Convert; import lombok.RequiredArgsConstructor; -import org.dromara.common.core.constant.UserConstants; +import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.core.domain.R; import org.dromara.common.core.utils.StringUtils; import org.dromara.common.log.annotation.Log; @@ -94,7 +94,7 @@ public class SysDeptController extends BaseController { return R.fail("修改部门'" + dept.getDeptName() + "'失败,部门名称已存在"); } else if (dept.getParentId().equals(deptId)) { return R.fail("修改部门'" + dept.getDeptName() + "'失败,上级部门不能是自己"); - } else if (StringUtils.equals(UserConstants.DEPT_DISABLE, dept.getStatus())) { + } else if (StringUtils.equals(SystemConstants.DISABLE, dept.getStatus())) { if (deptService.selectNormalChildrenDeptById(deptId) > 0) { return R.fail("该部门包含未停用的子部门!"); } else if (deptService.checkDeptExistUser(deptId)) { diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysMenuController.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysMenuController.java index e5daa0e12..d8cd335ce 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysMenuController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysMenuController.java @@ -4,8 +4,9 @@ import cn.dev33.satoken.annotation.SaCheckPermission; import cn.dev33.satoken.annotation.SaCheckRole; import cn.dev33.satoken.annotation.SaMode; import cn.hutool.core.lang.tree.Tree; +import lombok.RequiredArgsConstructor; +import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.core.constant.TenantConstants; -import org.dromara.common.core.constant.UserConstants; import org.dromara.common.core.domain.R; import org.dromara.common.core.utils.StringUtils; import org.dromara.common.log.annotation.Log; @@ -18,7 +19,6 @@ import org.dromara.system.domain.vo.MenuTreeSelectVo; import org.dromara.system.domain.vo.RouterVo; import org.dromara.system.domain.vo.SysMenuVo; import org.dromara.system.service.ISysMenuService; -import lombok.RequiredArgsConstructor; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -128,7 +128,7 @@ public class SysMenuController extends BaseController { public R add(@Validated @RequestBody SysMenuBo menu) { if (!menuService.checkMenuNameUnique(menu)) { return R.fail("新增菜单'" + menu.getMenuName() + "'失败,菜单名称已存在"); - } else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath())) { + } else if (SystemConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath())) { return R.fail("新增菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头"); } return toAjax(menuService.insertMenu(menu)); @@ -144,7 +144,7 @@ public class SysMenuController extends BaseController { public R edit(@Validated @RequestBody SysMenuBo menu) { if (!menuService.checkMenuNameUnique(menu)) { return R.fail("修改菜单'" + menu.getMenuName() + "'失败,菜单名称已存在"); - } else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath())) { + } else if (SystemConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath())) { return R.fail("修改菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头"); } else if (menu.getMenuId().equals(menu.getParentId())) { return R.fail("修改菜单'" + menu.getMenuName() + "'失败,上级菜单不能选择自己"); diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysPostController.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysPostController.java index 782bcfc55..5333a4aef 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysPostController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysPostController.java @@ -4,7 +4,7 @@ import cn.dev33.satoken.annotation.SaCheckPermission; import cn.hutool.core.util.ObjectUtil; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; -import org.dromara.common.core.constant.UserConstants; +import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.core.domain.R; import org.dromara.common.excel.utils.ExcelUtil; import org.dromara.common.log.annotation.Log; @@ -91,7 +91,7 @@ public class SysPostController extends BaseController { return R.fail("修改岗位'" + post.getPostName() + "'失败,岗位名称已存在"); } else if (!postService.checkPostCodeUnique(post)) { return R.fail("修改岗位'" + post.getPostName() + "'失败,岗位编码已存在"); - } else if (UserConstants.POST_DISABLE.equals(post.getStatus()) + } else if (SystemConstants.DISABLE.equals(post.getStatus()) && postService.countUserPostById(post.getPostId()) > 0) { return R.fail("该岗位下存在已分配用户,不能禁用!"); } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysUserController.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysUserController.java index 025800de9..d4cecbe14 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysUserController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysUserController.java @@ -8,7 +8,7 @@ import cn.hutool.core.util.ObjectUtil; import jakarta.servlet.http.HttpServletResponse; import jakarta.validation.constraints.NotNull; import lombok.RequiredArgsConstructor; -import org.dromara.common.core.constant.UserConstants; +import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.core.domain.R; import org.dromara.common.core.domain.model.LoginUser; import org.dromara.common.core.utils.StreamUtils; @@ -143,7 +143,7 @@ public class SysUserController extends BaseController { } } SysRoleBo roleBo = new SysRoleBo(); - roleBo.setStatus(UserConstants.ROLE_NORMAL); + roleBo.setStatus(SystemConstants.NORMAL); List roles = roleService.selectRoleList(roleBo); userInfoVo.setRoles(LoginHelper.isSuperAdmin(userId) ? roles : StreamUtils.filter(roles, r -> !r.isSuperAdmin())); return R.ok(userInfoVo); diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysDictData.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysDictData.java index 6884fc2db..9d83736e5 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysDictData.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysDictData.java @@ -2,10 +2,10 @@ package org.dromara.system.domain; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; -import org.dromara.common.core.constant.UserConstants; -import org.dromara.common.tenant.core.TenantEntity; import lombok.Data; import lombok.EqualsAndHashCode; +import org.dromara.common.core.constant.SystemConstants; +import org.dromara.common.tenant.core.TenantEntity; /** * 字典数据表 sys_dict_data @@ -65,7 +65,7 @@ public class SysDictData extends TenantEntity { private String remark; public boolean getDefault() { - return UserConstants.YES.equals(this.isDefault); + return SystemConstants.YES.equals(this.isDefault); } } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysMenu.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysMenu.java index 6b498a38e..2df55962b 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysMenu.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysMenu.java @@ -3,12 +3,12 @@ package org.dromara.system.domain; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; -import org.dromara.common.core.constant.Constants; -import org.dromara.common.core.constant.UserConstants; -import org.dromara.common.core.utils.StringUtils; -import org.dromara.common.mybatis.core.domain.BaseEntity; import lombok.Data; import lombok.EqualsAndHashCode; +import org.dromara.common.core.constant.Constants; +import org.dromara.common.core.constant.SystemConstants; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.mybatis.core.domain.BaseEntity; import java.util.ArrayList; import java.util.List; @@ -134,8 +134,8 @@ public class SysMenu extends BaseEntity { routerPath = innerLinkReplaceEach(routerPath); } // 非外链并且是一级目录(类型为目录) - if (0L == getParentId() && UserConstants.TYPE_DIR.equals(getMenuType()) - && UserConstants.NO_FRAME.equals(getIsFrame())) { + if (0L == getParentId() && SystemConstants.TYPE_DIR.equals(getMenuType()) + && SystemConstants.NO_FRAME.equals(getIsFrame())) { routerPath = "/" + this.path; } // 非外链并且是一级目录(类型为菜单) @@ -149,13 +149,13 @@ public class SysMenu extends BaseEntity { * 获取组件信息 */ public String getComponentInfo() { - String component = UserConstants.LAYOUT; + String component = SystemConstants.LAYOUT; if (StringUtils.isNotEmpty(this.component) && !isMenuFrame()) { component = this.component; } else if (StringUtils.isEmpty(this.component) && getParentId() != 0L && isInnerLink()) { - component = UserConstants.INNER_LINK; + component = SystemConstants.INNER_LINK; } else if (StringUtils.isEmpty(this.component) && isParentView()) { - component = UserConstants.PARENT_VIEW; + component = SystemConstants.PARENT_VIEW; } return component; } @@ -164,21 +164,21 @@ public class SysMenu extends BaseEntity { * 是否为菜单内部跳转 */ public boolean isMenuFrame() { - return getParentId() == 0L && UserConstants.TYPE_MENU.equals(menuType) && isFrame.equals(UserConstants.NO_FRAME); + return getParentId() == 0L && SystemConstants.TYPE_MENU.equals(menuType) && isFrame.equals(SystemConstants.NO_FRAME); } /** * 是否为内链组件 */ public boolean isInnerLink() { - return isFrame.equals(UserConstants.NO_FRAME) && StringUtils.ishttp(path); + return isFrame.equals(SystemConstants.NO_FRAME) && StringUtils.ishttp(path); } /** * 是否为parent_view组件 */ public boolean isParentView() { - return getParentId() != 0L && UserConstants.TYPE_DIR.equals(menuType); + return getParentId() != 0L && SystemConstants.TYPE_DIR.equals(menuType); } /** diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysUser.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysUser.java index 8dde40b35..4e603e551 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysUser.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysUser.java @@ -1,11 +1,11 @@ package org.dromara.system.domain; import com.baomidou.mybatisplus.annotation.*; -import org.dromara.common.core.constant.UserConstants; -import org.dromara.common.tenant.core.TenantEntity; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; +import org.dromara.common.core.constant.SystemConstants; +import org.dromara.common.tenant.core.TenantEntity; import java.util.Date; @@ -109,7 +109,7 @@ public class SysUser extends TenantEntity { } public boolean isSuperAdmin() { - return UserConstants.SUPER_ADMIN_ID.equals(this.userId); + return SystemConstants.SUPER_ADMIN_ID.equals(this.userId); } } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysRoleBo.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysRoleBo.java index 0c8b4dca9..3207bad1e 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysRoleBo.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysRoleBo.java @@ -7,7 +7,7 @@ import jakarta.validation.constraints.Size; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; -import org.dromara.common.core.constant.UserConstants; +import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.mybatis.core.domain.BaseEntity; import org.dromara.system.domain.SysRole; @@ -88,7 +88,7 @@ public class SysRoleBo extends BaseEntity { } public boolean isSuperAdmin() { - return UserConstants.SUPER_ADMIN_ID.equals(this.roleId); + return SystemConstants.SUPER_ADMIN_ID.equals(this.roleId); } } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysUserBo.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysUserBo.java index 7ad2759b2..2669a8179 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysUserBo.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysUserBo.java @@ -7,7 +7,7 @@ import jakarta.validation.constraints.Size; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; -import org.dromara.common.core.constant.UserConstants; +import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.core.xss.Xss; import org.dromara.common.mybatis.core.domain.BaseEntity; import org.dromara.system.domain.SysUser; @@ -113,7 +113,7 @@ public class SysUserBo extends BaseEntity { } public boolean isSuperAdmin() { - return UserConstants.SUPER_ADMIN_ID.equals(this.userId); + return SystemConstants.SUPER_ADMIN_ID.equals(this.userId); } } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysRoleVo.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysRoleVo.java index 1e5cd9ee6..ffb2c6d5a 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysRoleVo.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysRoleVo.java @@ -2,12 +2,12 @@ package org.dromara.system.domain.vo; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.alibaba.excel.annotation.ExcelProperty; -import org.dromara.common.core.constant.UserConstants; +import io.github.linpeilie.annotations.AutoMapper; +import lombok.Data; +import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.excel.annotation.ExcelDictFormat; import org.dromara.common.excel.convert.ExcelDictConvert; import org.dromara.system.domain.SysRole; -import io.github.linpeilie.annotations.AutoMapper; -import lombok.Data; import java.io.Serial; import java.io.Serializable; @@ -94,7 +94,7 @@ public class SysRoleVo implements Serializable { private boolean flag = false; public boolean isSuperAdmin() { - return UserConstants.SUPER_ADMIN_ID.equals(this.roleId); + return SystemConstants.SUPER_ADMIN_ID.equals(this.roleId); } } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysMenuMapper.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysMenuMapper.java index ac646c096..205413b3f 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysMenuMapper.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysMenuMapper.java @@ -3,11 +3,11 @@ package org.dromara.system.mapper; import com.baomidou.mybatisplus.core.conditions.Wrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Constants; -import org.dromara.common.core.constant.UserConstants; -import org.dromara.system.domain.SysMenu; -import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; -import org.dromara.system.domain.vo.SysMenuVo; import org.apache.ibatis.annotations.Param; +import org.dromara.common.core.constant.SystemConstants; +import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; +import org.dromara.system.domain.SysMenu; +import org.dromara.system.domain.vo.SysMenuVo; import java.util.List; @@ -49,8 +49,8 @@ public interface SysMenuMapper extends BaseMapperPlus { */ default List selectMenuTreeAll() { LambdaQueryWrapper lqw = new LambdaQueryWrapper() - .in(SysMenu::getMenuType, UserConstants.TYPE_DIR, UserConstants.TYPE_MENU) - .eq(SysMenu::getStatus, UserConstants.MENU_NORMAL) + .in(SysMenu::getMenuType, SystemConstants.TYPE_DIR, SystemConstants.TYPE_MENU) + .eq(SysMenu::getStatus, SystemConstants.NORMAL) .orderByAsc(SysMenu::getParentId) .orderByAsc(SysMenu::getOrderNum); return this.selectList(lqw); diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysConfigServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysConfigServiceImpl.java index 46526bd98..e8f64ec9b 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysConfigServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysConfigServiceImpl.java @@ -7,7 +7,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import org.dromara.common.core.constant.CacheNames; -import org.dromara.common.core.constant.UserConstants; +import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.service.ConfigService; import org.dromara.common.core.utils.MapstructUtils; @@ -173,7 +173,7 @@ public class SysConfigServiceImpl implements ISysConfigService, ConfigService { public void deleteConfigByIds(Long[] configIds) { for (Long configId : configIds) { SysConfig config = baseMapper.selectById(configId); - if (StringUtils.equals(UserConstants.YES, config.getConfigType())) { + if (StringUtils.equals(SystemConstants.YES, config.getConfigType())) { throw new ServiceException(String.format("内置参数【%1$s】不能删除 ", config.getConfigKey())); } CacheUtils.evict(CacheNames.SYS_CONFIG, config.getConfigKey()); 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 c17391674..44ff90e9c 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 @@ -9,14 +9,10 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import lombok.RequiredArgsConstructor; import org.dromara.common.core.constant.CacheNames; -import org.dromara.common.core.constant.UserConstants; +import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.service.DeptService; -import org.dromara.common.core.utils.MapstructUtils; -import org.dromara.common.core.utils.SpringUtils; -import org.dromara.common.core.utils.StringUtils; -import org.dromara.common.core.utils.StreamUtils; -import org.dromara.common.core.utils.TreeBuildUtils; +import org.dromara.common.core.utils.*; import org.dromara.common.mybatis.helper.DataBaseHelper; import org.dromara.common.redis.utils.CacheUtils; import org.dromara.common.satoken.utils.LoginHelper; @@ -71,7 +67,7 @@ public class SysDeptServiceImpl implements ISysDeptService, DeptService { @Override public List> selectDeptTreeList(SysDeptBo bo) { // 只查询未禁用部门 - bo.setStatus(UserConstants.DEPT_NORMAL); + bo.setStatus(SystemConstants.NORMAL); LambdaQueryWrapper lqw = buildQueryWrapper(bo); List depts = baseMapper.selectDeptList(lqw); return buildDeptTreeSelect(depts); @@ -79,7 +75,7 @@ public class SysDeptServiceImpl implements ISysDeptService, DeptService { private LambdaQueryWrapper buildQueryWrapper(SysDeptBo bo) { LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); - lqw.eq(SysDept::getDelFlag, UserConstants.DEL_FLAG_NORMAL); + lqw.eq(SysDept::getDelFlag, SystemConstants.NORMAL); lqw.eq(ObjectUtil.isNotNull(bo.getDeptId()), SysDept::getDeptId, bo.getDeptId()); lqw.eq(ObjectUtil.isNotNull(bo.getParentId()), SysDept::getParentId, bo.getParentId()); lqw.like(StringUtils.isNotBlank(bo.getDeptName()), SysDept::getDeptName, bo.getDeptName()); @@ -156,7 +152,7 @@ public class SysDeptServiceImpl implements ISysDeptService, DeptService { public List selectDeptByIds(List deptIds) { return baseMapper.selectDeptList(new LambdaQueryWrapper() .select(SysDept::getDeptId, SysDept::getDeptName, SysDept::getLeader) - .eq(SysDept::getStatus, UserConstants.DEPT_NORMAL) + .eq(SysDept::getStatus, SystemConstants.NORMAL) .in(CollUtil.isNotEmpty(deptIds), SysDept::getDeptId, deptIds)); } @@ -187,7 +183,7 @@ public class SysDeptServiceImpl implements ISysDeptService, DeptService { @Override public long selectNormalChildrenDeptById(Long deptId) { return baseMapper.selectCount(new LambdaQueryWrapper() - .eq(SysDept::getStatus, UserConstants.DEPT_NORMAL) + .eq(SysDept::getStatus, SystemConstants.NORMAL) .apply(DataBaseHelper.findInSet(deptId, "ancestors"))); } @@ -258,7 +254,7 @@ public class SysDeptServiceImpl implements ISysDeptService, DeptService { public int insertDept(SysDeptBo bo) { SysDept info = baseMapper.selectById(bo.getParentId()); // 如果父节点不为正常状态,则不允许新增子节点 - if (!UserConstants.DEPT_NORMAL.equals(info.getStatus())) { + if (!SystemConstants.NORMAL.equals(info.getStatus())) { throw new ServiceException("部门停用,不允许新增"); } SysDept dept = MapstructUtils.convert(bo, SysDept.class); @@ -294,8 +290,8 @@ public class SysDeptServiceImpl implements ISysDeptService, DeptService { dept.setAncestors(oldDept.getAncestors()); } int result = baseMapper.updateById(dept); - if (UserConstants.DEPT_NORMAL.equals(dept.getStatus()) && StringUtils.isNotEmpty(dept.getAncestors()) - && !StringUtils.equals(UserConstants.DEPT_NORMAL, dept.getAncestors())) { + if (SystemConstants.NORMAL.equals(dept.getStatus()) && StringUtils.isNotEmpty(dept.getAncestors()) + && !StringUtils.equals(SystemConstants.NORMAL, dept.getAncestors())) { // 如果该部门是启用状态,则启用该部门的所有上级部门 updateParentDeptStatusNormal(dept); } @@ -311,7 +307,7 @@ public class SysDeptServiceImpl implements ISysDeptService, DeptService { String ancestors = dept.getAncestors(); Long[] deptIds = Convert.toLongArray(ancestors); baseMapper.update(null, new LambdaUpdateWrapper() - .set(SysDept::getStatus, UserConstants.DEPT_NORMAL) + .set(SysDept::getStatus, SystemConstants.NORMAL) .in(SysDept::getDeptId, Arrays.asList(deptIds))); } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysMenuServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysMenuServiceImpl.java index af844c9bd..354d4b4d9 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysMenuServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysMenuServiceImpl.java @@ -8,7 +8,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import lombok.RequiredArgsConstructor; -import org.dromara.common.core.constant.UserConstants; +import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.core.utils.MapstructUtils; import org.dromara.common.core.utils.StreamUtils; import org.dromara.common.core.utils.StringUtils; @@ -196,7 +196,7 @@ public class SysMenuServiceImpl implements ISysMenuService { router.setQuery(menu.getQueryParam()); router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath())); List cMenus = menu.getChildren(); - if (CollUtil.isNotEmpty(cMenus) && UserConstants.TYPE_DIR.equals(menu.getMenuType())) { + if (CollUtil.isNotEmpty(cMenus) && SystemConstants.TYPE_DIR.equals(menu.getMenuType())) { router.setAlwaysShow(true); router.setRedirect("noRedirect"); router.setChildren(buildMenus(cMenus)); @@ -220,7 +220,7 @@ public class SysMenuServiceImpl implements ISysMenuService { String routerPath = SysMenu.innerLinkReplaceEach(menu.getPath()); String innerLinkName = StringUtils.capitalize(routerPath) + menu.getMenuId(); children.setPath(routerPath); - children.setComponent(UserConstants.INNER_LINK); + children.setComponent(SystemConstants.INNER_LINK); children.setName(innerLinkName); children.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), menu.getPath())); childrenList.add(children); 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 e3f4145b4..8643f0d92 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysPostServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysPostServiceImpl.java @@ -6,7 +6,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import lombok.RequiredArgsConstructor; -import org.dromara.common.core.constant.UserConstants; +import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.utils.MapstructUtils; import org.dromara.common.core.utils.StreamUtils; @@ -128,7 +128,7 @@ public class SysPostServiceImpl implements ISysPostService { public List selectPostByIds(List postIds) { return baseMapper.selectVoList(new LambdaQueryWrapper() .select(SysPost::getPostId, SysPost::getPostName, SysPost::getPostCode) - .eq(SysPost::getStatus, UserConstants.POST_NORMAL) + .eq(SysPost::getStatus, SystemConstants.NORMAL) .in(CollUtil.isNotEmpty(postIds), SysPost::getPostId, postIds)); } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysRoleServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysRoleServiceImpl.java index fee0a5b77..4148b7308 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysRoleServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysRoleServiceImpl.java @@ -12,8 +12,8 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import lombok.RequiredArgsConstructor; +import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.core.constant.TenantConstants; -import org.dromara.common.core.constant.UserConstants; import org.dromara.common.core.domain.model.LoginUser; import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.utils.MapstructUtils; @@ -72,7 +72,7 @@ public class SysRoleServiceImpl implements ISysRoleService { private Wrapper buildQueryWrapper(SysRoleBo bo) { Map params = bo.getParams(); QueryWrapper wrapper = Wrappers.query(); - wrapper.eq("r.del_flag", UserConstants.ROLE_NORMAL) + wrapper.eq("r.del_flag", SystemConstants.NORMAL) .eq(ObjectUtil.isNotNull(bo.getRoleId()), "r.role_id", bo.getRoleId()) .like(StringUtils.isNotBlank(bo.getRoleName()), "r.role_name", bo.getRoleName()) .eq(StringUtils.isNotBlank(bo.getStatus()), "r.status", bo.getStatus()) @@ -174,7 +174,7 @@ public class SysRoleServiceImpl implements ISysRoleService { @Override public List selectRoleByIds(List roleIds) { return baseMapper.selectRoleList(new QueryWrapper() - .eq("r.status", UserConstants.ROLE_NORMAL) + .eq("r.status", SystemConstants.NORMAL) .in(CollUtil.isNotEmpty(roleIds), "r.role_id", roleIds)); } @@ -294,7 +294,7 @@ public class SysRoleServiceImpl implements ISysRoleService { public int updateRole(SysRoleBo bo) { SysRole role = MapstructUtils.convert(bo, SysRole.class); - if (UserConstants.ROLE_DISABLE.equals(role.getStatus()) && this.countUserRoleByRoleId(role.getRoleId()) > 0) { + if (SystemConstants.DISABLE.equals(role.getStatus()) && this.countUserRoleByRoleId(role.getRoleId()) > 0) { throw new ServiceException("角色已分配,不能禁用!"); } // 修改角色信息 @@ -313,7 +313,7 @@ public class SysRoleServiceImpl implements ISysRoleService { */ @Override public int updateRoleStatus(Long roleId, String status) { - if (UserConstants.ROLE_DISABLE.equals(status) && this.countUserRoleByRoleId(roleId) > 0) { + if (SystemConstants.DISABLE.equals(status) && this.countUserRoleByRoleId(roleId) > 0) { throw new ServiceException("角色已分配,不能禁用!"); } return baseMapper.update(null, diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTenantPackageServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTenantPackageServiceImpl.java index d2a72f611..8d69e96ea 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTenantPackageServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTenantPackageServiceImpl.java @@ -6,7 +6,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import lombok.RequiredArgsConstructor; -import org.dromara.common.core.constant.TenantConstants; +import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.utils.MapstructUtils; import org.dromara.common.core.utils.StringUtils; @@ -59,7 +59,7 @@ public class SysTenantPackageServiceImpl implements ISysTenantPackageService { @Override public List selectList() { return baseMapper.selectVoList(new LambdaQueryWrapper() - .eq(SysTenantPackage::getStatus, TenantConstants.NORMAL)); + .eq(SysTenantPackage::getStatus, SystemConstants.NORMAL)); } /** diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTenantServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTenantServiceImpl.java index 747654982..7bfe989b9 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTenantServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTenantServiceImpl.java @@ -12,6 +12,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import lombok.RequiredArgsConstructor; import org.dromara.common.core.constant.CacheNames; import org.dromara.common.core.constant.Constants; +import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.core.constant.TenantConstants; import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.utils.MapstructUtils; @@ -231,7 +232,7 @@ public class SysTenantServiceImpl implements ISysTenantService { role.setRoleName(TenantConstants.TENANT_ADMIN_ROLE_NAME); role.setRoleKey(TenantConstants.TENANT_ADMIN_ROLE_KEY); role.setRoleSort(1); - role.setStatus(TenantConstants.NORMAL); + role.setStatus(SystemConstants.NORMAL); roleMapper.insert(role); Long roleId = role.getRoleId(); @@ -398,7 +399,7 @@ public class SysTenantServiceImpl implements ISysTenantService { // 获取所有租户编号 List tenantIds = baseMapper.selectObjs( new LambdaQueryWrapper().select(SysTenant::getTenantId) - .eq(SysTenant::getStatus, TenantConstants.NORMAL), x -> {return Convert.toStr(x);}); + .eq(SysTenant::getStatus, SystemConstants.NORMAL), x -> {return Convert.toStr(x);}); List saveTypeList = new ArrayList<>(); List saveDataList = new ArrayList<>(); Set set = new HashSet<>(); diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysUserServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysUserServiceImpl.java index cd69767cc..abb814c19 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysUserServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysUserServiceImpl.java @@ -14,7 +14,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.dromara.common.core.constant.CacheNames; -import org.dromara.common.core.constant.UserConstants; +import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.core.domain.dto.UserDTO; import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.service.UserService; @@ -80,7 +80,7 @@ public class SysUserServiceImpl implements ISysUserService, UserService { private Wrapper buildQueryWrapper(SysUserBo user) { Map params = user.getParams(); QueryWrapper wrapper = Wrappers.query(); - wrapper.eq("u.del_flag", UserConstants.USER_NORMAL) + wrapper.eq("u.del_flag", SystemConstants.NORMAL) .eq(ObjectUtil.isNotNull(user.getUserId()), "u.user_id", user.getUserId()) .like(StringUtils.isNotBlank(user.getUserName()), "u.user_name", user.getUserName()) .eq(StringUtils.isNotBlank(user.getStatus()), "u.status", user.getStatus()) @@ -108,7 +108,7 @@ public class SysUserServiceImpl implements ISysUserService, UserService { @Override public TableDataInfo selectAllocatedList(SysUserBo user, PageQuery pageQuery) { QueryWrapper wrapper = Wrappers.query(); - wrapper.eq("u.del_flag", UserConstants.USER_NORMAL) + wrapper.eq("u.del_flag", SystemConstants.NORMAL) .eq(ObjectUtil.isNotNull(user.getRoleId()), "r.role_id", user.getRoleId()) .like(StringUtils.isNotBlank(user.getUserName()), "u.user_name", user.getUserName()) .eq(StringUtils.isNotBlank(user.getStatus()), "u.status", user.getStatus()) @@ -128,7 +128,7 @@ public class SysUserServiceImpl implements ISysUserService, UserService { public TableDataInfo selectUnallocatedList(SysUserBo user, PageQuery pageQuery) { List userIds = userRoleMapper.selectUserIdsByRoleId(user.getRoleId()); QueryWrapper wrapper = Wrappers.query(); - wrapper.eq("u.del_flag", UserConstants.USER_NORMAL) + wrapper.eq("u.del_flag", SystemConstants.NORMAL) .and(w -> w.ne("r.role_id", user.getRoleId()).or().isNull("r.role_id")) .notIn(CollUtil.isNotEmpty(userIds), "u.user_id", userIds) .like(StringUtils.isNotBlank(user.getUserName()), "u.user_name", user.getUserName()) @@ -187,7 +187,7 @@ public class SysUserServiceImpl implements ISysUserService, UserService { public List selectUserByIds(List userIds, Long deptId) { return baseMapper.selectUserList(new LambdaQueryWrapper() .select(SysUser::getUserId, SysUser::getUserName, SysUser::getNickName) - .eq(SysUser::getStatus, UserConstants.USER_NORMAL) + .eq(SysUser::getStatus, SystemConstants.NORMAL) .eq(ObjectUtil.isNotNull(deptId), SysUser::getDeptId, deptId) .in(CollUtil.isNotEmpty(userIds), SysUser::getUserId, userIds)); } @@ -470,7 +470,7 @@ public class SysUserServiceImpl implements ISysUserService, UserService { if (ArrayUtil.isNotEmpty(roleIds)) { List roleList = new ArrayList<>(List.of(roleIds)); if (!LoginHelper.isSuperAdmin(userId)) { - roleList.remove(UserConstants.SUPER_ADMIN_ID); + roleList.remove(SystemConstants.SUPER_ADMIN_ID); } // 判断是否具有此角色的操作权限 List roles = roleMapper.selectRoleList( @@ -639,7 +639,7 @@ public class SysUserServiceImpl implements ISysUserService, UserService { } List list = baseMapper.selectVoList(new LambdaQueryWrapper() .select(SysUser::getUserId, SysUser::getUserName, SysUser::getNickName, SysUser::getEmail, SysUser::getPhonenumber) - .eq(SysUser::getStatus, UserConstants.USER_NORMAL) + .eq(SysUser::getStatus, SystemConstants.NORMAL) .in(SysUser::getUserId, userIds)); return BeanUtil.copyToList(list, UserDTO.class); } @@ -695,7 +695,7 @@ public class SysUserServiceImpl implements ISysUserService, UserService { } List list = baseMapper.selectVoList(new LambdaQueryWrapper() .select(SysUser::getUserId, SysUser::getUserName, SysUser::getNickName, SysUser::getEmail, SysUser::getPhonenumber) - .eq(SysUser::getStatus, UserConstants.USER_NORMAL) + .eq(SysUser::getStatus, SystemConstants.NORMAL) .in(SysUser::getDeptId, deptIds)); return BeanUtil.copyToList(list, UserDTO.class); } From 90328ae79b8b09865857475d5bfb6229908f3a79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Mon, 11 Nov 2024 10:26:24 +0800 Subject: [PATCH 033/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E9=80=BB?= =?UTF-8?q?=E8=BE=91=E5=88=A0=E9=99=A4=E7=8A=B6=E6=80=81=E6=94=B9=E4=B8=BA?= =?UTF-8?q?1=20=E9=81=BF=E5=85=8D=E8=AF=AF=E8=A7=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/common-mybatis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/resources/common-mybatis.yml b/ruoyi-common/ruoyi-common-mybatis/src/main/resources/common-mybatis.yml index f5dc63758..14662e16a 100644 --- a/ruoyi-common/ruoyi-common-mybatis/src/main/resources/common-mybatis.yml +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/resources/common-mybatis.yml @@ -24,8 +24,8 @@ mybatis-plus: # 主键类型 # AUTO 自增 NONE 空 INPUT 用户输入 ASSIGN_ID 雪花 ASSIGN_UUID 唯一 UUID idType: ASSIGN_ID - # 逻辑已删除值(框架表均使用此值 禁止随意修改) - logicDeleteValue: 2 + # 逻辑已删除值(可按需求随意修改) + logicDeleteValue: 1 # 逻辑未删除值 logicNotDeleteValue: 0 insertStrategy: NOT_NULL From 1b8c9fdaa98d2c28445f58d694a10359199526a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Mon, 11 Nov 2024 10:45:00 +0800 Subject: [PATCH 034/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E7=94=9F=E6=88=90=E5=99=A8=E6=95=B0=E5=AD=97=E7=B1=BB?= =?UTF-8?q?=E5=88=AB=E5=88=A4=E6=96=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/dromara/generator/util/GenUtils.java | 23 +++---------------- 1 file changed, 3 insertions(+), 20 deletions(-) diff --git a/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/util/GenUtils.java b/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/util/GenUtils.java index c9357c0c4..676896250 100644 --- a/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/util/GenUtils.java +++ b/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/util/GenUtils.java @@ -37,8 +37,6 @@ public class GenUtils { public static void initColumnField(GenTableColumn column, GenTable table) { String dataType = getDbType(column.getColumnType()); String columnName = column.getColumnName(); - column.setTableId(table.getTableId()); - column.setCreateBy(table.getCreateBy()); // 设置java字段名 column.setJavaField(StringUtils.toCamelCase(columnName)); // 设置默认类型 @@ -55,20 +53,9 @@ public class GenUtils { column.setHtmlType(GenConstants.HTML_DATETIME); } else if (arraysContains(GenConstants.COLUMNTYPE_NUMBER, dataType)) { column.setHtmlType(GenConstants.HTML_INPUT); - - // 如果是浮点型 统一用BigDecimal - String[] str = StringUtils.split(StringUtils.substringBetween(column.getColumnType(), "(", ")"), StringUtils.SEPARATOR); - if (str != null && str.length == 2 && Integer.parseInt(str[1]) > 0) { - column.setJavaType(GenConstants.TYPE_BIGDECIMAL); - } - // 如果是整形 - else if (str != null && str.length == 1 && Integer.parseInt(str[0]) <= 10) { - column.setJavaType(GenConstants.TYPE_INTEGER); - } - // 长整形 - else { - column.setJavaType(GenConstants.TYPE_LONG); - } + // 数据库的数字字段与java不匹配 且很多数据库的数字字段很模糊 例如oracle只有number没有细分 + // 所以默认数字类型全为Long可在界面上自行编辑想要的类型 有什么特殊需求也可以在这里特殊处理 + column.setJavaType(GenConstants.TYPE_LONG); } // BO对象 默认插入勾选 @@ -79,10 +66,6 @@ public class GenUtils { if (!arraysContains(GenConstants.COLUMNNAME_NOT_EDIT, columnName)) { column.setIsEdit(GenConstants.REQUIRE); } - // BO对象 默认是否必填勾选 - if (!arraysContains(GenConstants.COLUMNNAME_NOT_EDIT, columnName)) { - column.setIsRequired(GenConstants.REQUIRE); - } // VO对象 默认返回勾选 if (!arraysContains(GenConstants.COLUMNNAME_NOT_LIST, columnName)) { column.setIsList(GenConstants.REQUIRE); From 5d61782a6c1441723c3fc44f97b074b6635fd3a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A7=8B=E8=BE=9E=E6=9C=AA=E5=AF=92?= <545073804@qq.com> Date: Mon, 11 Nov 2024 03:40:48 +0000 Subject: [PATCH 035/175] =?UTF-8?q?add=20=E6=96=B0=E5=A2=9E=20=E5=AF=B9?= =?UTF-8?q?=E8=B1=A1=E5=B7=A5=E5=85=B7=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 秋辞未寒 <545073804@qq.com> --- .../common/core/utils/ObjectUtils.java | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/ObjectUtils.java diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/ObjectUtils.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/ObjectUtils.java new file mode 100644 index 000000000..e0de69a98 --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/ObjectUtils.java @@ -0,0 +1,42 @@ +package org.dromara.common.core.utils; + +import cn.hutool.core.util.ObjectUtil; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +import java.util.function.Function; + +/** + * 对象工具类 + * + * @author 秋辞未寒 + */ +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class ObjectUtils extends ObjectUtil { + + /** + * 如果对象不为空,则获取对象中的某个字段 + *

+ * 例: + * + *

public class User { + *

private String name; + *

// 省略 getter/setter + *

} + * + * + *

User user = userService.queryById(userId); + *

String name = ObjectUtils.notNullGetter(user,User::getName); + * + * @param obj 对象 + * @param func 获取方法 + * @return 对象字段 + */ + public static E notNullGetter(T obj, Function func) { + if (isNotNull(obj) && isNotNull(func)) { + return func.apply(obj); + } + return null; + } + +} From a82ed1e9ddf3763108e37864c400250e8bc75ef6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Mon, 11 Nov 2024 13:30:58 +0800 Subject: [PATCH 036/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E6=9D=83=E9=99=90=E6=9F=A5=E8=AF=A2=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E7=BC=93=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/core/constant/CacheNames.java | 10 ++++++ .../common/core/utils/ObjectUtils.java | 32 +++++++++++-------- .../service/impl/SysDataScopeServiceImpl.java | 4 +++ .../service/impl/SysDeptServiceImpl.java | 12 +++++-- .../service/impl/SysRoleServiceImpl.java | 4 +++ 5 files changed, 46 insertions(+), 16 deletions(-) diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/CacheNames.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/CacheNames.java index 28ba17739..bf8efc550 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/CacheNames.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/CacheNames.java @@ -60,6 +60,16 @@ public interface CacheNames { */ String SYS_OSS = "sys_oss#30d"; + /** + * 角色自定义权限 + */ + String SYS_ROLE_CUSTOM = "sys_role_custom#30d"; + + /** + * 部门及以下权限 + */ + String SYS_DEPT_AND_CHILD = "sys_dept_and_child#30d"; + /** * OSS配置 */ diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/ObjectUtils.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/ObjectUtils.java index e0de69a98..c86b55b71 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/ObjectUtils.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/ObjectUtils.java @@ -15,28 +15,32 @@ import java.util.function.Function; public class ObjectUtils extends ObjectUtil { /** - * 如果对象不为空,则获取对象中的某个字段 - *

- * 例: - * - *

public class User { - *

private String name; - *

// 省略 getter/setter - *

} - * - * - *

User user = userService.queryById(userId); - *

String name = ObjectUtils.notNullGetter(user,User::getName); - * + * 如果对象不为空,则获取对象中的某个字段 ObjectUtils.notNullGetter(user, User::getName); + * * @param obj 对象 * @param func 获取方法 * @return 对象字段 */ - public static E notNullGetter(T obj, Function func) { + public static E notNullGetter(T obj, Function func) { if (isNotNull(obj) && isNotNull(func)) { return func.apply(obj); } return null; } + /** + * 如果对象不为空,则获取对象中的某个字段 ObjectUtils.notNullGetter(user, User::getName, ""); + * + * @param obj 对象 + * @param func 获取方法 + * @param defaultValue 默认值 + * @return 对象字段 + */ + public static E notNullGetter(T obj, Function func, E defaultValue) { + if (isNotNull(obj) && isNotNull(func)) { + return func.apply(obj); + } + return defaultValue; + } + } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDataScopeServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDataScopeServiceImpl.java index 0c07f7f67..470646f35 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDataScopeServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDataScopeServiceImpl.java @@ -5,12 +5,14 @@ import cn.hutool.core.convert.Convert; import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import lombok.RequiredArgsConstructor; +import org.dromara.common.core.constant.CacheNames; import org.dromara.common.core.utils.StreamUtils; import org.dromara.system.domain.SysDept; import org.dromara.system.domain.SysRoleDept; import org.dromara.system.mapper.SysDeptMapper; import org.dromara.system.mapper.SysRoleDeptMapper; import org.dromara.system.service.ISysDataScopeService; +import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import java.util.List; @@ -36,6 +38,7 @@ public class SysDataScopeServiceImpl implements ISysDataScopeService { * @param roleId 角色Id * @return 部门Id组 */ + @Cacheable(cacheNames = CacheNames.SYS_ROLE_CUSTOM, key = "#roleId") @Override public String getRoleCustom(Long roleId) { if (ObjectUtil.isNull(roleId)) { @@ -57,6 +60,7 @@ public class SysDataScopeServiceImpl implements ISysDataScopeService { * @param deptId 部门Id * @return 部门Id组 */ + @Cacheable(cacheNames = CacheNames.SYS_DEPT_AND_CHILD, key = "#deptId") @Override public String getDeptAndChild(Long deptId) { if (ObjectUtil.isNull(deptId)) { 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 44ff90e9c..3c7bf5e36 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 @@ -27,6 +27,7 @@ import org.dromara.system.mapper.SysUserMapper; import org.dromara.system.service.ISysDeptService; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.Cacheable; +import org.springframework.cache.annotation.Caching; import org.springframework.stereotype.Service; import java.util.ArrayList; @@ -250,6 +251,7 @@ public class SysDeptServiceImpl implements ISysDeptService, DeptService { * @param bo 部门信息 * @return 结果 */ + @CacheEvict(cacheNames = CacheNames.SYS_DEPT_AND_CHILD, allEntries = true) @Override public int insertDept(SysDeptBo bo) { SysDept info = baseMapper.selectById(bo.getParentId()); @@ -268,7 +270,10 @@ public class SysDeptServiceImpl implements ISysDeptService, DeptService { * @param bo 部门信息 * @return 结果 */ - @CacheEvict(cacheNames = CacheNames.SYS_DEPT, key = "#bo.deptId") + @Caching(evict = { + @CacheEvict(cacheNames = CacheNames.SYS_DEPT, key = "#bo.deptId"), + @CacheEvict(cacheNames = CacheNames.SYS_DEPT_AND_CHILD, allEntries = true) + }) @Override public int updateDept(SysDeptBo bo) { SysDept dept = MapstructUtils.convert(bo, SysDept.class); @@ -341,7 +346,10 @@ public class SysDeptServiceImpl implements ISysDeptService, DeptService { * @param deptId 部门ID * @return 结果 */ - @CacheEvict(cacheNames = CacheNames.SYS_DEPT, key = "#deptId") + @Caching(evict = { + @CacheEvict(cacheNames = CacheNames.SYS_DEPT, key = "#deptId"), + @CacheEvict(cacheNames = CacheNames.SYS_DEPT_AND_CHILD, key = "#deptId") + }) @Override public int deleteDeptById(Long deptId) { return baseMapper.deleteById(deptId); diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysRoleServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysRoleServiceImpl.java index 4148b7308..c11b1ac1b 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysRoleServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysRoleServiceImpl.java @@ -12,6 +12,7 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import lombok.RequiredArgsConstructor; +import org.dromara.common.core.constant.CacheNames; import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.core.constant.TenantConstants; import org.dromara.common.core.domain.model.LoginUser; @@ -33,6 +34,7 @@ import org.dromara.system.mapper.SysRoleMapper; import org.dromara.system.mapper.SysRoleMenuMapper; import org.dromara.system.mapper.SysUserRoleMapper; import org.dromara.system.service.ISysRoleService; +import org.springframework.cache.annotation.CacheEvict; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -328,6 +330,7 @@ public class SysRoleServiceImpl implements ISysRoleService { * @param bo 角色信息 * @return 结果 */ + @CacheEvict(cacheNames = CacheNames.SYS_ROLE_CUSTOM, key = "#bo.roleId") @Override @Transactional(rollbackFor = Exception.class) public int authDataScope(SysRoleBo bo) { @@ -404,6 +407,7 @@ public class SysRoleServiceImpl implements ISysRoleService { * @param roleIds 需要删除的角色ID * @return 结果 */ + @CacheEvict(cacheNames = CacheNames.SYS_ROLE_CUSTOM, allEntries = true) @Override @Transactional(rollbackFor = Exception.class) public int deleteRoleByIds(Long[] roleIds) { From b4678b74ab4de1f42580993985c1dfade485fe41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Mon, 11 Nov 2024 13:52:16 +0800 Subject: [PATCH 037/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E4=BD=BF?= =?UTF-8?q?=E7=94=A8ObjectUtils=E6=96=B0=E5=A2=9E=E6=96=B9=E6=B3=95?= =?UTF-8?q?=E5=B0=81=E8=A3=85=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/core/utils/ObjectUtils.java | 29 ++++++++++++++++++- .../common/encrypt/core/EncryptorManager.java | 7 ++--- .../handler/InjectionMetaObjectHandler.java | 12 +++----- .../service/impl/SysConfigServiceImpl.java | 8 ++--- .../service/impl/SysDeptServiceImpl.java | 2 +- .../service/impl/SysDictDataServiceImpl.java | 3 +- .../service/impl/SysNoticeServiceImpl.java | 4 +-- .../service/impl/SysOssConfigServiceImpl.java | 3 +- .../service/impl/SysUserServiceImpl.java | 13 ++++----- 9 files changed, 49 insertions(+), 32 deletions(-) diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/ObjectUtils.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/ObjectUtils.java index c86b55b71..82faf2c57 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/ObjectUtils.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/ObjectUtils.java @@ -29,7 +29,7 @@ public class ObjectUtils extends ObjectUtil { } /** - * 如果对象不为空,则获取对象中的某个字段 ObjectUtils.notNullGetter(user, User::getName, ""); + * 如果对象不为空,则获取对象中的某个字段,否则返回默认值 * * @param obj 对象 * @param func 获取方法 @@ -43,4 +43,31 @@ public class ObjectUtils extends ObjectUtil { return defaultValue; } + /** + * 如果值不为空,则返回值 + * + * @param obj 对象 + * @return 对象字段 + */ + public static T notNull(T obj) { + if (isNotNull(obj)) { + return obj; + } + return null; + } + + /** + * 如果值不为空,则返回值,否则返回默认值 + * + * @param obj 对象 + * @param defaultValue 默认值 + * @return 对象字段 + */ + public static T notNull(T obj, T defaultValue) { + if (isNotNull(obj)) { + return obj; + } + return defaultValue; + } + } diff --git a/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/core/EncryptorManager.java b/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/core/EncryptorManager.java index 2d795e074..b5f194d76 100644 --- a/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/core/EncryptorManager.java +++ b/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/core/EncryptorManager.java @@ -1,11 +1,11 @@ package org.dromara.common.encrypt.core; import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ReflectUtil; import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.ibatis.io.Resources; +import org.dromara.common.core.utils.ObjectUtils; import org.dromara.common.core.utils.StringUtils; import org.dromara.common.encrypt.annotation.EncryptField; import org.springframework.context.ConfigurableApplicationContext; @@ -58,10 +58,7 @@ public class EncryptorManager { * 获取类加密字段缓存 */ public Set getFieldCache(Class sourceClazz) { - if (ObjectUtil.isNotNull(fieldCache)) { - return fieldCache.get(sourceClazz); - } - return null; + return ObjectUtils.notNullGetter(fieldCache, f -> f.get(sourceClazz)); } /** diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/InjectionMetaObjectHandler.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/InjectionMetaObjectHandler.java index 7d44d2648..85ef2e97a 100644 --- a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/InjectionMetaObjectHandler.java +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/InjectionMetaObjectHandler.java @@ -7,6 +7,7 @@ import lombok.extern.slf4j.Slf4j; import org.apache.ibatis.reflection.MetaObject; import org.dromara.common.core.domain.model.LoginUser; import org.dromara.common.core.exception.ServiceException; +import org.dromara.common.core.utils.ObjectUtils; import org.dromara.common.mybatis.core.domain.BaseEntity; import org.dromara.common.satoken.utils.LoginHelper; @@ -31,8 +32,7 @@ public class InjectionMetaObjectHandler implements MetaObjectHandler { try { if (ObjectUtil.isNotNull(metaObject) && metaObject.getOriginalObject() instanceof BaseEntity baseEntity) { // 获取当前时间作为创建时间和更新时间,如果创建时间不为空,则使用创建时间,否则使用当前时间 - Date current = ObjectUtil.isNotNull(baseEntity.getCreateTime()) - ? baseEntity.getCreateTime() : new Date(); + Date current = ObjectUtils.notNull(baseEntity.getCreateTime(), new Date()); baseEntity.setCreateTime(current); baseEntity.setUpdateTime(current); @@ -44,8 +44,7 @@ public class InjectionMetaObjectHandler implements MetaObjectHandler { // 填充创建人、更新人和创建部门信息 baseEntity.setCreateBy(userId); baseEntity.setUpdateBy(userId); - baseEntity.setCreateDept(ObjectUtil.isNotNull(baseEntity.getCreateDept()) - ? baseEntity.getCreateDept() : loginUser.getDeptId()); + baseEntity.setCreateDept(ObjectUtils.notNull(baseEntity.getCreateDept(), loginUser.getDeptId())); } } } else { @@ -72,10 +71,7 @@ public class InjectionMetaObjectHandler implements MetaObjectHandler { baseEntity.setUpdateTime(current); // 获取当前登录用户的ID,并填充更新人信息 - Long userId = LoginHelper.getUserId(); - if (ObjectUtil.isNotNull(userId)) { - baseEntity.setUpdateBy(userId); - } + baseEntity.setUpdateBy(ObjectUtils.notNull(LoginHelper.getUserId())); } else { this.strictUpdateFill(metaObject, "updateTime", Date.class, new Date()); } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysConfigServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysConfigServiceImpl.java index e8f64ec9b..d92647c44 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysConfigServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysConfigServiceImpl.java @@ -11,6 +11,7 @@ import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.service.ConfigService; import org.dromara.common.core.utils.MapstructUtils; +import org.dromara.common.core.utils.ObjectUtils; import org.dromara.common.core.utils.SpringUtils; import org.dromara.common.core.utils.StringUtils; import org.dromara.common.mybatis.core.page.PageQuery; @@ -72,10 +73,7 @@ public class SysConfigServiceImpl implements ISysConfigService, ConfigService { public String selectConfigByKey(String configKey) { SysConfig retConfig = baseMapper.selectOne(new LambdaQueryWrapper() .eq(SysConfig::getConfigKey, configKey)); - if (ObjectUtil.isNotNull(retConfig)) { - return retConfig.getConfigValue(); - } - return StringUtils.EMPTY; + return ObjectUtils.notNullGetter(retConfig, SysConfig::getConfigValue, StringUtils.EMPTY); } /** @@ -197,7 +195,7 @@ public class SysConfigServiceImpl implements ISysConfigService, ConfigService { */ @Override public boolean checkConfigKeyUnique(SysConfigBo config) { - long configId = ObjectUtil.isNull(config.getConfigId()) ? -1L : config.getConfigId(); + long configId = ObjectUtils.notNull(config.getConfigId(), -1L); SysConfig info = baseMapper.selectOne(new LambdaQueryWrapper().eq(SysConfig::getConfigKey, config.getConfigKey())); if (ObjectUtil.isNotNull(info) && info.getConfigId() != configId) { return false; diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDeptServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDeptServiceImpl.java index 3c7bf5e36..a3f0b6ffc 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 @@ -145,7 +145,7 @@ public class SysDeptServiceImpl implements ISysDeptService, DeptService { } SysDeptVo parentDept = baseMapper.selectVoOne(new LambdaQueryWrapper() .select(SysDept::getDeptName).eq(SysDept::getDeptId, dept.getParentId())); - dept.setParentName(ObjectUtil.isNotNull(parentDept) ? parentDept.getDeptName() : null); + dept.setParentName(ObjectUtils.notNullGetter(parentDept, SysDeptVo::getDeptName)); return dept; } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDictDataServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDictDataServiceImpl.java index 1ab0fafd1..e44fdbc29 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDictDataServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDictDataServiceImpl.java @@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import org.dromara.common.core.constant.CacheNames; import org.dromara.common.core.utils.MapstructUtils; +import org.dromara.common.core.utils.ObjectUtils; import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.system.domain.SysDictData; import org.dromara.common.mybatis.core.page.TableDataInfo; @@ -144,7 +145,7 @@ public class SysDictDataServiceImpl implements ISysDictDataService { */ @Override public boolean checkDictDataUnique(SysDictDataBo dict) { - Long dictCode = ObjectUtil.isNull(dict.getDictCode()) ? -1L : dict.getDictCode(); + Long dictCode = ObjectUtils.notNull(dict.getDictCode(), -1L); SysDictData entity = baseMapper.selectOne(new LambdaQueryWrapper() .eq(SysDictData::getDictType, dict.getDictType()).eq(SysDictData::getDictValue, dict.getDictValue())); if (ObjectUtil.isNotNull(entity) && !dictCode.equals(entity.getDictCode())) { diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysNoticeServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysNoticeServiceImpl.java index db63e61d0..19a3ff59a 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysNoticeServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysNoticeServiceImpl.java @@ -1,10 +1,10 @@ package org.dromara.system.service.impl; -import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import org.dromara.common.core.utils.MapstructUtils; +import org.dromara.common.core.utils.ObjectUtils; import org.dromara.common.core.utils.StringUtils; import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.TableDataInfo; @@ -70,7 +70,7 @@ public class SysNoticeServiceImpl implements ISysNoticeService { lqw.eq(StringUtils.isNotBlank(bo.getNoticeType()), SysNotice::getNoticeType, bo.getNoticeType()); if (StringUtils.isNotBlank(bo.getCreateByName())) { SysUserVo sysUser = userMapper.selectVoOne(new LambdaQueryWrapper().eq(SysUser::getUserName, bo.getCreateByName())); - lqw.eq(SysNotice::getCreateBy, ObjectUtil.isNotNull(sysUser) ? sysUser.getUserId() : null); + lqw.eq(SysNotice::getCreateBy, ObjectUtils.notNullGetter(sysUser, SysUserVo::getUserId)); } lqw.orderByAsc(SysNotice::getNoticeId); return lqw; diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssConfigServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssConfigServiceImpl.java index a1eefcefd..a67b04ea9 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssConfigServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssConfigServiceImpl.java @@ -11,6 +11,7 @@ import lombok.extern.slf4j.Slf4j; import org.dromara.common.core.constant.CacheNames; import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.utils.MapstructUtils; +import org.dromara.common.core.utils.ObjectUtils; import org.dromara.common.core.utils.StringUtils; import org.dromara.common.json.utils.JsonUtils; import org.dromara.common.mybatis.core.page.PageQuery; @@ -147,7 +148,7 @@ public class SysOssConfigServiceImpl implements ISysOssConfigService { * 判断configKey是否唯一 */ private boolean checkConfigKeyUnique(SysOssConfig sysOssConfig) { - long ossConfigId = ObjectUtil.isNull(sysOssConfig.getOssConfigId()) ? -1L : sysOssConfig.getOssConfigId(); + long ossConfigId = ObjectUtils.notNull(sysOssConfig.getOssConfigId(), -1L); SysOssConfig info = baseMapper.selectOne(new LambdaQueryWrapper() .select(SysOssConfig::getOssConfigId, SysOssConfig::getConfigKey) .eq(SysOssConfig::getConfigKey, sysOssConfig.getConfigKey())); diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysUserServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysUserServiceImpl.java index abb814c19..4b5758763 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 @@ -18,10 +18,7 @@ import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.core.domain.dto.UserDTO; import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.service.UserService; -import org.dromara.common.core.utils.MapstructUtils; -import org.dromara.common.core.utils.SpringUtils; -import org.dromara.common.core.utils.StreamUtils; -import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.core.utils.*; import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.satoken.utils.LoginHelper; @@ -565,7 +562,7 @@ public class SysUserServiceImpl implements ISysUserService, UserService { public String selectUserNameById(Long userId) { SysUser sysUser = baseMapper.selectOne(new LambdaQueryWrapper() .select(SysUser::getUserName).eq(SysUser::getUserId, userId)); - return ObjectUtil.isNull(sysUser) ? null : sysUser.getUserName(); + return ObjectUtils.notNullGetter(sysUser, SysUser::getUserName); } /** @@ -579,7 +576,7 @@ public class SysUserServiceImpl implements ISysUserService, UserService { public String selectNicknameById(Long userId) { SysUser sysUser = baseMapper.selectOne(new LambdaQueryWrapper() .select(SysUser::getNickName).eq(SysUser::getUserId, userId)); - return ObjectUtil.isNull(sysUser) ? null : sysUser.getNickName(); + return ObjectUtils.notNullGetter(sysUser, SysUser::getNickName); } /** @@ -610,7 +607,7 @@ public class SysUserServiceImpl implements ISysUserService, UserService { public String selectPhonenumberById(Long userId) { SysUser sysUser = baseMapper.selectOne(new LambdaQueryWrapper() .select(SysUser::getPhonenumber).eq(SysUser::getUserId, userId)); - return ObjectUtil.isNull(sysUser) ? null : sysUser.getPhonenumber(); + return ObjectUtils.notNullGetter(sysUser, SysUser::getPhonenumber); } /** @@ -623,7 +620,7 @@ public class SysUserServiceImpl implements ISysUserService, UserService { public String selectEmailById(Long userId) { SysUser sysUser = baseMapper.selectOne(new LambdaQueryWrapper() .select(SysUser::getEmail).eq(SysUser::getUserId, userId)); - return ObjectUtil.isNull(sysUser) ? null : sysUser.getEmail(); + return ObjectUtils.notNullGetter(sysUser, SysUser::getEmail); } /** From 63d22b9b3386e397284f62cdca4d98804b03b2ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Mon, 11 Nov 2024 13:58:29 +0800 Subject: [PATCH 038/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E8=A7=92?= =?UTF-8?q?=E8=89=B2=E5=88=A0=E9=99=A4=E6=B8=85=E7=90=86=E7=BC=93=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/org/dromara/system/service/impl/SysRoleServiceImpl.java | 1 + 1 file changed, 1 insertion(+) diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysRoleServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysRoleServiceImpl.java index c11b1ac1b..cbca57e5d 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysRoleServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysRoleServiceImpl.java @@ -391,6 +391,7 @@ public class SysRoleServiceImpl implements ISysRoleService { * @param roleId 角色ID * @return 结果 */ + @CacheEvict(cacheNames = CacheNames.SYS_ROLE_CUSTOM, key = "#roleId") @Override @Transactional(rollbackFor = Exception.class) public int deleteRoleById(Long roleId) { From 5c66f3b90c6cd9411f78fe28990175c2102fa0b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Tue, 12 Nov 2024 10:37:51 +0800 Subject: [PATCH 039/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E8=84=B1=E6=95=8F=E4=BC=A0=E5=A4=9A=E8=A7=92=E8=89=B2?= =?UTF-8?q?=E5=A4=9A=E6=9D=83=E9=99=90=E6=A0=87=E8=AF=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/sensitive/annotation/Sensitive.java | 10 ++++++++-- .../common/sensitive/core/SensitiveService.java | 2 +- .../common/sensitive/handler/SensitiveHandler.java | 4 ++-- .../service/impl/SysSensitiveServiceImpl.java | 14 +++++++------- 4 files changed, 18 insertions(+), 12 deletions(-) diff --git a/ruoyi-common/ruoyi-common-sensitive/src/main/java/org/dromara/common/sensitive/annotation/Sensitive.java b/ruoyi-common/ruoyi-common-sensitive/src/main/java/org/dromara/common/sensitive/annotation/Sensitive.java index 1dfc896ff..6940966b5 100644 --- a/ruoyi-common/ruoyi-common-sensitive/src/main/java/org/dromara/common/sensitive/annotation/Sensitive.java +++ b/ruoyi-common/ruoyi-common-sensitive/src/main/java/org/dromara/common/sensitive/annotation/Sensitive.java @@ -22,7 +22,13 @@ import java.lang.annotation.Target; public @interface Sensitive { SensitiveStrategy strategy(); - String roleKey() default ""; + /** + * 角色标识符 多个角色满足一个即可 + */ + String[] roleKey(); - String perms() default ""; + /** + * 权限标识符 多个权限满足一个即可 + */ + String[] perms(); } diff --git a/ruoyi-common/ruoyi-common-sensitive/src/main/java/org/dromara/common/sensitive/core/SensitiveService.java b/ruoyi-common/ruoyi-common-sensitive/src/main/java/org/dromara/common/sensitive/core/SensitiveService.java index 7b5264b87..03a7f9c75 100644 --- a/ruoyi-common/ruoyi-common-sensitive/src/main/java/org/dromara/common/sensitive/core/SensitiveService.java +++ b/ruoyi-common/ruoyi-common-sensitive/src/main/java/org/dromara/common/sensitive/core/SensitiveService.java @@ -13,6 +13,6 @@ public interface SensitiveService { /** * 是否脱敏 */ - boolean isSensitive(String roleKey, String perms); + boolean isSensitive(String[] roleKey, String[] perms); } diff --git a/ruoyi-common/ruoyi-common-sensitive/src/main/java/org/dromara/common/sensitive/handler/SensitiveHandler.java b/ruoyi-common/ruoyi-common-sensitive/src/main/java/org/dromara/common/sensitive/handler/SensitiveHandler.java index c76c83a98..d454724d7 100644 --- a/ruoyi-common/ruoyi-common-sensitive/src/main/java/org/dromara/common/sensitive/handler/SensitiveHandler.java +++ b/ruoyi-common/ruoyi-common-sensitive/src/main/java/org/dromara/common/sensitive/handler/SensitiveHandler.java @@ -26,8 +26,8 @@ import java.util.Objects; public class SensitiveHandler extends JsonSerializer implements ContextualSerializer { private SensitiveStrategy strategy; - private String roleKey; - private String perms; + private String[] roleKey; + private String[] perms; @Override public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException { diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysSensitiveServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysSensitiveServiceImpl.java index 5f4d121b1..8a0d45ef3 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysSensitiveServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysSensitiveServiceImpl.java @@ -1,7 +1,7 @@ package org.dromara.system.service.impl; import cn.dev33.satoken.stp.StpUtil; -import org.dromara.common.core.utils.StringUtils; +import cn.hutool.core.util.ArrayUtil; import org.dromara.common.satoken.utils.LoginHelper; import org.dromara.common.sensitive.core.SensitiveService; import org.dromara.common.tenant.helper.TenantHelper; @@ -22,19 +22,19 @@ public class SysSensitiveServiceImpl implements SensitiveService { * 是否脱敏 */ @Override - public boolean isSensitive(String roleKey, String perms) { + public boolean isSensitive(String[] roleKey, String[] perms) { if (!LoginHelper.isLogin()) { return true; } - boolean roleExist = StringUtils.isNotBlank(roleKey); - boolean permsExist = StringUtils.isNotBlank(perms); + boolean roleExist = ArrayUtil.isNotEmpty(roleKey); + boolean permsExist = ArrayUtil.isNotEmpty(perms); if (roleExist && permsExist) { - if (StpUtil.hasRole(roleKey) && StpUtil.hasPermission(perms)) { + if (StpUtil.hasRoleOr(roleKey) && StpUtil.hasPermissionOr(perms)) { return false; } - } else if (roleExist && StpUtil.hasRole(roleKey)) { + } else if (roleExist && StpUtil.hasRoleOr(roleKey)) { return false; - } else if (permsExist && StpUtil.hasPermission(perms)) { + } else if (permsExist && StpUtil.hasPermissionOr(perms)) { return false; } From 0d5fe5d91e035ec56e3b7fe31ac7a515c939fd56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Tue, 12 Nov 2024 10:39:41 +0800 Subject: [PATCH 040/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E8=84=B1=E6=95=8F=E4=BC=A0=E5=A4=9A=E8=A7=92=E8=89=B2?= =?UTF-8?q?=E5=A4=9A=E6=9D=83=E9=99=90=E6=A0=87=E8=AF=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/dromara/common/sensitive/annotation/Sensitive.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ruoyi-common/ruoyi-common-sensitive/src/main/java/org/dromara/common/sensitive/annotation/Sensitive.java b/ruoyi-common/ruoyi-common-sensitive/src/main/java/org/dromara/common/sensitive/annotation/Sensitive.java index 6940966b5..e75dc5bf2 100644 --- a/ruoyi-common/ruoyi-common-sensitive/src/main/java/org/dromara/common/sensitive/annotation/Sensitive.java +++ b/ruoyi-common/ruoyi-common-sensitive/src/main/java/org/dromara/common/sensitive/annotation/Sensitive.java @@ -25,10 +25,10 @@ public @interface Sensitive { /** * 角色标识符 多个角色满足一个即可 */ - String[] roleKey(); + String[] roleKey() default {}; /** * 权限标识符 多个权限满足一个即可 */ - String[] perms(); + String[] perms() default {}; } From a098565c37e6c822076f277ba9674b9f307862a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Tue, 12 Nov 2024 10:48:28 +0800 Subject: [PATCH 041/175] =?UTF-8?q?fix=20=E4=BF=AE=E5=A4=8D=20=E8=AF=AF?= =?UTF-8?q?=E5=88=A0=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/org/dromara/generator/util/GenUtils.java | 1 + 1 file changed, 1 insertion(+) diff --git a/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/util/GenUtils.java b/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/util/GenUtils.java index 676896250..0981997d8 100644 --- a/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/util/GenUtils.java +++ b/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/util/GenUtils.java @@ -37,6 +37,7 @@ public class GenUtils { public static void initColumnField(GenTableColumn column, GenTable table) { String dataType = getDbType(column.getColumnType()); String columnName = column.getColumnName(); + column.setTableId(table.getTableId()); // 设置java字段名 column.setJavaField(StringUtils.toCamelCase(columnName)); // 设置默认类型 From 4f92c0317ea77262999bd31a11e9556890d4b932 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Tue, 12 Nov 2024 10:50:10 +0800 Subject: [PATCH 042/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E5=88=A0?= =?UTF-8?q?=E9=99=A4=E6=97=A0=E6=84=8F=E4=B9=89=E7=9A=84=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/dromara/common/core/utils/ObjectUtils.java | 13 ------------- .../mybatis/handler/InjectionMetaObjectHandler.java | 5 ++++- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/ObjectUtils.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/ObjectUtils.java index 82faf2c57..93617b018 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/ObjectUtils.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/ObjectUtils.java @@ -43,19 +43,6 @@ public class ObjectUtils extends ObjectUtil { return defaultValue; } - /** - * 如果值不为空,则返回值 - * - * @param obj 对象 - * @return 对象字段 - */ - public static T notNull(T obj) { - if (isNotNull(obj)) { - return obj; - } - return null; - } - /** * 如果值不为空,则返回值,否则返回默认值 * diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/InjectionMetaObjectHandler.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/InjectionMetaObjectHandler.java index 85ef2e97a..fec25792a 100644 --- a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/InjectionMetaObjectHandler.java +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/InjectionMetaObjectHandler.java @@ -71,7 +71,10 @@ public class InjectionMetaObjectHandler implements MetaObjectHandler { baseEntity.setUpdateTime(current); // 获取当前登录用户的ID,并填充更新人信息 - baseEntity.setUpdateBy(ObjectUtils.notNull(LoginHelper.getUserId())); + Long userId = LoginHelper.getUserId(); + if (ObjectUtil.isNotNull(userId)) { + baseEntity.setUpdateBy(userId); + } } else { this.strictUpdateFill(metaObject, "updateTime", Date.class, new Date()); } From d3b5220dc3c472deb7b4d51b50aa6b5c633dcc6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Tue, 12 Nov 2024 15:10:04 +0800 Subject: [PATCH 043/175] =?UTF-8?q?update=20=E6=8E=92=E9=99=A4=20websocket?= =?UTF-8?q?=E5=8C=85=E5=86=85=E5=8C=85=E5=90=AB=E7=9A=84tomcat=E4=BE=9D?= =?UTF-8?q?=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ruoyi-common/ruoyi-common-websocket/pom.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ruoyi-common/ruoyi-common-websocket/pom.xml b/ruoyi-common/ruoyi-common-websocket/pom.xml index db86dcbe4..0587cd79a 100644 --- a/ruoyi-common/ruoyi-common-websocket/pom.xml +++ b/ruoyi-common/ruoyi-common-websocket/pom.xml @@ -35,6 +35,12 @@ org.springframework.boot spring-boot-starter-websocket + + + org.springframework.boot + spring-boot-starter-tomcat + + From 1a993a7899c2128e78975754502fba0993a8079e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Tue, 12 Nov 2024 18:17:47 +0800 Subject: [PATCH 044/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20xss?= =?UTF-8?q?=E5=8C=85=E8=A3=85=E5=99=A8=20Parameter=20=E5=A4=84=E7=90=86=20?= =?UTF-8?q?=E5=85=BC=E5=AE=B9=E6=9F=90=E4=BA=9B=E5=AE=B9=E5=99=A8=E4=B8=8D?= =?UTF-8?q?=E5=85=81=E8=AE=B8=E6=94=B9=E5=8F=82=E6=95=B0=E7=9A=84=E6=83=85?= =?UTF-8?q?=E5=86=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../filter/XssHttpServletRequestWrapper.java | 47 +++++++++++-------- 1 file changed, 28 insertions(+), 19 deletions(-) diff --git a/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/filter/XssHttpServletRequestWrapper.java b/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/filter/XssHttpServletRequestWrapper.java index 190f94eab..914e54995 100644 --- a/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/filter/XssHttpServletRequestWrapper.java +++ b/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/filter/XssHttpServletRequestWrapper.java @@ -1,19 +1,22 @@ package org.dromara.common.web.filter; import cn.hutool.core.io.IoUtil; +import cn.hutool.core.map.MapUtil; +import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.http.HtmlUtil; -import org.dromara.common.core.utils.StringUtils; -import org.springframework.http.HttpHeaders; -import org.springframework.http.MediaType; - import jakarta.servlet.ReadListener; import jakarta.servlet.ServletInputStream; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequestWrapper; +import org.dromara.common.core.utils.StringUtils; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; + import java.io.ByteArrayInputStream; import java.io.IOException; import java.nio.charset.StandardCharsets; +import java.util.HashMap; import java.util.Map; /** @@ -32,16 +35,22 @@ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper { @Override public String getParameter(String name) { String value = super.getParameter(name); - if (value != null) { - return HtmlUtil.cleanHtmlTag(value).trim(); + if (value == null) { + return null; } - return value; + return HtmlUtil.cleanHtmlTag(value).trim(); } @Override public Map getParameterMap() { Map valueMap = super.getParameterMap(); - for (Map.Entry entry : valueMap.entrySet()) { + if (MapUtil.isEmpty(valueMap)) { + return valueMap; + } + // 避免某些容器不允许改参数的情况 copy一份重新改 + Map map = new HashMap<>(valueMap.size()); + map.putAll(valueMap); + for (Map.Entry entry : map.entrySet()) { String[] values = entry.getValue(); if (values != null) { int length = values.length; @@ -50,25 +59,25 @@ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper { // 防xss攻击和过滤前后空格 escapseValues[i] = HtmlUtil.cleanHtmlTag(values[i]).trim(); } - valueMap.put(entry.getKey(), escapseValues); + map.put(entry.getKey(), escapseValues); } } - return valueMap; + return map; } @Override public String[] getParameterValues(String name) { String[] values = super.getParameterValues(name); - if (values != null) { - int length = values.length; - String[] escapseValues = new String[length]; - for (int i = 0; i < length; i++) { - // 防xss攻击和过滤前后空格 - escapseValues[i] = HtmlUtil.cleanHtmlTag(values[i]).trim(); - } - return escapseValues; + if (ArrayUtil.isEmpty(values)) { + return values; } - return values; + int length = values.length; + String[] escapseValues = new String[length]; + for (int i = 0; i < length; i++) { + // 防xss攻击和过滤前后空格 + escapseValues[i] = HtmlUtil.cleanHtmlTag(values[i]).trim(); + } + return escapseValues; } @Override From a18e430056205e995da35531c36dc934aff643f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Thu, 14 Nov 2024 15:56:16 +0800 Subject: [PATCH 045/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=E9=83=A8?= =?UTF-8?q?=E7=BD=B2=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .run/ruoyi-server.run.xml | 2 +- ruoyi-admin/Dockerfile | 2 +- ruoyi-extend/ruoyi-monitor-admin/Dockerfile | 2 +- ruoyi-extend/ruoyi-snailjob-server/Dockerfile | 2 +- script/docker/database.yml | 2 -- script/docker/docker-compose.yml | 2 -- 6 files changed, 4 insertions(+), 8 deletions(-) diff --git a/.run/ruoyi-server.run.xml b/.run/ruoyi-server.run.xml index 57b0fb821..f59be88cc 100644 --- a/.run/ruoyi-server.run.xml +++ b/.run/ruoyi-server.run.xml @@ -1,5 +1,5 @@ - +

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

+ * + * @param factory Undertow 的 Web 服务器工厂 + */ @Override public void customize(UndertowServletWebServerFactory factory) { factory.addDeploymentInfoCustomizers(deploymentInfo -> { + // 配置 WebSocket 部署信息,设置 WebSocket 使用的缓冲区池 WebSocketDeploymentInfo webSocketDeploymentInfo = new WebSocketDeploymentInfo(); webSocketDeploymentInfo.setBuffers(new DefaultByteBufferPool(true, 1024)); deploymentInfo.addServletContextAttribute("io.undertow.websockets.jsr.WebSocketDeploymentInfo", webSocketDeploymentInfo); - // 使用虚拟线程 + + // 如果启用了虚拟线程,配置 Undertow 使用虚拟线程池 if (SpringUtils.isVirtual()) { + // 创建虚拟线程池,线程池前缀为 "undertow-" VirtualThreadTaskExecutor executor = new VirtualThreadTaskExecutor("undertow-"); + // 设置虚拟线程池为执行器和异步执行器 deploymentInfo.setExecutor(executor); deploymentInfo.setAsyncExecutor(executor); } + + // 配置禁止某些不安全的 HTTP 方法(如 CONNECT、TRACE、TRACK) deploymentInfo.addInitialHandlerChainWrapper(handler -> { // 禁止三个方法 CONNECT/TRACE/TRACK 也是不安全的 避免爬虫骚扰 HttpString[] disallowedHttpMethods = { @@ -37,6 +54,7 @@ public class UndertowConfig implements WebServerFactoryCustomizer Date: Fri, 15 Nov 2024 15:17:36 +0800 Subject: [PATCH 054/175] =?UTF-8?q?docs=20=E8=A1=A5=E5=85=85=E5=AE=A2?= =?UTF-8?q?=E6=88=B7=E7=AB=AF=E5=B7=A5=E5=85=B7=E7=B1=BB=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/core/utils/ServletUtils.java | 99 +++++++++++++++---- 1 file changed, 80 insertions(+), 19 deletions(-) diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/ServletUtils.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/ServletUtils.java index a1316eb85..bd1aab808 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/ServletUtils.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/ServletUtils.java @@ -25,7 +25,7 @@ import java.util.HashMap; import java.util.Map; /** - * 客户端工具类 + * 客户端工具类,提供获取请求参数、响应处理、头部信息等常用操作 * * @author ruoyi */ @@ -33,52 +33,73 @@ import java.util.Map; public class ServletUtils extends JakartaServletUtil { /** - * 获取String参数 + * 获取指定名称的 String 类型的请求参数 + * + * @param name 参数名 + * @return 参数值 */ public static String getParameter(String name) { return getRequest().getParameter(name); } /** - * 获取String参数 + * 获取指定名称的 String 类型的请求参数,若参数不存在,则返回默认值 + * + * @param name 参数名 + * @param defaultValue 默认值 + * @return 参数值或默认值 */ public static String getParameter(String name, String defaultValue) { return Convert.toStr(getRequest().getParameter(name), defaultValue); } /** - * 获取Integer参数 + * 获取指定名称的 Integer 类型的请求参数 + * + * @param name 参数名 + * @return 参数值 */ public static Integer getParameterToInt(String name) { return Convert.toInt(getRequest().getParameter(name)); } /** - * 获取Integer参数 + * 获取指定名称的 Integer 类型的请求参数,若参数不存在,则返回默认值 + * + * @param name 参数名 + * @param defaultValue 默认值 + * @return 参数值或默认值 */ public static Integer getParameterToInt(String name, Integer defaultValue) { return Convert.toInt(getRequest().getParameter(name), defaultValue); } /** - * 获取Boolean参数 + * 获取指定名称的 Boolean 类型的请求参数 + * + * @param name 参数名 + * @return 参数值 */ public static Boolean getParameterToBool(String name) { return Convert.toBool(getRequest().getParameter(name)); } /** - * 获取Boolean参数 + * 获取指定名称的 Boolean 类型的请求参数,若参数不存在,则返回默认值 + * + * @param name 参数名 + * @param defaultValue 默认值 + * @return 参数值或默认值 */ public static Boolean getParameterToBool(String name, Boolean defaultValue) { return Convert.toBool(getRequest().getParameter(name), defaultValue); } /** - * 获得所有请求参数 + * 获取所有请求参数(以 Map 的形式返回) * * @param request 请求对象{@link ServletRequest} - * @return Map + * @return 请求参数的 Map,键为参数名,值为参数值数组 */ public static Map getParams(ServletRequest request) { final Map map = request.getParameterMap(); @@ -86,10 +107,10 @@ public class ServletUtils extends JakartaServletUtil { } /** - * 获得所有请求参数 + * 获取所有请求参数(以 Map 的形式返回,值为字符串形式的拼接) * * @param request 请求对象{@link ServletRequest} - * @return Map + * @return 请求参数的 Map,键为参数名,值为拼接后的字符串 */ public static Map getParamMap(ServletRequest request) { Map params = new HashMap<>(); @@ -100,7 +121,9 @@ public class ServletUtils extends JakartaServletUtil { } /** - * 获取request + * 获取当前 HTTP 请求对象 + * + * @return 当前 HTTP 请求对象 */ public static HttpServletRequest getRequest() { try { @@ -111,7 +134,9 @@ public class ServletUtils extends JakartaServletUtil { } /** - * 获取response + * 获取当前 HTTP 响应对象 + * + * @return 当前 HTTP 响应对象 */ public static HttpServletResponse getResponse() { try { @@ -122,12 +147,25 @@ public class ServletUtils extends JakartaServletUtil { } /** - * 获取session + * 获取当前请求的 HttpSession 对象 + *

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

+ * HttpSession 用于存储会话级别的数据,如用户登录信息、购物车内容等, + * 可以在多个请求之间共享会话数据 + * + * @return 当前请求的 HttpSession 对象 */ public static HttpSession getSession() { return getRequest().getSession(); } + /** + * 获取当前请求的请求属性 + * + * @return {@link ServletRequestAttributes} 请求属性对象 + */ public static ServletRequestAttributes getRequestAttributes() { try { RequestAttributes attributes = RequestContextHolder.getRequestAttributes(); @@ -137,6 +175,13 @@ public class ServletUtils extends JakartaServletUtil { } } + /** + * 获取指定请求头的值,如果头部为空则返回空字符串 + * + * @param request 请求对象 + * @param name 头部名称 + * @return 头部值 + */ public static String getHeader(HttpServletRequest request, String name) { String value = request.getHeader(name); if (StringUtils.isEmpty(value)) { @@ -145,6 +190,12 @@ public class ServletUtils extends JakartaServletUtil { return urlDecode(value); } + /** + * 获取所有请求头的 Map,键为头部名称,值为头部值 + * + * @param request 请求对象 + * @return 请求头的 Map + */ public static Map getHeaders(HttpServletRequest request) { Map map = new LinkedCaseInsensitiveMap<>(); Enumeration enumeration = request.getHeaderNames(); @@ -159,7 +210,7 @@ public class ServletUtils extends JakartaServletUtil { } /** - * 将字符串渲染到客户端 + * 将字符串渲染到客户端(以 JSON 格式返回) * * @param response 渲染对象 * @param string 待渲染的字符串 @@ -176,37 +227,47 @@ public class ServletUtils extends JakartaServletUtil { } /** - * 是否是Ajax异步请求 + * 判断当前请求是否为 Ajax 异步请求 * - * @param request + * @param request 请求对象 + * @return 是否为 Ajax 请求 */ public static boolean isAjaxRequest(HttpServletRequest request) { + // 判断 Accept 头部是否包含 application/json String accept = request.getHeader("accept"); if (accept != null && accept.contains(MediaType.APPLICATION_JSON_VALUE)) { return true; } + // 判断 X-Requested-With 头部是否包含 XMLHttpRequest String xRequestedWith = request.getHeader("X-Requested-With"); if (xRequestedWith != null && xRequestedWith.contains("XMLHttpRequest")) { return true; } + // 判断 URI 后缀是否为 .json 或 .xml String uri = request.getRequestURI(); if (StringUtils.equalsAnyIgnoreCase(uri, ".json", ".xml")) { return true; } + // 判断请求参数 __ajax 是否为 json 或 xml String ajax = request.getParameter("__ajax"); return StringUtils.equalsAnyIgnoreCase(ajax, "json", "xml"); } + /** + * 获取客户端 IP 地址 + * + * @return 客户端 IP 地址 + */ public static String getClientIP() { return getClientIP(getRequest()); } /** - * 内容编码 + * 对内容进行 URL 编码 * * @param str 内容 * @return 编码后的内容 @@ -216,7 +277,7 @@ public class ServletUtils extends JakartaServletUtil { } /** - * 内容解码 + * 对内容进行 URL 解码 * * @param str 内容 * @return 解码后的内容 From 6d4519959269418ae939ff1ff530f08f32c32827 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Fri, 15 Nov 2024 16:28:33 +0800 Subject: [PATCH 055/175] =?UTF-8?q?update=20=E4=BF=AE=E6=94=B9=20readme=20?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=88=90=E5=91=98=E9=A1=B9=E7=9B=AE=E8=AF=B4?= =?UTF-8?q?=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 40636ab94..b37eaf91f 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,9 @@ > 系统演示: [传送门](https://plus-doc.dromara.org/#/common/demo_system) -> 前端项目地址: [plus-ui](https://gitee.com/JavaLionLi/plus-ui) +> 官方前端项目地址: [plus-ui](https://gitee.com/JavaLionLi/plus-ui)
+> 成员前端项目地址: 基于vben [ruoyi-plus-vben](https://gitee.com/dapppp/ruoyi-plus-vben)
+> 成员前端项目地址: 基于vben5 [ruoyi-plus-vben5](https://gitee.com/dapppp/ruoyi-plus-vben5) > 文档地址: [plus-doc](https://plus-doc.dromara.org) From e94fccc784d4e2fbf6f225cac2e4818bd95fb01a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Wed, 20 Nov 2024 11:03:55 +0800 Subject: [PATCH 056/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20Dockerfil?= =?UTF-8?q?e=20=E6=B6=88=E9=99=A4warn=E8=AD=A6=E5=91=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ruoyi-admin/Dockerfile | 2 ++ ruoyi-extend/ruoyi-monitor-admin/Dockerfile | 2 ++ ruoyi-extend/ruoyi-snailjob-server/Dockerfile | 2 ++ 3 files changed, 6 insertions(+) diff --git a/ruoyi-admin/Dockerfile b/ruoyi-admin/Dockerfile index 027384298..e0be8aeef 100644 --- a/ruoyi-admin/Dockerfile +++ b/ruoyi-admin/Dockerfile @@ -17,6 +17,8 @@ EXPOSE ${SERVER_PORT} ADD ./target/ruoyi-admin.jar ./app.jar +SHELL ["/bin/bash", "-c"] + ENTRYPOINT java -Djava.security.egd=file:/dev/./urandom -Dserver.port=${SERVER_PORT} \ # 应用名称 如果想区分集群节点监控 改成不同的名称即可 #-Dskywalking.agent.service_name=ruoyi-server \ diff --git a/ruoyi-extend/ruoyi-monitor-admin/Dockerfile b/ruoyi-extend/ruoyi-monitor-admin/Dockerfile index 8e31e78a8..d55b95627 100644 --- a/ruoyi-extend/ruoyi-monitor-admin/Dockerfile +++ b/ruoyi-extend/ruoyi-monitor-admin/Dockerfile @@ -15,6 +15,8 @@ EXPOSE 9090 ADD ./target/ruoyi-monitor-admin.jar ./app.jar +SHELL ["/bin/bash", "-c"] + ENTRYPOINT java -Djava.security.egd=file:/dev/./urandom \ -XX:+HeapDumpOnOutOfMemoryError -XX:+UseZGC ${JAVA_OPTS} \ -jar app.jar diff --git a/ruoyi-extend/ruoyi-snailjob-server/Dockerfile b/ruoyi-extend/ruoyi-snailjob-server/Dockerfile index 29bde41f7..6f4484d33 100644 --- a/ruoyi-extend/ruoyi-snailjob-server/Dockerfile +++ b/ruoyi-extend/ruoyi-snailjob-server/Dockerfile @@ -16,6 +16,8 @@ EXPOSE 17888 ADD ./target/ruoyi-snailjob-server.jar ./app.jar +SHELL ["/bin/bash", "-c"] + ENTRYPOINT java -Djava.security.egd=file:/dev/./urandom \ -XX:+HeapDumpOnOutOfMemoryError -XX:+UseZGC ${JAVA_OPTS} \ -jar app.jar From bf515042d06ebeb7ca1022d2c05d9a2b56034711 Mon Sep 17 00:00:00 2001 From: dhb52 Date: Wed, 20 Nov 2024 12:44:22 +0800 Subject: [PATCH 057/175] =?UTF-8?q?update=20=E5=8D=87=E7=BA=A7SnailJob?= =?UTF-8?q?=E7=89=88=E6=9C=AC=E5=88=B01.2.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 9c9abd0ed..1591c0cb0 100644 --- a/pom.xml +++ b/pom.xml @@ -31,7 +31,7 @@ 3.37.0 2.2.7 4.3.1 - 1.1.2 + 1.2.0 1.4.5 0.2.0 1.18.34 From dd2abd95c951f8e037e78c421a37ffb5aa999e57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Fri, 22 Nov 2024 10:43:44 +0800 Subject: [PATCH 058/175] =?UTF-8?q?fix=20=E4=BF=AE=E5=A4=8D=20aop=20?= =?UTF-8?q?=E6=97=A0=E6=B3=95=E6=8B=A6=E6=88=AAmapper=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E4=B8=8A=E7=9A=84=E6=B3=A8=E8=A7=A3=E5=AF=BC=E8=87=B4=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98=20=E7=B1=BB=E4=B8=8A=E4=BE=9D=E6=97=A7?= =?UTF-8?q?=E4=BD=BF=E7=94=A8=E6=89=AB=E6=8F=8F=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mybatis/config/MybatisPlusConfig.java | 2 +- .../handler/PlusDataPermissionHandler.java | 87 ++++++++++++++++++- .../PlusDataPermissionInterceptor.java | 10 ++- 3 files changed, 91 insertions(+), 8 deletions(-) diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/config/MybatisPlusConfig.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/config/MybatisPlusConfig.java index f7d14ee97..1e8d619fa 100644 --- a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/config/MybatisPlusConfig.java +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/config/MybatisPlusConfig.java @@ -52,7 +52,7 @@ public class MybatisPlusConfig { * 数据权限拦截器 */ public PlusDataPermissionInterceptor dataPermissionInterceptor() { - return new PlusDataPermissionInterceptor(); + return new PlusDataPermissionInterceptor(SpringUtils.getProperty("mybatis-plus.mapperPackage")); } /** diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/PlusDataPermissionHandler.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/PlusDataPermissionHandler.java index 236538af4..4ae67429f 100644 --- a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/PlusDataPermissionHandler.java +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/PlusDataPermissionHandler.java @@ -1,5 +1,6 @@ package org.dromara.common.mybatis.handler; +import cn.hutool.core.annotation.AnnotationUtil; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; import lombok.extern.slf4j.Slf4j; @@ -8,6 +9,7 @@ import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.operators.conditional.AndExpression; import net.sf.jsqlparser.expression.operators.relational.ParenthesedExpressionList; import net.sf.jsqlparser.parser.CCJSqlParserUtil; +import org.apache.ibatis.io.Resources; import org.dromara.common.core.domain.dto.RoleDTO; import org.dromara.common.core.domain.model.LoginUser; import org.dromara.common.core.exception.ServiceException; @@ -19,17 +21,26 @@ import org.dromara.common.mybatis.annotation.DataPermission; import org.dromara.common.mybatis.enums.DataScopeType; import org.dromara.common.mybatis.helper.DataPermissionHelper; import org.dromara.common.satoken.utils.LoginHelper; +import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.expression.BeanFactoryResolver; +import org.springframework.core.io.Resource; +import org.springframework.core.io.support.PathMatchingResourcePatternResolver; +import org.springframework.core.io.support.ResourcePatternResolver; +import org.springframework.core.type.ClassMetadata; +import org.springframework.core.type.classreading.CachingMetadataReaderFactory; import org.springframework.expression.BeanResolver; import org.springframework.expression.ExpressionParser; import org.springframework.expression.ParserContext; import org.springframework.expression.common.TemplateParserContext; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.expression.spel.support.StandardEvaluationContext; +import org.springframework.util.ClassUtils; import java.util.Arrays; import java.util.HashSet; +import java.util.Map; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import java.util.function.Function; /** @@ -41,6 +52,11 @@ import java.util.function.Function; @Slf4j public class PlusDataPermissionHandler { + /** + * 类名称与注解的映射关系缓存(由于aop无法拦截mybatis接口类上的注解 只能通过启动预扫描的方式进行) + */ + private final Map dataPermissionCacheMap = new ConcurrentHashMap<>(); + /** * spel 解析器 */ @@ -51,6 +67,15 @@ public class PlusDataPermissionHandler { */ private final BeanResolver beanResolver = new BeanFactoryResolver(SpringUtils.getBeanFactory()); + /** + * 构造方法,扫描指定包下的 Mapper 类并初始化缓存 + * + * @param mapperPackage Mapper 类所在的包路径 + */ + public PlusDataPermissionHandler(String mapperPackage) { + scanMapperClasses(mapperPackage); + } + /** * 获取数据过滤条件的 SQL 片段 * @@ -62,7 +87,7 @@ public class PlusDataPermissionHandler { public Expression getSqlSegment(Expression where, String mappedStatementId, boolean isSelect) { try { // 获取数据权限配置 - DataPermission dataPermission = DataPermissionHelper.getPermission(); + DataPermission dataPermission = getDataPermission(mappedStatementId); // 获取当前登录用户信息 LoginUser currentUser = DataPermissionHelper.getVariable("user"); if (ObjectUtil.isNull(currentUser)) { @@ -169,12 +194,68 @@ public class PlusDataPermissionHandler { return ""; } + /** + * 扫描指定包下的 Mapper 类,并查找其中带有特定注解的方法或类 + * + * @param mapperPackage Mapper 类所在的包路径 + */ + private void scanMapperClasses(String mapperPackage) { + // 创建资源解析器和元数据读取工厂 + PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); + CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory(); + // 将 Mapper 包路径按分隔符拆分为数组 + String[] packagePatternArray = StringUtils.splitPreserveAllTokens(mapperPackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS); + String classpath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX; + try { + for (String packagePattern : packagePatternArray) { + // 将包路径转换为资源路径 + String path = ClassUtils.convertClassNameToResourcePath(packagePattern); + // 获取指定路径下的所有 .class 文件资源 + Resource[] resources = resolver.getResources(classpath + path + "/*.class"); + for (Resource resource : resources) { + // 获取资源的类元数据 + ClassMetadata classMetadata = factory.getMetadataReader(resource).getClassMetadata(); + // 获取资源对应的类对象 + Class clazz = Resources.classForName(classMetadata.getClassName()); + // 查找类中的特定注解 + if (AnnotationUtil.hasAnnotation(clazz, DataPermission.class)) { + DataPermission dataPermission = AnnotationUtil.getAnnotation(clazz, DataPermission.class); + dataPermissionCacheMap.put(clazz.getName(), dataPermission); + } + } + } + } catch (Exception e) { + log.error("初始化数据安全缓存时出错:{}", e.getMessage()); + } + } + + /** + * 根据映射语句 ID 或类名获取对应的 DataPermission 注解对象 + * + * @param mapperId 映射语句 ID + * @return DataPermission 注解对象,如果不存在则返回 null + */ + public DataPermission getDataPermission(String mapperId) { + // 检查上下文中是否包含映射语句 ID 对应的 DataPermission 注解对象 + if (DataPermissionHelper.getPermission() != null) { + return DataPermissionHelper.getPermission(); + } + // 如果缓存中不包含映射语句 ID 对应的 DataPermission 注解对象,则尝试使用类名作为键查找 + String clazzName = mapperId.substring(0, mapperId.lastIndexOf(".")); + if (dataPermissionCacheMap.containsKey(clazzName)) { + return dataPermissionCacheMap.get(clazzName); + } + return null; + } + /** * 检查给定的映射语句 ID 是否有效,即是否能够找到对应的 DataPermission 注解对象 * + * @param mapperId 映射语句 ID * @return 如果找到对应的 DataPermission 注解对象,则返回 false;否则返回 true */ - public boolean invalid() { - return DataPermissionHelper.getPermission() == null; + public boolean invalid(String mapperId) { + return getDataPermission(mapperId) == null; } + } diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/interceptor/PlusDataPermissionInterceptor.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/interceptor/PlusDataPermissionInterceptor.java index 587a99886..85a4d0abc 100644 --- a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/interceptor/PlusDataPermissionInterceptor.java +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/interceptor/PlusDataPermissionInterceptor.java @@ -39,9 +39,11 @@ public class PlusDataPermissionInterceptor extends BaseMultiTableInnerIntercepto /** * 构造函数,初始化 PlusDataPermissionHandler 实例 + * + * @param mapperPackage 扫描的映射器包 */ - public PlusDataPermissionInterceptor() { - this.dataPermissionHandler = new PlusDataPermissionHandler(); + public PlusDataPermissionInterceptor(String mapperPackage) { + this.dataPermissionHandler = new PlusDataPermissionHandler(mapperPackage); } /** @@ -62,7 +64,7 @@ public class PlusDataPermissionInterceptor extends BaseMultiTableInnerIntercepto return; } // 检查是否缺少有效的数据权限注解 - if (dataPermissionHandler.invalid()) { + if (dataPermissionHandler.invalid(ms.getId())) { return; } // 解析 sql 分配对应方法 @@ -90,7 +92,7 @@ public class PlusDataPermissionInterceptor extends BaseMultiTableInnerIntercepto return; } // 检查是否缺少有效的数据权限注解 - if (dataPermissionHandler.invalid()) { + if (dataPermissionHandler.invalid(ms.getId())) { return; } PluginUtils.MPBoundSql mpBs = mpSh.mPBoundSql(); From 847b158283a495d6d42980e5b2475bd20dfb9002 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Fri, 22 Nov 2024 15:59:40 +0800 Subject: [PATCH 059/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E4=B8=AA?= =?UTF-8?q?=E4=BA=BA=E4=B8=AD=E5=BF=83=E5=BC=BA=E9=80=80=E8=AE=BE=E5=A4=87?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E8=B7=AF=E5=BE=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../system/controller/monitor/SysUserOnlineController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/monitor/SysUserOnlineController.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/monitor/SysUserOnlineController.java index 9b08c2d2c..95439a266 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/monitor/SysUserOnlineController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/monitor/SysUserOnlineController.java @@ -113,7 +113,7 @@ public class SysUserOnlineController extends BaseController { * @param tokenId token值 */ @Log(title = "在线设备", businessType = BusinessType.FORCE) - @PostMapping("/{tokenId}") + @DeleteMapping("/myself/{tokenId}") public R remove(@PathVariable("tokenId") String tokenId) { try { // 获取指定账号 id 的 token 集合 From ef919b9f3d069f775625332b152f9792243d34b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Fri, 22 Nov 2024 17:01:05 +0800 Subject: [PATCH 060/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E7=94=9F=E6=88=90=E5=99=A8=E7=B1=BB=E5=9E=8B=E8=8E=B7?= =?UTF-8?q?=E5=8F=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/org/dromara/generator/service/GenTableServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java b/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java index 3f9ef1920..cf4e81377 100644 --- a/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java +++ b/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java @@ -310,7 +310,7 @@ public class GenTableServiceImpl implements IGenTableService { tableColumn.setIsPk(String.valueOf(column.isPrimaryKey())); tableColumn.setColumnName(column.getName()); tableColumn.setColumnComment(column.getComment()); - tableColumn.setColumnType(column.getTypeName().toLowerCase()); + tableColumn.setColumnType(column.getOriginType().toLowerCase()); tableColumn.setSort(column.getPosition()); tableColumn.setIsRequired(column.isNullable() == 0 ? "1" : "0"); tableColumn.setIsIncrement(column.isAutoIncrement() == -1 ? "0" : "1"); From cd08f66c597dea41fa5254f24e1d5d9dd1079aea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Fri, 22 Nov 2024 17:18:27 +0800 Subject: [PATCH 061/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E7=94=9F=E6=88=90=E5=99=A8=20pg=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E5=BA=93=20=E4=B8=BB=E9=94=AE=E8=8E=B7=E5=8F=96=E4=B8=8D?= =?UTF-8?q?=E7=B2=BE=E7=A1=AE=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/dromara/generator/service/GenTableServiceImpl.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java b/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java index cf4e81377..d3f4dded3 100644 --- a/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java +++ b/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java @@ -303,7 +303,11 @@ public class GenTableServiceImpl implements IGenTableService { @DS("#dataName") @Override public List selectDbTableColumnsByName(String tableName, String dataName) { - LinkedHashMap columns = ServiceProxy.metadata().columns(tableName); + Table table = ServiceProxy.metadata().table(tableName); + if (ObjectUtil.isNull(table)) { + return new ArrayList<>(); + } + LinkedHashMap columns = table.getColumns(); List tableColumns = new ArrayList<>(); columns.forEach((columnName, column) -> { GenTableColumn tableColumn = new GenTableColumn(); From d194b39e57e3d6caf5d76749ab1618e524f479a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Fri, 22 Nov 2024 17:54:16 +0800 Subject: [PATCH 062/175] =?UTF-8?q?fix=20=E4=BF=AE=E5=A4=8D=20monitor=20?= =?UTF-8?q?=E8=AE=BE=E7=BD=AE=20context-path=20=E5=AF=BC=E8=87=B4=E9=80=80?= =?UTF-8?q?=E5=87=BA=E9=87=8D=E6=96=B0=E7=99=BB=E5=BD=95404=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ruoyi-admin/src/main/resources/application-dev.yml | 2 +- ruoyi-admin/src/main/resources/application-prod.yml | 2 +- .../ruoyi-monitor-admin/src/main/resources/application.yml | 3 +-- .../src/main/resources/application-dev.yml | 2 +- .../src/main/resources/application-prod.yml | 2 +- script/docker/nginx/conf/nginx.conf | 2 +- 6 files changed, 6 insertions(+), 7 deletions(-) diff --git a/ruoyi-admin/src/main/resources/application-dev.yml b/ruoyi-admin/src/main/resources/application-dev.yml index 4410ab59f..283cdad44 100644 --- a/ruoyi-admin/src/main/resources/application-dev.yml +++ b/ruoyi-admin/src/main/resources/application-dev.yml @@ -2,7 +2,7 @@ spring.boot.admin.client: # 增加客户端开关 enabled: true - url: http://localhost:9090/admin + url: http://localhost:9090 instance: service-host-type: IP metadata: diff --git a/ruoyi-admin/src/main/resources/application-prod.yml b/ruoyi-admin/src/main/resources/application-prod.yml index d26111828..2002e9eee 100644 --- a/ruoyi-admin/src/main/resources/application-prod.yml +++ b/ruoyi-admin/src/main/resources/application-prod.yml @@ -5,7 +5,7 @@ spring.servlet.multipart.location: /ruoyi/server/temp spring.boot.admin.client: # 增加客户端开关 enabled: true - url: http://localhost:9090/admin + url: http://localhost:9090 instance: service-host-type: IP metadata: diff --git a/ruoyi-extend/ruoyi-monitor-admin/src/main/resources/application.yml b/ruoyi-extend/ruoyi-monitor-admin/src/main/resources/application.yml index 622c93d3c..b9720cba8 100644 --- a/ruoyi-extend/ruoyi-monitor-admin/src/main/resources/application.yml +++ b/ruoyi-extend/ruoyi-monitor-admin/src/main/resources/application.yml @@ -19,7 +19,6 @@ spring: admin: ui: title: RuoYi-Vue-Plus服务监控中心 - context-path: /admin --- # Actuator 监控端点的配置项 management: @@ -38,7 +37,7 @@ spring.boot.admin.client: # 增加客户端开关 enabled: true # 设置 Spring Boot Admin Server 地址 - url: http://localhost:9090/admin + url: http://localhost:9090 instance: service-host-type: IP metadata: diff --git a/ruoyi-extend/ruoyi-snailjob-server/src/main/resources/application-dev.yml b/ruoyi-extend/ruoyi-snailjob-server/src/main/resources/application-dev.yml index 3ed797cf6..579f376db 100644 --- a/ruoyi-extend/ruoyi-snailjob-server/src/main/resources/application-dev.yml +++ b/ruoyi-extend/ruoyi-snailjob-server/src/main/resources/application-dev.yml @@ -40,7 +40,7 @@ snail-job: spring.boot.admin.client: # 增加客户端开关 enabled: true - url: http://localhost:9090/admin + url: http://localhost:9090 instance: service-host-type: IP metadata: diff --git a/ruoyi-extend/ruoyi-snailjob-server/src/main/resources/application-prod.yml b/ruoyi-extend/ruoyi-snailjob-server/src/main/resources/application-prod.yml index 1d830dbe7..dffe05777 100644 --- a/ruoyi-extend/ruoyi-snailjob-server/src/main/resources/application-prod.yml +++ b/ruoyi-extend/ruoyi-snailjob-server/src/main/resources/application-prod.yml @@ -40,7 +40,7 @@ snail-job: spring.boot.admin.client: # 增加客户端开关 enabled: true - url: http://localhost:9090/admin + url: http://localhost:9090 instance: service-host-type: IP metadata: diff --git a/script/docker/nginx/conf/nginx.conf b/script/docker/nginx/conf/nginx.conf index 3c79d97f6..3df4a722c 100644 --- a/script/docker/nginx/conf/nginx.conf +++ b/script/docker/nginx/conf/nginx.conf @@ -96,7 +96,7 @@ http { proxy_set_header X-Real-IP $remote_addr; proxy_set_header REMOTE-HOST $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_pass http://monitor-admin/admin/; + proxy_pass http://monitor-admin/; } location /snail-job/ { From 4af46a604589220b7d1c37dd5ebcdb05081f4132 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A7=8B=E8=BE=9E=E6=9C=AA=E5=AF=92?= <545073804@qq.com> Date: Sat, 23 Nov 2024 06:57:11 +0000 Subject: [PATCH 063/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E6=A0=A1?= =?UTF-8?q?=E9=AA=8C=E7=A7=9F=E6=88=B7=E5=88=A4=E7=A9=BA=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 秋辞未寒 <545073804@qq.com> --- .../main/java/org/dromara/web/service/SysLoginService.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ruoyi-admin/src/main/java/org/dromara/web/service/SysLoginService.java b/ruoyi-admin/src/main/java/org/dromara/web/service/SysLoginService.java index 0fdd521a0..2eae90ab7 100644 --- a/ruoyi-admin/src/main/java/org/dromara/web/service/SysLoginService.java +++ b/ruoyi-admin/src/main/java/org/dromara/web/service/SysLoginService.java @@ -223,12 +223,12 @@ public class SysLoginService { if (!TenantHelper.isEnable()) { return; } - if (TenantConstants.DEFAULT_TENANT_ID.equals(tenantId)) { - return; - } if (StringUtils.isBlank(tenantId)) { throw new TenantException("tenant.number.not.blank"); } + if (TenantConstants.DEFAULT_TENANT_ID.equals(tenantId)) { + return; + } SysTenantVo tenant = tenantService.queryByTenantId(tenantId); if (ObjectUtil.isNull(tenant)) { log.info("登录租户:{} 不存在.", tenantId); From 71a59d3e5f033f7002e6199e08ed50a91862ffa5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Sat, 23 Nov 2024 07:59:40 +0000 Subject: [PATCH 064/175] =?UTF-8?q?fix=20=E4=BF=AE=E5=A4=8D=20=E8=BF=87?= =?UTF-8?q?=E6=BB=A4=E5=99=A8=E6=AD=A3=E5=88=99=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 疯狂的狮子Li <15040126243@163.com> --- .../aizuda/snailjob/server/starter/filter/SecurityConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruoyi-extend/ruoyi-snailjob-server/src/main/java/com/aizuda/snailjob/server/starter/filter/SecurityConfig.java b/ruoyi-extend/ruoyi-snailjob-server/src/main/java/com/aizuda/snailjob/server/starter/filter/SecurityConfig.java index 3cae8f58e..5196c77ef 100644 --- a/ruoyi-extend/ruoyi-snailjob-server/src/main/java/com/aizuda/snailjob/server/starter/filter/SecurityConfig.java +++ b/ruoyi-extend/ruoyi-snailjob-server/src/main/java/com/aizuda/snailjob/server/starter/filter/SecurityConfig.java @@ -22,7 +22,7 @@ public class SecurityConfig { public FilterRegistrationBean actuatorFilterRegistrationBean() { FilterRegistrationBean registrationBean = new FilterRegistrationBean<>(); registrationBean.setFilter(new ActuatorAuthFilter(username, password)); - registrationBean.addUrlPatterns("/actuator", "/actuator/**"); + registrationBean.addUrlPatterns("/actuator", "/actuator/*"); return registrationBean; } From 7f359257945699f071488027e727dc392a2aeba9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Mon, 25 Nov 2024 10:33:32 +0800 Subject: [PATCH 065/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E9=BB=98=E8=AE=A4=E6=95=B0=E6=8D=AE=E6=9D=83=E9=99=90?= =?UTF-8?q?=20"=E9=83=A8=E9=97=A8=E5=8F=8A=E4=BB=A5=E4=B8=8B=E6=88=96?= =?UTF-8?q?=E6=9C=AC=E4=BA=BA=E6=95=B0=E6=8D=AE=E6=9D=83=E9=99=90"=20?= =?UTF-8?q?=E9=80=89=E9=A1=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/dromara/common/mybatis/enums/DataScopeType.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/enums/DataScopeType.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/enums/DataScopeType.java index 981bd421b..02a5f481f 100644 --- a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/enums/DataScopeType.java +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/enums/DataScopeType.java @@ -48,7 +48,12 @@ public enum DataScopeType { /** * 仅本人数据权限 */ - SELF("5", " #{#userName} = #{#user.userId} ", " 1 = 0 "); + SELF("5", " #{#userName} = #{#user.userId} ", " 1 = 0 "), + + /** + * 部门及以下或本人数据权限 + */ + DEPT_AND_CHILD_OR_SELF("6", " #{#deptName} IN ( #{@sdss.getDeptAndChild( #user.deptId )} ) OR #{#userName} = #{#user.userId} ", " 1 = 0 "); private final String code; From e78684886d9c3d8e955b7e647bd1ed5ce7d10b34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Mon, 25 Nov 2024 11:58:39 +0800 Subject: [PATCH 066/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E6=9D=83=E9=99=90=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../handler/PlusDataPermissionHandler.java | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/PlusDataPermissionHandler.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/PlusDataPermissionHandler.java index 4ae67429f..c529c5332 100644 --- a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/PlusDataPermissionHandler.java +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/PlusDataPermissionHandler.java @@ -36,10 +36,7 @@ import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.expression.spel.support.StandardEvaluationContext; import org.springframework.util.ClassUtils; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Function; @@ -149,14 +146,20 @@ public class PlusDataPermissionHandler { return ""; } boolean isSuccess = false; + List keys = new ArrayList<>(); for (DataColumn dataColumn : dataPermission.value()) { if (dataColumn.key().length != dataColumn.value().length) { throw new ServiceException("角色数据范围异常 => key与value长度不匹配"); } + // 设置注解变量 key 为表达式变量 value 为变量值 + for (int i = 0; i < dataColumn.key().length; i++) { + context.setVariable(dataColumn.key()[i], dataColumn.value()[i]); + } + keys.addAll(Arrays.stream(dataColumn.key()).map(key -> "#" + key).toList()); + } + for (DataColumn dataColumn : dataPermission.value()) { // 不包含 key 变量 则不处理 - if (!StringUtils.containsAny(type.getSqlTemplate(), - Arrays.stream(dataColumn.key()).map(key -> "#" + key).toArray(String[]::new) - )) { + if (!StringUtils.containsAny(type.getSqlTemplate(), keys.toArray(String[]::new))) { continue; } // 包含权限标识符 这直接跳过 @@ -168,10 +171,6 @@ public class PlusDataPermissionHandler { isSuccess = true; continue; } - // 设置注解变量 key 为表达式变量 value 为变量值 - for (int i = 0; i < dataColumn.key().length; i++) { - context.setVariable(dataColumn.key()[i], dataColumn.value()[i]); - } // 忽略数据权限 防止spel表达式内有其他sql查询导致死循环调用 String sql = DataPermissionHelper.ignore(() -> From 1aff46bc1c17f5481d08a80573f6a5089a5e4abf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Tue, 26 Nov 2024 15:38:22 +0800 Subject: [PATCH 067/175] =?UTF-8?q?fix=20=E4=BF=AE=E5=A4=8D=20=E5=AD=97?= =?UTF-8?q?=E6=AE=B5=E9=95=BF=E5=BA=A6=E8=B6=85=E5=87=BA=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E5=BA=93=E9=99=90=E5=88=B6=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/org/dromara/common/log/aspect/LogAspect.java | 8 ++++---- script/sql/oracle/oracle_ry_vue_5.X.sql | 6 +++--- script/sql/postgres/postgres_ry_vue_5.X.sql | 8 ++++---- script/sql/ry_vue_5.X.sql | 8 ++++---- script/sql/sqlserver/sqlserver_ry_vue_5.X.sql | 6 +++--- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/ruoyi-common/ruoyi-common-log/src/main/java/org/dromara/common/log/aspect/LogAspect.java b/ruoyi-common/ruoyi-common-log/src/main/java/org/dromara/common/log/aspect/LogAspect.java index df9e0677d..71b3790b7 100644 --- a/ruoyi-common/ruoyi-common-log/src/main/java/org/dromara/common/log/aspect/LogAspect.java +++ b/ruoyi-common/ruoyi-common-log/src/main/java/org/dromara/common/log/aspect/LogAspect.java @@ -100,7 +100,7 @@ public class LogAspect { if (e != null) { operLog.setStatus(BusinessStatus.FAIL.ordinal()); - operLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 5000)); + operLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 3800)); } // 设置方法名称 String className = joinPoint.getTarget().getClass().getName(); @@ -146,7 +146,7 @@ public class LogAspect { } // 是否需要保存response,参数和值 if (log.isSaveResponseData() && ObjectUtil.isNotNull(jsonResult)) { - operLog.setJsonResult(StringUtils.substring(JsonUtils.toJsonString(jsonResult), 0, 5000)); + operLog.setJsonResult(StringUtils.substring(JsonUtils.toJsonString(jsonResult), 0, 3800)); } } @@ -161,11 +161,11 @@ public class LogAspect { String requestMethod = operLog.getRequestMethod(); if (MapUtil.isEmpty(paramsMap) && StringUtils.equalsAny(requestMethod, HttpMethod.PUT.name(), HttpMethod.POST.name(), HttpMethod.DELETE.name())) { String params = argsArrayToString(joinPoint.getArgs(), excludeParamNames); - operLog.setOperParam(StringUtils.substring(params, 0, 5000)); + operLog.setOperParam(StringUtils.substring(params, 0, 3800)); } else { MapUtil.removeAny(paramsMap, EXCLUDE_PROPERTIES); MapUtil.removeAny(paramsMap, excludeParamNames); - operLog.setOperParam(StringUtils.substring(JsonUtils.toJsonString(paramsMap), 0, 5000)); + operLog.setOperParam(StringUtils.substring(JsonUtils.toJsonString(paramsMap), 0, 3800)); } } diff --git a/script/sql/oracle/oracle_ry_vue_5.X.sql b/script/sql/oracle/oracle_ry_vue_5.X.sql index 08f609e5c..6171b8d31 100644 --- a/script/sql/oracle/oracle_ry_vue_5.X.sql +++ b/script/sql/oracle/oracle_ry_vue_5.X.sql @@ -738,10 +738,10 @@ create table sys_oper_log ( oper_url varchar2(255) default '', oper_ip varchar2(128) default '', oper_location varchar2(255) default '', - oper_param varchar2(5500) default '', - json_result varchar2(5500) default '', + oper_param varchar2(4000) default '', + json_result varchar2(4000) default '', status number(1) default 0, - error_msg varchar2(5500) default '', + error_msg varchar2(4000) default '', oper_time date, cost_time number(20) default 0 ); diff --git a/script/sql/postgres/postgres_ry_vue_5.X.sql b/script/sql/postgres/postgres_ry_vue_5.X.sql index 414350f80..af97ac7dc 100644 --- a/script/sql/postgres/postgres_ry_vue_5.X.sql +++ b/script/sql/postgres/postgres_ry_vue_5.X.sql @@ -741,10 +741,10 @@ create table if not exists sys_oper_log oper_url varchar(255) default ''::varchar, oper_ip varchar(128) default ''::varchar, oper_location varchar(255) default ''::varchar, - oper_param varchar(5000) default ''::varchar, - json_result varchar(5000) default ''::varchar, + oper_param varchar(4000) default ''::varchar, + json_result varchar(4000) default ''::varchar, status int4 default 0, - error_msg varchar(5000) default ''::varchar, + error_msg varchar(4000) default ''::varchar, oper_time timestamp, cost_time int8 default 0, constraint sys_oper_log_pk primary key (oper_id) @@ -1209,7 +1209,7 @@ comment on column sys_oss_config.remark is '备注'; insert into sys_oss_config values (1, '000000', 'minio', 'ruoyi', 'ruoyi123', 'ruoyi', '', '127.0.0.1:9000', '','N', '', '1', '0', '', 103, 1, now(), 1, now(), null); insert into sys_oss_config values (2, '000000', 'qiniu', 'XXXXXXXXXXXXXXX', 'XXXXXXXXXXXXXXX', 'ruoyi', '', 's3-cn-north-1.qiniucs.com', '','N', '', '1', '1', '', 103, 1, now(), 1, now(), null); insert into sys_oss_config values (3, '000000', 'aliyun', 'XXXXXXXXXXXXXXX', 'XXXXXXXXXXXXXXX', 'ruoyi', '', 'oss-cn-beijing.aliyuncs.com', '','N', '', '1', '1', '', 103, 1, now(), 1, now(), null); -insert into sys_oss_config values (4, '000000', 'qcloud', 'XXXXXXXXXXXXXXX', 'XXXXXXXXXXXXXXX', 'ruoyi-1250000000', '', 'cos.ap-beijing.myqcloud.com', '','N', 'ap-beijing', '1', '1', '', 103, 1, now(), 1, now(), null); +insert into sys_oss_config values (4, '000000', 'qcloud', 'XXXXXXXXXXXXXXX', 'XXXXXXXXXXXXXXX', 'ruoyi-1240000000', '', 'cos.ap-beijing.myqcloud.com', '','N', 'ap-beijing', '1', '1', '', 103, 1, now(), 1, now(), null); insert into sys_oss_config values (5, '000000', 'image', 'ruoyi', 'ruoyi123', 'ruoyi', 'image', '127.0.0.1:9000', '','N', '', '1', '1', '', 103, 1, now(), 1, now(), NULL); -- ---------------------------- diff --git a/script/sql/ry_vue_5.X.sql b/script/sql/ry_vue_5.X.sql index 301eee7c7..d73369617 100644 --- a/script/sql/ry_vue_5.X.sql +++ b/script/sql/ry_vue_5.X.sql @@ -554,10 +554,10 @@ create table sys_oper_log ( oper_url varchar(255) default '' comment '请求URL', oper_ip varchar(128) default '' comment '主机地址', oper_location varchar(255) default '' comment '操作地点', - oper_param varchar(5000) default '' comment '请求参数', - json_result varchar(5000) default '' comment '返回参数', + oper_param varchar(4000) default '' comment '请求参数', + json_result varchar(4000) default '' comment '返回参数', status int(1) default 0 comment '操作状态(0正常 1异常)', - error_msg varchar(5000) default '' comment '错误消息', + error_msg varchar(4000) default '' comment '错误消息', oper_time datetime comment '操作时间', cost_time bigint(20) default 0 comment '消耗时间', primary key (oper_id), @@ -840,7 +840,7 @@ create table sys_oss_config ( insert into sys_oss_config values (1, '000000', 'minio', 'ruoyi', 'ruoyi123', 'ruoyi', '', '127.0.0.1:9000', '','N', '', '1' ,'0', '', 103, 1, sysdate(), 1, sysdate(), null); insert into sys_oss_config values (2, '000000', 'qiniu', 'XXXXXXXXXXXXXXX', 'XXXXXXXXXXXXXXX', 'ruoyi', '', 's3-cn-north-1.qiniucs.com', '','N', '', '1' ,'1', '', 103, 1, sysdate(), 1, sysdate(), null); insert into sys_oss_config values (3, '000000', 'aliyun', 'XXXXXXXXXXXXXXX', 'XXXXXXXXXXXXXXX', 'ruoyi', '', 'oss-cn-beijing.aliyuncs.com', '','N', '', '1' ,'1', '', 103, 1, sysdate(), 1, sysdate(), null); -insert into sys_oss_config values (4, '000000', 'qcloud', 'XXXXXXXXXXXXXXX', 'XXXXXXXXXXXXXXX', 'ruoyi-1250000000', '', 'cos.ap-beijing.myqcloud.com', '','N', 'ap-beijing', '1' ,'1', '', 103, 1, sysdate(), 1, sysdate(), null); +insert into sys_oss_config values (4, '000000', 'qcloud', 'XXXXXXXXXXXXXXX', 'XXXXXXXXXXXXXXX', 'ruoyi-1240000000', '', 'cos.ap-beijing.myqcloud.com', '','N', 'ap-beijing', '1' ,'1', '', 103, 1, sysdate(), 1, sysdate(), null); insert into sys_oss_config values (5, '000000', 'image', 'ruoyi', 'ruoyi123', 'ruoyi', 'image', '127.0.0.1:9000', '','N', '', '1' ,'1', '', 103, 1, sysdate(), 1, sysdate(), null); -- ---------------------------- diff --git a/script/sql/sqlserver/sqlserver_ry_vue_5.X.sql b/script/sql/sqlserver/sqlserver_ry_vue_5.X.sql index 7d5ff68a6..bf8661514 100644 --- a/script/sql/sqlserver/sqlserver_ry_vue_5.X.sql +++ b/script/sql/sqlserver/sqlserver_ry_vue_5.X.sql @@ -2002,10 +2002,10 @@ CREATE TABLE sys_oper_log oper_url nvarchar(255) DEFAULT '' NULL, oper_ip nvarchar(128) DEFAULT '' NULL, oper_location nvarchar(255) DEFAULT '' NULL, - oper_param nvarchar(5000) DEFAULT '' NULL, - json_result nvarchar(5000) DEFAULT '' NULL, + oper_param nvarchar(4000) DEFAULT '' NULL, + json_result nvarchar(4000) DEFAULT '' NULL, status int DEFAULT ((0)) NULL, - error_msg nvarchar(5000) DEFAULT '' NULL, + error_msg nvarchar(4000) DEFAULT '' NULL, oper_time datetime2(7) NULL, cost_time bigint DEFAULT ((0)) NULL, CONSTRAINT PK__sys_oper__34723BF9BD954573 PRIMARY KEY CLUSTERED (oper_id) From eba6b48daf43912df11128cc1e40ecf661cde2bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Tue, 26 Nov 2024 16:29:26 +0800 Subject: [PATCH 068/175] update springdoc 2.6.0 => 2.7.0 update redisson 3.37.0 => 3.39.0 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 1591c0cb0..8186079bc 100644 --- a/pom.xml +++ b/pom.xml @@ -19,7 +19,7 @@ UTF-8 17 3.5.16 - 2.6.0 + 2.7.0 0.15.0 4.0.3 2.3 @@ -28,7 +28,7 @@ 3.9.1 5.8.31 3.3.4 - 3.37.0 + 3.39.0 2.2.7 4.3.1 1.2.0 From 8dc4b5cf6b45bc9044ea7ef2330eba2e8d943422 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Wed, 27 Nov 2024 15:22:05 +0800 Subject: [PATCH 069/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E7=A7=9F?= =?UTF-8?q?=E6=88=B7=E6=97=A5=E5=BF=97=E6=A8=A1=E5=9D=97=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/system/SysTenantController.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysTenantController.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysTenantController.java index 10c6777e7..66c1b7ddf 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysTenantController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysTenantController.java @@ -59,7 +59,7 @@ public class SysTenantController extends BaseController { */ @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY) @SaCheckPermission("system:tenant:export") - @Log(title = "租户", businessType = BusinessType.EXPORT) + @Log(title = "租户管理", businessType = BusinessType.EXPORT) @PostMapping("/export") public void export(SysTenantBo bo, HttpServletResponse response) { List list = tenantService.queryList(bo); @@ -85,7 +85,7 @@ public class SysTenantController extends BaseController { @ApiEncrypt @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY) @SaCheckPermission("system:tenant:add") - @Log(title = "租户", businessType = BusinessType.INSERT) + @Log(title = "租户管理", businessType = BusinessType.INSERT) @Lock4j @RepeatSubmit() @PostMapping() @@ -101,7 +101,7 @@ public class SysTenantController extends BaseController { */ @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY) @SaCheckPermission("system:tenant:edit") - @Log(title = "租户", businessType = BusinessType.UPDATE) + @Log(title = "租户管理", businessType = BusinessType.UPDATE) @RepeatSubmit() @PutMapping() public R edit(@Validated(EditGroup.class) @RequestBody SysTenantBo bo) { @@ -117,7 +117,7 @@ public class SysTenantController extends BaseController { */ @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY) @SaCheckPermission("system:tenant:edit") - @Log(title = "租户", businessType = BusinessType.UPDATE) + @Log(title = "租户管理", businessType = BusinessType.UPDATE) @PutMapping("/changeStatus") public R changeStatus(@RequestBody SysTenantBo bo) { tenantService.checkTenantAllowed(bo.getTenantId()); @@ -131,7 +131,7 @@ public class SysTenantController extends BaseController { */ @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY) @SaCheckPermission("system:tenant:remove") - @Log(title = "租户", businessType = BusinessType.DELETE) + @Log(title = "租户管理", businessType = BusinessType.DELETE) @DeleteMapping("/{ids}") public R remove(@NotEmpty(message = "主键不能为空") @PathVariable Long[] ids) { @@ -169,7 +169,7 @@ public class SysTenantController extends BaseController { */ @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY) @SaCheckPermission("system:tenant:edit") - @Log(title = "租户", businessType = BusinessType.UPDATE) + @Log(title = "租户管理", businessType = BusinessType.UPDATE) @GetMapping("/syncTenantPackage") public R syncTenantPackage(@NotBlank(message = "租户ID不能为空") String tenantId, @NotNull(message = "套餐ID不能为空") Long packageId) { @@ -180,7 +180,7 @@ public class SysTenantController extends BaseController { * 同步租户字典 */ @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY) - @Log(title = "同步租户字典", businessType = BusinessType.INSERT) + @Log(title = "租户管理", businessType = BusinessType.INSERT) @GetMapping("/syncTenantDict") public R syncTenantDict() { if (!TenantHelper.isEnable()) { From 476c7a77c8e45f9a51d26e077dc9ddbd8045fae5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Wed, 27 Nov 2024 18:23:10 +0800 Subject: [PATCH 070/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20redis?= =?UTF-8?q?=E5=BA=8F=E5=88=97=E5=8C=96=20=E6=94=AF=E6=8C=81=E6=9B=B4?= =?UTF-8?q?=E5=BF=AB=E7=9A=84apache=E4=BA=8C=E8=BF=9B=E5=88=B6=E8=B7=A8?= =?UTF-8?q?=E8=AF=AD=E8=A8=80=E5=BA=8F=E5=88=97=E5=8C=96=E6=96=B9=E6=A1=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ruoyi-admin/src/main/resources/application.yml | 1 + ruoyi-common/ruoyi-common-redis/pom.xml | 12 ++++++++++++ .../org/dromara/common/redis/config/RedisConfig.java | 3 +++ 3 files changed, 16 insertions(+) diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml index f05bdaf85..33fbcb7ab 100644 --- a/ruoyi-admin/src/main/resources/application.yml +++ b/ruoyi-admin/src/main/resources/application.yml @@ -47,6 +47,7 @@ logging: org.dromara: @logging.level@ org.springframework: warn org.mybatis.spring.mapper: error + org.apache.fury: warn config: classpath:logback-plus.xml # 用户配置 diff --git a/ruoyi-common/ruoyi-common-redis/pom.xml b/ruoyi-common/ruoyi-common-redis/pom.xml index f56f8aad3..d7d99cacc 100644 --- a/ruoyi-common/ruoyi-common-redis/pom.xml +++ b/ruoyi-common/ruoyi-common-redis/pom.xml @@ -42,6 +42,18 @@ com.fasterxml.jackson.datatype jackson-datatype-jsr310 + + + + + + + + + + + + diff --git a/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/config/RedisConfig.java b/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/config/RedisConfig.java index f8fe79a8c..7ba94751a 100644 --- a/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/config/RedisConfig.java +++ b/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/config/RedisConfig.java @@ -53,6 +53,9 @@ public class RedisConfig { om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); // 指定序列化输入的类型,类必须是非final修饰的。序列化时将对象全类名一起保存下来 om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL); +// LoggerFactory.useSlf4jLogging(true); +// FuryCodec furyCodec = new FuryCodec(); +// CompositeCodec codec = new CompositeCodec(StringCodec.INSTANCE, furyCodec, furyCodec); TypedJsonJacksonCodec jsonCodec = new TypedJsonJacksonCodec(Object.class, om); // 组合序列化 key 使用 String 内容使用通用 json 格式 CompositeCodec codec = new CompositeCodec(StringCodec.INSTANCE, jsonCodec, jsonCodec); From 99d9c516fc12ee4b12f38eb4fdbb0c8143586649 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Fri, 29 Nov 2024 16:21:19 +0800 Subject: [PATCH 071/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E9=94=80?= =?UTF-8?q?=E6=AF=81=E7=AD=96=E7=95=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/org/dromara/common/redis/utils/QueueUtils.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/QueueUtils.java b/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/QueueUtils.java index e436a467f..ebef0ad72 100644 --- a/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/QueueUtils.java +++ b/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/QueueUtils.java @@ -174,11 +174,11 @@ public class QueueUtils { * * @param queueName 队列名 * @param capacity 容量 - * @param destroy 已存在是否销毁 + * @param destroy 是否销毁 */ public static boolean trySetBoundedQueueCapacity(String queueName, int capacity, boolean destroy) { RBoundedBlockingQueue boundedBlockingQueue = CLIENT.getBoundedBlockingQueue(queueName); - if (boundedBlockingQueue.isExists() && destroy) { + if (destroy) { destroyQueue(queueName); } return boundedBlockingQueue.trySetCapacity(capacity); From 87294b41affcfbd990af235c7f85f08e43d31654 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Fri, 29 Nov 2024 16:26:56 +0800 Subject: [PATCH 072/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E6=9C=89?= =?UTF-8?q?=E7=95=8C=E9=98=9F=E5=88=97=E9=94=80=E6=AF=81=E6=96=B9=E5=BC=8F?= =?UTF-8?q?=20=E5=BA=94=E8=AF=A5=E4=BD=BF=E7=94=A8=E7=89=B9=E6=AE=8A?= =?UTF-8?q?=E9=94=80=E6=AF=81=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/org/dromara/common/redis/utils/QueueUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/QueueUtils.java b/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/QueueUtils.java index ebef0ad72..7c09e3138 100644 --- a/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/QueueUtils.java +++ b/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/QueueUtils.java @@ -179,7 +179,7 @@ public class QueueUtils { public static boolean trySetBoundedQueueCapacity(String queueName, int capacity, boolean destroy) { RBoundedBlockingQueue boundedBlockingQueue = CLIENT.getBoundedBlockingQueue(queueName); if (destroy) { - destroyQueue(queueName); + boundedBlockingQueue.delete(); } return boundedBlockingQueue.trySetCapacity(capacity); } From fef2d5207b88212bff6fb8d518d4776c2e3af28a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Mon, 2 Dec 2024 09:36:46 +0800 Subject: [PATCH 073/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E7=94=B1?= =?UTF-8?q?=E4=BA=8Esse=E9=87=8D=E8=AF=95=E6=9C=BA=E5=88=B6=E5=AF=BC?= =?UTF-8?q?=E8=87=B4=E7=BB=8F=E5=B8=B8=E8=BE=93=E5=87=BA=E8=AE=A4=E8=AF=81?= =?UTF-8?q?=E5=A4=B1=E8=B4=A5=E6=97=A5=E5=BF=97=E8=BF=87=E5=A4=9A=20?= =?UTF-8?q?=E5=B0=86sse=E5=A4=B1=E8=B4=A5=E6=94=B9=E4=B8=BAdebug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/dromara/common/web/handler/GlobalExceptionHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/handler/GlobalExceptionHandler.java b/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/handler/GlobalExceptionHandler.java index 321c22615..0a60fbcc7 100644 --- a/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/handler/GlobalExceptionHandler.java +++ b/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/handler/GlobalExceptionHandler.java @@ -63,7 +63,7 @@ public class GlobalExceptionHandler { @ExceptionHandler(SseException.class) public String handleNotLoginException(SseException e, HttpServletRequest request) { String requestURI = request.getRequestURI(); - log.error("请求地址'{}',认证失败'{}',无法访问系统资源", requestURI, e.getMessage()); + log.debug("请求地址'{}',认证失败'{}',无法访问系统资源", requestURI, e.getMessage()); return JsonUtils.toJsonString(R.fail(HttpStatus.HTTP_UNAUTHORIZED, "认证失败,无法访问系统资源")); } From eda67dd5724dee940737859ad82f4356b2feb6a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Mon, 2 Dec 2024 10:05:25 +0800 Subject: [PATCH 074/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E7=94=9F=E6=88=90=E5=99=A8=20=E5=B0=86=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E5=BA=93=E5=AD=97=E6=AE=B5=E9=BB=98=E8=AE=A4=E8=BD=AC?= =?UTF-8?q?=E4=B8=BA=E5=B0=8F=E5=86=99=20=E9=81=BF=E5=85=8D=E6=9F=90?= =?UTF-8?q?=E4=BA=9B=E6=95=B0=E6=8D=AE=E5=BA=93=E5=A4=A7=E5=86=99=E5=87=BA?= =?UTF-8?q?=E7=8E=B0=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/org/dromara/generator/util/GenUtils.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/util/GenUtils.java b/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/util/GenUtils.java index 0981997d8..53b433502 100644 --- a/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/util/GenUtils.java +++ b/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/util/GenUtils.java @@ -36,7 +36,8 @@ public class GenUtils { */ public static void initColumnField(GenTableColumn column, GenTable table) { String dataType = getDbType(column.getColumnType()); - String columnName = column.getColumnName(); + // 统一转小写 避免有些数据库默认大写问题 如果需要特别书写方式 请在实体类增加注解标注别名 + String columnName = column.getColumnName().toLowerCase(); column.setTableId(table.getTableId()); // 设置java字段名 column.setJavaField(StringUtils.toCamelCase(columnName)); From eed929b9fef6eae14dfa19e2c57aa26caa1b9104 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Mon, 2 Dec 2024 23:24:16 +0800 Subject: [PATCH 075/175] =?UTF-8?q?fix=20=E4=BF=AE=E5=A4=8D=20=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E7=94=9F=E6=88=90=20=E8=A1=A8=E5=90=8D=E4=B8=AD?= =?UTF-8?q?=E9=97=B4=E5=B8=A6=E6=9C=89=E7=89=B9=E6=AE=8A=E5=AD=97=E7=AC=A6?= =?UTF-8?q?=E8=A2=AB=E8=BF=87=E6=BB=A4=E9=97=AE=E9=A2=98=20=E6=94=B9?= =?UTF-8?q?=E4=B8=BA=E5=BC=80=E5=A4=B4=E8=BF=87=E6=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/org/dromara/generator/service/GenTableServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java b/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java index d3f4dded3..ff6a2d8d6 100644 --- a/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java +++ b/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java @@ -202,7 +202,7 @@ public class GenTableServiceImpl implements IGenTableService { } List> tableList = tablesMap.values().stream() - .filter(x -> !StringUtils.containsAnyIgnoreCase(x.getName(), TABLE_IGNORE)) + .filter(x -> !startWithAnyIgnoreCase(x.getName(), TABLE_IGNORE)) .filter(x -> tableNameSet.contains(x.getName())).toList(); if (CollUtil.isEmpty(tableList)) { From 14c1bde958e72a0e254252a3cf432fcadf1d4e99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Tue, 3 Dec 2024 11:00:54 +0800 Subject: [PATCH 076/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E7=A7=9F?= =?UTF-8?q?=E6=88=B7=E5=9F=9F=E5=90=8D=E4=BD=BF=E7=94=A8=E5=BF=BD=E7=95=A5?= =?UTF-8?q?=E5=A4=A7=E5=B0=8F=E5=86=99=E5=8C=B9=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/org/dromara/web/controller/AuthController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruoyi-admin/src/main/java/org/dromara/web/controller/AuthController.java b/ruoyi-admin/src/main/java/org/dromara/web/controller/AuthController.java index 89fe607f6..c1ffef3d3 100644 --- a/ruoyi-admin/src/main/java/org/dromara/web/controller/AuthController.java +++ b/ruoyi-admin/src/main/java/org/dromara/web/controller/AuthController.java @@ -226,7 +226,7 @@ public class AuthController { } // 根据域名进行筛选 List list = StreamUtils.filter(voList, vo -> - StringUtils.equals(vo.getDomain(), host)); + StringUtils.equalsIgnoreCase(vo.getDomain(), host)); result.setVoList(CollUtil.isNotEmpty(list) ? list : voList); return R.ok(result); } From 19aed0a1e494edef38e15e7d854b63cc92afd6d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Wed, 4 Dec 2024 10:11:41 +0800 Subject: [PATCH 077/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE=E5=90=8D=E5=89=8D=E5=A2=9E=E5=8A=A0=E7=A4=BE=E5=8C=BA?= =?UTF-8?q?=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b37eaf91f..5ed7878f1 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ [![JDK-17](https://img.shields.io/badge/JDK-17-green.svg)]() [![JDK-21](https://img.shields.io/badge/JDK-21-green.svg)]() -> RuoYi-Vue-Plus 是重写 RuoYi-Vue 针对 `分布式集群与多租户` 场景全方位升级(不兼容原框架) +> Dromara RuoYi-Vue-Plus 是重写 RuoYi-Vue 针对 `分布式集群与多租户` 场景全方位升级(不兼容原框架) > 项目代码、文档 均开源免费可商用 遵循开源协议在项目中保留开源协议文件即可
活到老写到老 为兴趣而开源 为学习而开源 为让大家真正可以学到技术而开源 diff --git a/pom.xml b/pom.xml index 8186079bc..e3b9b8456 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ RuoYi-Vue-Plus https://gitee.com/dromara/RuoYi-Vue-Plus - RuoYi-Vue-Plus多租户管理系统 + Dromara RuoYi-Vue-Plus多租户管理系统 5.2.3 From c17225abb16c5e459e7af34e5f147c15583fa557 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Fri, 6 Dec 2024 10:11:38 +0800 Subject: [PATCH 078/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E5=9C=A8?= =?UTF-8?q?=E7=BA=BF=E7=94=A8=E6=88=B7=E6=9F=A5=E8=AF=A2=20=E4=BC=98?= =?UTF-8?q?=E5=85=88=E6=9F=A5=E8=AF=A2=E7=A7=9F=E6=88=B7=E4=B8=8B=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=20=E5=87=8F=E5=B0=91=E6=95=B0=E6=8D=AE=E9=87=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../system/controller/monitor/SysUserOnlineController.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/monitor/SysUserOnlineController.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/monitor/SysUserOnlineController.java index 95439a266..1cab23251 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/monitor/SysUserOnlineController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/monitor/SysUserOnlineController.java @@ -19,6 +19,7 @@ import org.dromara.system.domain.SysUserOnline; import org.springframework.web.bind.annotation.*; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; @@ -43,7 +44,7 @@ public class SysUserOnlineController extends BaseController { @GetMapping("/list") public TableDataInfo list(String ipaddr, String userName) { // 获取所有未过期的 token - List keys = StpUtil.searchTokenValue("", 0, -1, false); + Collection keys = RedisUtils.keys(CacheConstants.ONLINE_TOKEN_KEY + "*"); List userOnlineDTOList = new ArrayList<>(); for (String key : keys) { String token = StringUtils.substringAfterLast(key, ":"); From e0b0ffcb289a9fc98b3660a0e7e391f8899518f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Fri, 6 Dec 2024 14:02:46 +0800 Subject: [PATCH 079/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E4=B9=A6?= =?UTF-8?q?=E5=86=99=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index e3b9b8456..58672cae4 100644 --- a/pom.xml +++ b/pom.xml @@ -55,7 +55,7 @@ 3.2.2 3.2.2 - 3.11.0 + 3.11.0 3.1.2 1.3.0 @@ -375,7 +375,7 @@ org.apache.maven.plugins maven-compiler-plugin - ${maven-compiler-plugin.verison} + ${maven-compiler-plugin.version} ${java.version} ${java.version} From 64d574cf06245c6712a3e5a3e73b9f345e446736 Mon Sep 17 00:00:00 2001 From: AprilWind <2100166581@qq.com> Date: Mon, 9 Dec 2024 11:20:05 +0800 Subject: [PATCH 080/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E7=94=9F=E6=88=90=E6=8E=92=E5=BA=8F=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/dromara/generator/service/GenTableServiceImpl.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java b/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java index ff6a2d8d6..e8f3a2e50 100644 --- a/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java +++ b/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java @@ -106,7 +106,7 @@ public class GenTableServiceImpl implements IGenTableService { .like(StringUtils.isNotBlank(genTable.getTableComment()), "lower(table_comment)", StringUtils.lowerCase(genTable.getTableComment())) .between(params.get("beginTime") != null && params.get("endTime") != null, "create_time", params.get("beginTime"), params.get("endTime")) - .orderByAsc("table_id"); + .orderByDesc("update_time", "create_time"); return wrapper; } @@ -165,7 +165,8 @@ public class GenTableServiceImpl implements IGenTableService { gen.setCreateTime(x.getCreateTime()); gen.setUpdateTime(x.getUpdateTime()); return gen; - }).toList(); + }).sorted(Comparator.comparing(GenTable::getCreateTime).reversed()) + .toList(); IPage page = pageQuery.build(); page.setTotal(tables.size()); @@ -274,6 +275,7 @@ public class GenTableServiceImpl implements IGenTableService { String tableName = table.getTableName(); GenUtils.initTable(table); table.setDataName(dataName); + table.setCreateTime(new Date()); int row = baseMapper.insert(table); if (row > 0) { // 保存列信息 From ed6f8262c6e511edd72f87c667b70eb35b01c6f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Mon, 9 Dec 2024 12:39:27 +0800 Subject: [PATCH 081/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E7=94=9F=E6=88=90=20=E5=88=9B=E5=BB=BA=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E6=97=B6=E9=97=B4=E8=A2=AB=E8=A6=86=E7=9B=96=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/dromara/generator/service/GenTableServiceImpl.java | 3 +-- .../src/main/java/org/dromara/generator/util/GenUtils.java | 4 ++++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java b/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java index e8f3a2e50..7eb99eb59 100644 --- a/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java +++ b/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java @@ -106,7 +106,7 @@ public class GenTableServiceImpl implements IGenTableService { .like(StringUtils.isNotBlank(genTable.getTableComment()), "lower(table_comment)", StringUtils.lowerCase(genTable.getTableComment())) .between(params.get("beginTime") != null && params.get("endTime") != null, "create_time", params.get("beginTime"), params.get("endTime")) - .orderByDesc("update_time", "create_time"); + .orderByDesc("update_time"); return wrapper; } @@ -275,7 +275,6 @@ public class GenTableServiceImpl implements IGenTableService { String tableName = table.getTableName(); GenUtils.initTable(table); table.setDataName(dataName); - table.setCreateTime(new Date()); int row = baseMapper.insert(table); if (row > 0) { // 保存列信息 diff --git a/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/util/GenUtils.java b/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/util/GenUtils.java index 53b433502..996cf9b71 100644 --- a/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/util/GenUtils.java +++ b/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/util/GenUtils.java @@ -29,6 +29,8 @@ public class GenUtils { genTable.setBusinessName(getBusinessName(genTable.getTableName())); genTable.setFunctionName(replaceText(genTable.getTableComment())); genTable.setFunctionAuthor(GenConfig.getAuthor()); + genTable.setCreateTime(null); + genTable.setUpdateTime(null); } /** @@ -39,6 +41,8 @@ public class GenUtils { // 统一转小写 避免有些数据库默认大写问题 如果需要特别书写方式 请在实体类增加注解标注别名 String columnName = column.getColumnName().toLowerCase(); column.setTableId(table.getTableId()); + column.setCreateTime(null); + column.setUpdateTime(null); // 设置java字段名 column.setJavaField(StringUtils.toCamelCase(columnName)); // 设置默认类型 From 2bb787886d23b6bded217a1622c80cbf7180baf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Mon, 9 Dec 2024 12:42:36 +0800 Subject: [PATCH 082/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E7=94=9F=E6=88=90=20=E5=A2=9E=E5=8A=A0buildQueryWrapp?= =?UTF-8?q?er=E9=BB=98=E8=AE=A4=E6=8E=92=E5=BA=8F=E8=A7=84=E5=88=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/vm/java/serviceImpl.java.vm | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/serviceImpl.java.vm b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/serviceImpl.java.vm index 67690ca6e..0df655bd2 100644 --- a/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/serviceImpl.java.vm +++ b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/serviceImpl.java.vm @@ -95,6 +95,9 @@ public class ${ClassName}ServiceImpl implements I${ClassName}Service { ${ClassName}::get$AttrName ,params.get("begin$AttrName"), params.get("end$AttrName")); #end #end +#if($column.isPk==1) + lqw.orderByAsc(${ClassName}::get$AttrName); +#end #end return lqw; } From 5e6cb0dd3c083ef98642ee02b83e9eeeb7208630 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Mon, 9 Dec 2024 13:31:17 +0800 Subject: [PATCH 083/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E7=94=9F=E6=88=90=20=E5=A2=9E=E5=8A=A0buildQueryWrapp?= =?UTF-8?q?er=E9=BB=98=E8=AE=A4=E6=8E=92=E5=BA=8F=E8=A7=84=E5=88=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/vm/java/serviceImpl.java.vm | 1 + 1 file changed, 1 insertion(+) diff --git a/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/serviceImpl.java.vm b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/serviceImpl.java.vm index 0df655bd2..48cc8b15b 100644 --- a/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/serviceImpl.java.vm +++ b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/serviceImpl.java.vm @@ -95,6 +95,7 @@ public class ${ClassName}ServiceImpl implements I${ClassName}Service { ${ClassName}::get$AttrName ,params.get("begin$AttrName"), params.get("end$AttrName")); #end #end +#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) #if($column.isPk==1) lqw.orderByAsc(${ClassName}::get$AttrName); #end From 9e613488f1a01563913b4f6aade062980a315fea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A7=8B=E8=BE=9E=E6=9C=AA=E5=AF=92?= <545073804@qq.com> Date: Mon, 9 Dec 2024 09:03:31 +0000 Subject: [PATCH 084/175] =?UTF-8?q?add=20=E6=96=B0=E5=A2=9E=20validation?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E6=9E=9A=E4=B8=BE=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 秋辞未寒 <545073804@qq.com> --- .../core/validate/enumd/EnumPattern.java | 39 +++++++++++++++++ .../validate/enumd/EnumPatternValidator.java | 43 +++++++++++++++++++ .../core/validate/enumd/ValidateEnum.java | 29 +++++++++++++ 3 files changed, 111 insertions(+) create mode 100644 ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/validate/enumd/EnumPattern.java create mode 100644 ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/validate/enumd/EnumPatternValidator.java create mode 100644 ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/validate/enumd/ValidateEnum.java diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/validate/enumd/EnumPattern.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/validate/enumd/EnumPattern.java new file mode 100644 index 000000000..2f7de7550 --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/validate/enumd/EnumPattern.java @@ -0,0 +1,39 @@ +package org.dromara.common.core.validate.enumd; + +import jakarta.validation.Constraint; +import jakarta.validation.Payload; + +import java.lang.annotation.*; + +import static java.lang.annotation.ElementType.*; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * 自定义枚举校验注解 + * + * @author 秋辞未寒 + * @date 2024-12-09 + */ +@Documented +@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE}) +@Retention(RUNTIME) +@Repeatable(EnumPattern.List.class) // 允许在同一元素上多次使用该注解 +@Constraint(validatedBy = {EnumPatternValidator.class}) +public @interface EnumPattern { + + Class type() default ValidateEnum.class; + + String message() default "输入值不在枚举范围内"; + + Class[] groups() default {}; + + Class[] payload() default {}; + + @Documented + @Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE}) + @Retention(RUNTIME) + @interface List { + EnumPattern[] value(); + } + +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/validate/enumd/EnumPatternValidator.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/validate/enumd/EnumPatternValidator.java new file mode 100644 index 000000000..451dc71a7 --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/validate/enumd/EnumPatternValidator.java @@ -0,0 +1,43 @@ +package org.dromara.common.core.validate.enumd; + +import org.dromara.common.core.utils.StringUtils; +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; +import jakarta.validation.ValidationException; +import lombok.extern.slf4j.Slf4j; + +/** + * 自定义枚举校验注解实现 + * + * @author 秋辞未寒 + * @date 2024-12-09 + */ +public class EnumPatternValidator implements ConstraintValidator { + + private EnumPattern annotation;; + + @Override + public void initialize(EnumPattern annotation) { + ConstraintValidator.super.initialize(annotation); + this.annotation = annotation; + } + + @Override + public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext) { + try { + if (StringUtils.isNotBlank(value)) { + Class type = annotation.type(); + ValidateEnum[] constants = type.getEnumConstants(); + for (ValidateEnum e : constants) { + if (e.validate(value)) { + return true; + } + } + } + return false; + } catch (Exception e) { + throw new ValidationException(e); + } + } + +} \ No newline at end of file diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/validate/enumd/ValidateEnum.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/validate/enumd/ValidateEnum.java new file mode 100644 index 000000000..f3a367c8f --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/validate/enumd/ValidateEnum.java @@ -0,0 +1,29 @@ +package org.dromara.common.core.validate.enumd; + +import org.dromara.common.core.utils.StringUtils; + +/** + * 枚举类型校验接口 + * + * @author 秋辞未寒 + * @date 2024-12-09 + */ +public interface ValidateEnum { + + /** + * 获取枚举code + *

该code用于匹配
+ * @return 枚举code + */ + String getCode(); + + /** + * 校验枚举code + * @param code 枚举code + * @return 校验结果 + */ + default boolean validate(String code) { + return StringUtils.equals(code, getCode()); + } + +} From fc9c90ad998e53ed6378a21bd1df10fe826fb22d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Mon, 9 Dec 2024 17:35:53 +0800 Subject: [PATCH 085/175] =?UTF-8?q?fix=20=E4=BF=AE=E5=A4=8D=20=E4=B8=89?= =?UTF-8?q?=E6=96=B9=E7=BC=BA=E5=A4=B1=E5=8F=82=E6=95=B0=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/org/dromara/common/social/utils/SocialUtils.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/utils/SocialUtils.java b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/utils/SocialUtils.java index 9191fca77..357256d52 100644 --- a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/utils/SocialUtils.java +++ b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/utils/SocialUtils.java @@ -58,9 +58,9 @@ public class SocialUtils { case "linkedin" -> new AuthLinkedinRequest(builder.build(), STATE_CACHE); case "microsoft" -> new AuthMicrosoftRequest(builder.build(), STATE_CACHE); case "renren" -> new AuthRenrenRequest(builder.build(), STATE_CACHE); - case "stack_overflow" -> new AuthStackOverflowRequest(builder.build(), STATE_CACHE); + case "stack_overflow" -> new AuthStackOverflowRequest(builder.stackOverflowKey(obj.getStackOverflowKey()).build(), STATE_CACHE); case "huawei" -> new AuthHuaweiRequest(builder.build(), STATE_CACHE); - case "wechat_enterprise" -> new AuthWeChatEnterpriseQrcodeRequest(builder.build(), STATE_CACHE); + case "wechat_enterprise" -> new AuthWeChatEnterpriseQrcodeRequest(builder.agentId(obj.getAgentId()).build(), STATE_CACHE); case "gitlab" -> new AuthGitlabRequest(builder.build(), STATE_CACHE); case "wechat_mp" -> new AuthWeChatMpRequest(builder.build(), STATE_CACHE); case "aliyun" -> new AuthAliyunRequest(builder.build(), STATE_CACHE); From 9009a90ef27754a81ba86932663d33e176942d4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A7=8B=E8=BE=9E=E6=9C=AA=E5=AF=92?= <545073804@qq.com> Date: Mon, 9 Dec 2024 09:41:52 +0000 Subject: [PATCH 086/175] =?UTF-8?q?update=20=E6=9B=B4=E6=96=B0=20=E6=9E=9A?= =?UTF-8?q?=E4=B8=BE=E6=A0=A1=E9=AA=8C=E9=80=9A=E8=BF=87=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E6=9E=9A=E4=B8=BE=E5=80=BC=EF=BC=8C=E4=B8=8D=E5=86=8D=E9=9C=80?= =?UTF-8?q?=E8=A6=81=E5=AE=9E=E7=8E=B0=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 秋辞未寒 <545073804@qq.com> --- .../common/core/validate/enumd/EnumPattern.java | 10 +++++++++- .../core/validate/enumd/EnumPatternValidator.java | 10 ++++++---- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/validate/enumd/EnumPattern.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/validate/enumd/EnumPattern.java index 2f7de7550..35f7ecbe3 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/validate/enumd/EnumPattern.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/validate/enumd/EnumPattern.java @@ -21,7 +21,15 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME; @Constraint(validatedBy = {EnumPatternValidator.class}) public @interface EnumPattern { - Class type() default ValidateEnum.class; + /** + * 需要校验的枚举类型 + */ + Class type() default Enum.class; + + /** + * 枚举类型校验值判断方法 + */ + String method() default "getCode"; String message() default "输入值不在枚举范围内"; diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/validate/enumd/EnumPatternValidator.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/validate/enumd/EnumPatternValidator.java index 451dc71a7..af87225a6 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/validate/enumd/EnumPatternValidator.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/validate/enumd/EnumPatternValidator.java @@ -1,6 +1,7 @@ package org.dromara.common.core.validate.enumd; import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.core.utils.reflect.ReflectUtils; import jakarta.validation.ConstraintValidator; import jakarta.validation.ConstraintValidatorContext; import jakarta.validation.ValidationException; @@ -26,10 +27,11 @@ public class EnumPatternValidator implements ConstraintValidator type = annotation.type(); - ValidateEnum[] constants = type.getEnumConstants(); - for (ValidateEnum e : constants) { - if (e.validate(value)) { + Class type = annotation.type(); + Object[] enumConstants = type.getEnumConstants(); + Method method = ReflectUtils.getMethod(type, annotation.method()); + for (Object e : enumConstants) { + if (value.equals(method.invoke(e))) { return true; } } From a1f82a7d0855db0eb19c66d909bed4c76a77f7a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A7=8B=E8=BE=9E=E6=9C=AA=E5=AF=92?= <545073804@qq.com> Date: Mon, 9 Dec 2024 09:43:01 +0000 Subject: [PATCH 087/175] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20?= =?UTF-8?q?ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common?= =?UTF-8?q?/core/validate/enumd/ValidateEnum.java?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/validate/enumd/ValidateEnum.java | 29 ------------------- 1 file changed, 29 deletions(-) delete mode 100644 ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/validate/enumd/ValidateEnum.java diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/validate/enumd/ValidateEnum.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/validate/enumd/ValidateEnum.java deleted file mode 100644 index f3a367c8f..000000000 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/validate/enumd/ValidateEnum.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.dromara.common.core.validate.enumd; - -import org.dromara.common.core.utils.StringUtils; - -/** - * 枚举类型校验接口 - * - * @author 秋辞未寒 - * @date 2024-12-09 - */ -public interface ValidateEnum { - - /** - * 获取枚举code - *
该code用于匹配
- * @return 枚举code - */ - String getCode(); - - /** - * 校验枚举code - * @param code 枚举code - * @return 校验结果 - */ - default boolean validate(String code) { - return StringUtils.equals(code, getCode()); - } - -} From 4821902fdc73052b56a0b39ebe60e0c7287b254e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A7=8B=E8=BE=9E=E6=9C=AA=E5=AF=92?= <545073804@qq.com> Date: Mon, 9 Dec 2024 10:16:49 +0000 Subject: [PATCH 088/175] =?UTF-8?q?update=20=E6=9B=B4=E6=96=B0=20=E6=9E=9A?= =?UTF-8?q?=E4=B8=BE=E6=A0=A1=E9=AA=8C=E9=80=9A=E8=BF=87=E6=9E=9A=E4=B8=BE?= =?UTF-8?q?=E5=AD=97=E6=AE=B5=E7=9A=84getter=E6=96=B9=E6=B3=95=E5=8F=96?= =?UTF-8?q?=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 秋辞未寒 <545073804@qq.com> --- .../dromara/common/core/validate/enumd/EnumPattern.java | 7 ++++--- .../common/core/validate/enumd/EnumPatternValidator.java | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/validate/enumd/EnumPattern.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/validate/enumd/EnumPattern.java index 35f7ecbe3..c31c7703c 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/validate/enumd/EnumPattern.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/validate/enumd/EnumPattern.java @@ -9,7 +9,7 @@ import static java.lang.annotation.ElementType.*; import static java.lang.annotation.RetentionPolicy.RUNTIME; /** - * 自定义枚举校验注解 + * 自定义枚举校验 * * @author 秋辞未寒 * @date 2024-12-09 @@ -27,9 +27,10 @@ public @interface EnumPattern { Class type() default Enum.class; /** - * 枚举类型校验值判断方法 + * 枚举类型校验值字段名称 + * TODO 需确保该字段实现了 getter 方法 */ - String method() default "getCode"; + String fieldName() default "code"; String message() default "输入值不在枚举范围内"; diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/validate/enumd/EnumPatternValidator.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/validate/enumd/EnumPatternValidator.java index af87225a6..0e748c0a4 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/validate/enumd/EnumPatternValidator.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/validate/enumd/EnumPatternValidator.java @@ -28,10 +28,10 @@ public class EnumPatternValidator implements ConstraintValidator type = annotation.type(); + String fieldName = annotation.fieldName(); Object[] enumConstants = type.getEnumConstants(); - Method method = ReflectUtils.getMethod(type, annotation.method()); for (Object e : enumConstants) { - if (value.equals(method.invoke(e))) { + if (value.equals(ReflectUtils.invokeGetter(e, fieldName))) { return true; } } From d257de78825ebc812dad1d138035c4b07b8991d1 Mon Sep 17 00:00:00 2001 From: AprilWind <2100166581@qq.com> Date: Tue, 10 Dec 2024 11:47:13 +0800 Subject: [PATCH 089/175] =?UTF-8?q?update=20=E5=85=BC=E5=AE=B9=E4=BA=91?= =?UTF-8?q?=E5=8E=82=E5=95=86=E8=87=AA=E5=AE=9A=E4=B9=89=E5=9F=9F=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/org/dromara/common/oss/core/OssClient.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 1261b4777..a37c5a210 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 @@ -297,7 +297,7 @@ public class OssClient { .build()) .build()) .url(); - return url.toString(); + return url.toString().replace(url.getProtocol() + "://" + url.getHost(), getDomain()); } /** From 9f34edee4f3b83395b24690ef1fc9b6f8bebfd95 Mon Sep 17 00:00:00 2001 From: AprilWind <2100166581@qq.com> Date: Tue, 10 Dec 2024 12:41:59 +0800 Subject: [PATCH 090/175] =?UTF-8?q?reset=20=E5=9B=9E=E6=BB=9A=E9=94=99?= =?UTF-8?q?=E8=AF=AF=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/org/dromara/common/oss/core/OssClient.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 a37c5a210..1261b4777 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 @@ -297,7 +297,7 @@ public class OssClient { .build()) .build()) .url(); - return url.toString().replace(url.getProtocol() + "://" + url.getHost(), getDomain()); + return url.toString(); } /** From 552e543471984fd37fd5cd70cde0218398258b3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Tue, 10 Dec 2024 17:46:45 +0800 Subject: [PATCH 091/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20pr?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/validate/enumd/EnumPattern.java | 6 ++--- .../validate/enumd/EnumPatternValidator.java | 26 +++++++------------ 2 files changed, 12 insertions(+), 20 deletions(-) diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/validate/enumd/EnumPattern.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/validate/enumd/EnumPattern.java index c31c7703c..d4f1c3d01 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/validate/enumd/EnumPattern.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/validate/enumd/EnumPattern.java @@ -24,13 +24,13 @@ public @interface EnumPattern { /** * 需要校验的枚举类型 */ - Class type() default Enum.class; + Class> type(); /** * 枚举类型校验值字段名称 - * TODO 需确保该字段实现了 getter 方法 + * 需确保该字段实现了 getter 方法 */ - String fieldName() default "code"; + String fieldName(); String message() default "输入值不在枚举范围内"; diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/validate/enumd/EnumPatternValidator.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/validate/enumd/EnumPatternValidator.java index 0e748c0a4..6cfa11a33 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/validate/enumd/EnumPatternValidator.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/validate/enumd/EnumPatternValidator.java @@ -1,11 +1,9 @@ package org.dromara.common.core.validate.enumd; -import org.dromara.common.core.utils.StringUtils; -import org.dromara.common.core.utils.reflect.ReflectUtils; import jakarta.validation.ConstraintValidator; import jakarta.validation.ConstraintValidatorContext; -import jakarta.validation.ValidationException; -import lombok.extern.slf4j.Slf4j; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.core.utils.reflect.ReflectUtils; /** * 自定义枚举校验注解实现 @@ -25,21 +23,15 @@ public class EnumPatternValidator implements ConstraintValidator type = annotation.type(); - String fieldName = annotation.fieldName(); - Object[] enumConstants = type.getEnumConstants(); - for (Object e : enumConstants) { - if (value.equals(ReflectUtils.invokeGetter(e, fieldName))) { - return true; - } + if (StringUtils.isNotBlank(value)) { + String fieldName = annotation.fieldName(); + for (Object e : annotation.type().getEnumConstants()) { + if (value.equals(ReflectUtils.invokeGetter(e, fieldName))) { + return true; } } - return false; - } catch (Exception e) { - throw new ValidationException(e); } + return false; } -} \ No newline at end of file +} From 59fd7eeeb3a233c288e2440b65f59d11b16c4620 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A7=8B=E8=BE=9E=E6=9C=AA=E5=AF=92?= <545073804@qq.com> Date: Tue, 10 Dec 2024 09:55:11 +0000 Subject: [PATCH 092/175] =?UTF-8?q?add=20=E6=96=B0=E5=A2=9E=20=E5=9F=BA?= =?UTF-8?q?=E4=BA=8ERedisson=E7=9A=84=E5=8F=91=E5=8F=B7=E5=99=A8=E5=B7=A5?= =?UTF-8?q?=E5=85=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/redis/utils/SequenceUtils.java | 165 ++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/SequenceUtils.java diff --git a/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/SequenceUtils.java b/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/SequenceUtils.java new file mode 100644 index 000000000..3c2f70329 --- /dev/null +++ b/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/SequenceUtils.java @@ -0,0 +1,165 @@ +package org.dromara.common.redis.utils; + +import cn.hutool.core.date.DatePattern; +import cn.hutool.core.date.DateUtil; +import org.dromara.common.core.utils.SpringUtils; +import org.dromara.common.core.utils.StringUtils; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import org.redisson.api.RIdGenerator; +import org.redisson.api.RedissonClient; + +import java.time.Duration; + +/** + * 发号器工具类 + * + * @author 秋辞未寒 + * @date 2024-12-10 + */ +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class SequenceUtils { + + /** + * 默认初始值 + */ + public static final Long DEFAULT_INIT_VALUE = 1L; + /** + * 默认步长 + */ + public static final Long DEFAULT_STEP_VALUE = 1L; + /** + * 默认过期时间-天 + */ + public static final Duration DEFAULT_EXPIRE_TIME_DAY = Duration.ofDays(1); + /** + * 默认过期时间-分钟 + */ + public static final Duration DEFAULT_EXPIRE_TIME_MINUTE = Duration.ofMinutes(1); + + /** + * 获取Redisson客户端实例 + */ + private static final RedissonClient REDISSON_CLIENT = SpringUtils.getBean(RedissonClient.class); + + /** + * 获取ID生成器 + * + * @param key 业务key + * @param expireTime 过期时间 + * @param initValue ID初始值 + * @param stepValue ID步长 + * @return ID生成器 + */ + private static RIdGenerator getIdGenerator(String key, Duration expireTime, Long initValue, Long stepValue) { + if (initValue == null || initValue <= 0) { + initValue = DEFAULT_INIT_VALUE; + } + if (stepValue == null || stepValue <= 0) { + stepValue = DEFAULT_STEP_VALUE; + } + RIdGenerator idGenerator = REDISSON_CLIENT.getIdGenerator(key); + // 设置过期时间 + idGenerator.expire(expireTime); + // 设置初始值和步长 + idGenerator.tryInit(initValue, stepValue); + return idGenerator; + } + + /** + * 获取指定业务key的唯一id + * + * @param key 业务key + * @param expireTime 过期时间 + * @param initValue ID初始值 + * @param stepValue ID步长 + * @return 唯一id + */ + public static long nextId(String key, Duration expireTime, Long initValue, Long stepValue) { + return getIdGenerator(key, expireTime, initValue, stepValue).nextId(); + } + + /** + * 获取指定业务key的唯一id字符串 + * + * @param key 业务key + * @param expireTime 过期时间 + * @param initValue ID初始值 + * @param stepValue ID步长 + * @return 唯一id + */ + public static String nextIdStr(String key, Duration expireTime, Long initValue, Long stepValue) { + return String.valueOf(nextId(key, expireTime, initValue, stepValue)); + } + + /** + * 获取指定业务key的唯一id (ID初始值=1,ID步长=1) + * + * @param key 业务key + * @param expireTime 过期时间 + * @return 唯一id + */ + public static long nextId(String key, Duration expireTime) { + return getIdGenerator(key, expireTime, DEFAULT_INIT_VALUE, DEFAULT_STEP_VALUE).nextId(); + } + + /** + * 获取指定业务key的唯一id字符串 (ID初始值=1,ID步长=1) + * + * @param key 业务key + * @param expireTime 过期时间 + * @return 唯一id + */ + public static String nextIdStr(String key, Duration expireTime) { + return String.valueOf(nextId(key, expireTime)); + } + + /** + * 获取 yyyyMMdd 开头的唯一id + * + * @return 唯一id + */ + public static String nextIdDate() { + return nextIdDate(""); + } + + /** + * 获取 prefix + yyyyMMdd 开头的唯一id + * + * @param prefix 业务前缀 + * @return 唯一id + */ + public static String nextIdDate(String prefix) { + // 前缀+日期 构建 prefixKey + String prefixKey = StringUtils.format("{}{}", StringUtils.blankToDefault(prefix, ""), DateUtil.format(DateUtil.date(), DatePattern.PURE_DATE_FORMATTER)); + // 获取下一个id + long nextId = getIdGenerator(prefixKey, DEFAULT_EXPIRE_TIME_DAY, DEFAULT_INIT_VALUE, DEFAULT_STEP_VALUE).nextId(); + // 返回完整id + return StringUtils.format("{}{}", prefixKey, nextId); + } + + /** + * 获取 yyyyMMddHHmmss 开头的唯一id + * + * @return 唯一id + */ + public static String nextIdDateTime() { + return nextIdDateTime(""); + } + + /** + * 获取 prefix + yyyyMMddHHmmss 开头的唯一id + * + * @param prefix 业务前缀 + * @return 唯一id + */ + public static String nextIdDateTime(String prefix) { + // 前缀+日期时间 构建 prefixKey + String prefixKey = StringUtils.format("{}{}", StringUtils.blankToDefault(prefix, ""), DateUtil.format(DateUtil.date(), DatePattern.PURE_DATETIME_FORMATTER)); + // 获取下一个id + long nextId = getIdGenerator(prefixKey, DEFAULT_EXPIRE_TIME_MINUTE, DEFAULT_INIT_VALUE, DEFAULT_STEP_VALUE).nextId(); + // 返回完整id + return StringUtils.format("{}{}", prefixKey, nextId); + } + +} From 8a731efe0dc5e47cac75cab8373aedc21eba04be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Wed, 11 Dec 2024 14:01:41 +0800 Subject: [PATCH 093/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20workflow?= =?UTF-8?q?=20=E6=A8=A1=E5=9D=97=E5=A2=9E=E5=8A=A0=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E6=96=87=E6=A1=A3=E7=94=9F=E6=88=90=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ruoyi-admin/src/main/resources/application.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml index 33fbcb7ab..dead74198 100644 --- a/ruoyi-admin/src/main/resources/application.yml +++ b/ruoyi-admin/src/main/resources/application.yml @@ -215,6 +215,8 @@ springdoc: packages-to-scan: org.dromara.system - group: 4.代码生成模块 packages-to-scan: org.dromara.generator + - group: 5.工作流模块 + packages-to-scan: org.dromara.workflow # 防止XSS攻击 xss: From 4598d4d843662a9274cb9b42b9abb5fa4274b70a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Wed, 11 Dec 2024 15:31:17 +0800 Subject: [PATCH 094/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E9=83=A8?= =?UTF-8?q?=E9=97=A8=E6=A0=91=E5=A2=9E=E5=8A=A0=E7=A6=81=E7=94=A8=E6=A0=87?= =?UTF-8?q?=E5=BF=97=E4=BD=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/dromara/system/service/impl/SysDeptServiceImpl.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 a3f0b6ffc..eb95a48fe 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 @@ -110,7 +110,8 @@ public class SysDeptServiceImpl implements ISysDeptService, DeptService { tree.setId(dept.getDeptId()) .setParentId(dept.getParentId()) .setName(dept.getDeptName()) - .setWeight(dept.getOrderNum())); + .setWeight(dept.getOrderNum()) + .putExtra("disabled", SystemConstants.DISABLE.equals(dept.getStatus()))); Tree tree = trees.stream().filter(it -> it.getId().longValue() == d.getDeptId()).findFirst().get(); treeList.add(tree); } From d7b0dc91d5d8ee66eb710286b7f47d26564aa55d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Wed, 11 Dec 2024 18:12:31 +0800 Subject: [PATCH 095/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E5=8E=BB?= =?UTF-8?q?=E9=99=A4=E9=83=A8=E9=97=A8=E6=9F=A5=E8=AF=A2=E7=8A=B6=E6=80=81?= =?UTF-8?q?=E6=A0=A1=E9=AA=8C=20=E6=94=B9=E4=B8=BA=E5=89=8D=E7=AB=AF?= =?UTF-8?q?=E8=BF=87=E6=BB=A4=20=E4=BE=BF=E4=BA=8E=E6=9F=A5=E7=9C=8B?= =?UTF-8?q?=E7=A6=81=E7=94=A8=E9=83=A8=E9=97=A8=E4=B8=8B=E7=9A=84=E5=85=B6?= =?UTF-8?q?=E4=BB=96=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/dromara/system/service/impl/SysDeptServiceImpl.java | 2 -- 1 file changed, 2 deletions(-) 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 eb95a48fe..478a42c72 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 @@ -67,8 +67,6 @@ public class SysDeptServiceImpl implements ISysDeptService, DeptService { */ @Override public List> selectDeptTreeList(SysDeptBo bo) { - // 只查询未禁用部门 - bo.setStatus(SystemConstants.NORMAL); LambdaQueryWrapper lqw = buildQueryWrapper(bo); List depts = baseMapper.selectDeptList(lqw); return buildDeptTreeSelect(depts); From dd17246086672c9571994a062735453fb8356cd2 Mon Sep 17 00:00:00 2001 From: DoubleH <1402818247@qq.com> Date: Thu, 12 Dec 2024 14:15:59 +0000 Subject: [PATCH 096/175] =?UTF-8?q?!613=20refactor=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=20*=20update=20=E4=BC=98=E5=8C=96=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/dromara/common/core/utils/Threads.java | 12 ------------ .../mail/config/properties/MailProperties.java | 8 +++++++- .../common/sse/core/SseEmitterManager.java | 12 ++++++------ .../demo/controller/RedisCacheController.java | 7 ++----- .../demo/controller/RedisLockController.java | 17 +++++------------ .../controller/system/SysClientController.java | 2 +- .../controller/system/SysUserController.java | 2 +- .../system/service/ISysClientService.java | 2 +- .../service/impl/SysClientServiceImpl.java | 2 +- .../system/service/impl/SysDeptServiceImpl.java | 2 +- .../service/impl/SysLogininforServiceImpl.java | 3 +-- .../service/impl/SysOperLogServiceImpl.java | 3 +-- 12 files changed, 27 insertions(+), 45 deletions(-) diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/Threads.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/Threads.java index ae6cfa322..82ea5caf1 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/Threads.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/Threads.java @@ -14,18 +14,6 @@ import java.util.concurrent.*; @Slf4j @NoArgsConstructor(access = AccessLevel.PRIVATE) public class Threads { - - /** - * sleep等待,单位为毫秒 - */ - public static void sleep(long milliseconds) { - try { - Thread.sleep(milliseconds); - } catch (InterruptedException e) { - return; - } - } - /** * 停止线程池 * 先使用shutdown, 停止接收新任务并尝试完成所有已存在任务. diff --git a/ruoyi-common/ruoyi-common-mail/src/main/java/org/dromara/common/mail/config/properties/MailProperties.java b/ruoyi-common/ruoyi-common-mail/src/main/java/org/dromara/common/mail/config/properties/MailProperties.java index d0e78a2ca..e44aa3da3 100644 --- a/ruoyi-common/ruoyi-common-mail/src/main/java/org/dromara/common/mail/config/properties/MailProperties.java +++ b/ruoyi-common/ruoyi-common-mail/src/main/java/org/dromara/common/mail/config/properties/MailProperties.java @@ -43,7 +43,13 @@ public class MailProperties { private String pass; /** - * 发送方,遵循RFC-822标准 + * 发送方,遵循RFC-822标准
+ * 发件人可以是以下形式: + * + *
+     * 1. user@xxx.xx
+     * 2.  name <user@xxx.xx>
+     * 
*/ private String from; diff --git a/ruoyi-common/ruoyi-common-sse/src/main/java/org/dromara/common/sse/core/SseEmitterManager.java b/ruoyi-common/ruoyi-common-sse/src/main/java/org/dromara/common/sse/core/SseEmitterManager.java index c26adca50..fd22db694 100644 --- a/ruoyi-common/ruoyi-common-sse/src/main/java/org/dromara/common/sse/core/SseEmitterManager.java +++ b/ruoyi-common/ruoyi-common-sse/src/main/java/org/dromara/common/sse/core/SseEmitterManager.java @@ -126,10 +126,10 @@ public class SseEmitterManager { SseMessageDto broadcastMessage = new SseMessageDto(); broadcastMessage.setMessage(sseMessageDto.getMessage()); broadcastMessage.setUserIds(sseMessageDto.getUserIds()); - RedisUtils.publish(SSE_TOPIC, broadcastMessage, consumer -> { + RedisUtils.publish(SSE_TOPIC, broadcastMessage, consumer -> log.info("SSE发送主题订阅消息topic:{} session keys:{} message:{}", - SSE_TOPIC, sseMessageDto.getUserIds(), sseMessageDto.getMessage()); - }); + SSE_TOPIC, sseMessageDto.getUserIds(), sseMessageDto.getMessage()) + ); } /** @@ -140,8 +140,8 @@ public class SseEmitterManager { public void publishAll(String message) { SseMessageDto broadcastMessage = new SseMessageDto(); broadcastMessage.setMessage(message); - RedisUtils.publish(SSE_TOPIC, broadcastMessage, consumer -> { - log.info("SSE发送主题订阅消息topic:{} message:{}", SSE_TOPIC, message); - }); + RedisUtils.publish(SSE_TOPIC, broadcastMessage, consumer -> + log.info("SSE发送主题订阅消息topic:{} message:{}", SSE_TOPIC, message) + ); } } diff --git a/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/RedisCacheController.java b/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/RedisCacheController.java index 341880c5d..303cf885d 100644 --- a/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/RedisCacheController.java +++ b/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/RedisCacheController.java @@ -1,5 +1,6 @@ package org.dromara.demo.controller; +import cn.hutool.core.thread.ThreadUtil; import org.dromara.common.core.constant.CacheNames; import org.dromara.common.core.domain.R; import org.dromara.common.redis.utils.RedisUtils; @@ -83,11 +84,7 @@ public class RedisCacheController { RedisUtils.setCacheObject(key, value); boolean flag = RedisUtils.expire(key, Duration.ofSeconds(10)); System.out.println("***********" + flag); - try { - Thread.sleep(11 * 1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } + ThreadUtil.sleep(11 * 1000); Object obj = RedisUtils.getCacheObject(key); return R.ok(value.equals(obj)); } diff --git a/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/RedisLockController.java b/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/RedisLockController.java index b7e096266..237b6ee2d 100644 --- a/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/RedisLockController.java +++ b/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/RedisLockController.java @@ -1,5 +1,6 @@ package org.dromara.demo.controller; +import cn.hutool.core.thread.ThreadUtil; import com.baomidou.lock.LockInfo; import com.baomidou.lock.LockTemplate; import com.baomidou.lock.annotation.Lock4j; @@ -33,13 +34,9 @@ public class RedisLockController { @Lock4j(keys = {"#key"}) @GetMapping("/testLock4j") public R testLock4j(String key, String value) { - System.out.println("start:" + key + ",time:" + LocalTime.now().toString()); - try { - Thread.sleep(10000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - System.out.println("end :" + key + ",time:" + LocalTime.now().toString()); + System.out.println("start:" + key + ",time:" + LocalTime.now()); + ThreadUtil.sleep(10000); + System.out.println("end :" + key + ",time:" + LocalTime.now()); return R.ok("操作成功", value); } @@ -54,11 +51,7 @@ public class RedisLockController { } // 获取锁成功,处理业务 try { - try { - Thread.sleep(8000); - } catch (InterruptedException e) { - // - } + ThreadUtil.sleep(8000); System.out.println("执行简单方法1 , 当前线程:" + Thread.currentThread().getName()); } finally { //释放锁 diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysClientController.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysClientController.java index 13be4a4a9..eaed06847 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysClientController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysClientController.java @@ -97,7 +97,7 @@ public class SysClientController extends BaseController { @Log(title = "客户端管理", businessType = BusinessType.UPDATE) @PutMapping("/changeStatus") public R changeStatus(@RequestBody SysClientBo bo) { - return toAjax(sysClientService.updateUserStatus(bo.getClientId(), bo.getStatus())); + return toAjax(sysClientService.updateClientStatus(bo.getClientId(), bo.getStatus())); } /** diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysUserController.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysUserController.java index d4cecbe14..e1e868a6e 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysUserController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysUserController.java @@ -218,7 +218,7 @@ public class SysUserController extends BaseController { @GetMapping("/optionselect") public R> optionselect(@RequestParam(required = false) Long[] userIds, @RequestParam(required = false) Long deptId) { - return R.ok(userService.selectUserByIds(userIds == null ? null : List.of(userIds), deptId)); + return R.ok(userService.selectUserByIds(ArrayUtil.isEmpty(userIds) ? null : List.of(userIds), deptId)); } /** diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysClientService.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysClientService.java index d0f8a3cbe..546c3f33a 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysClientService.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysClientService.java @@ -50,7 +50,7 @@ public interface ISysClientService { /** * 修改状态 */ - int updateUserStatus(String clientId, String status); + int updateClientStatus(String clientId, String status); /** * 校验并批量删除客户端管理信息 diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysClientServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysClientServiceImpl.java index 1c6924320..4f6e676df 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysClientServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysClientServiceImpl.java @@ -123,7 +123,7 @@ public class SysClientServiceImpl implements ISysClientService { */ @CacheEvict(cacheNames = CacheNames.SYS_CLIENT, key = "#clientId") @Override - public int updateUserStatus(String clientId, String status) { + public int updateClientStatus(String clientId, String status) { return baseMapper.update(null, new LambdaUpdateWrapper() .set(SysClient::getStatus, status) diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDeptServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDeptServiceImpl.java index 478a42c72..98c1bd644 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 @@ -110,7 +110,7 @@ public class SysDeptServiceImpl implements ISysDeptService, DeptService { .setName(dept.getDeptName()) .setWeight(dept.getOrderNum()) .putExtra("disabled", SystemConstants.DISABLE.equals(dept.getStatus()))); - Tree tree = trees.stream().filter(it -> it.getId().longValue() == d.getDeptId()).findFirst().get(); + Tree tree = StreamUtils.findFirst(trees, it -> it.getId().longValue() == d.getDeptId()); treeList.add(tree); } } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysLogininforServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysLogininforServiceImpl.java index b95baf44b..72b497eca 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysLogininforServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysLogininforServiceImpl.java @@ -118,8 +118,7 @@ public class SysLogininforServiceImpl implements ISysLogininforService { .between(params.get("beginTime") != null && params.get("endTime") != null, SysLogininfor::getLoginTime, params.get("beginTime"), params.get("endTime")); if (StringUtils.isBlank(pageQuery.getOrderByColumn())) { - pageQuery.setOrderByColumn("info_id"); - pageQuery.setIsAsc("desc"); + lqw.orderByDesc(SysLogininfor::getInfoId); } Page page = baseMapper.selectVoPage(pageQuery.build(), lqw); return TableDataInfo.build(page); diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOperLogServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOperLogServiceImpl.java index 750e455ac..27c2f32d5 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOperLogServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOperLogServiceImpl.java @@ -53,8 +53,7 @@ public class SysOperLogServiceImpl implements ISysOperLogService { public TableDataInfo selectPageOperLogList(SysOperLogBo operLog, PageQuery pageQuery) { LambdaQueryWrapper lqw = buildQueryWrapper(operLog); if (StringUtils.isBlank(pageQuery.getOrderByColumn())) { - pageQuery.setOrderByColumn("oper_id"); - pageQuery.setIsAsc("desc"); + lqw.orderByDesc(SysOperLog::getOperId); } Page page = baseMapper.selectVoPage(pageQuery.build(), lqw); return TableDataInfo.build(page); From 4352b3fe4af884ba23a4461d517267a1fe852741 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Thu, 12 Dec 2024 22:20:32 +0800 Subject: [PATCH 097/175] =?UTF-8?q?update=20=E5=9B=9E=E9=80=80=E4=B8=80?= =?UTF-8?q?=E4=BA=9B=E4=B8=8D=E5=BA=94=E8=AF=A5=E8=A2=AB=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E7=9A=84=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dromara/common/sse/core/SseEmitterManager.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ruoyi-common/ruoyi-common-sse/src/main/java/org/dromara/common/sse/core/SseEmitterManager.java b/ruoyi-common/ruoyi-common-sse/src/main/java/org/dromara/common/sse/core/SseEmitterManager.java index fd22db694..c26adca50 100644 --- a/ruoyi-common/ruoyi-common-sse/src/main/java/org/dromara/common/sse/core/SseEmitterManager.java +++ b/ruoyi-common/ruoyi-common-sse/src/main/java/org/dromara/common/sse/core/SseEmitterManager.java @@ -126,10 +126,10 @@ public class SseEmitterManager { SseMessageDto broadcastMessage = new SseMessageDto(); broadcastMessage.setMessage(sseMessageDto.getMessage()); broadcastMessage.setUserIds(sseMessageDto.getUserIds()); - RedisUtils.publish(SSE_TOPIC, broadcastMessage, consumer -> + RedisUtils.publish(SSE_TOPIC, broadcastMessage, consumer -> { log.info("SSE发送主题订阅消息topic:{} session keys:{} message:{}", - SSE_TOPIC, sseMessageDto.getUserIds(), sseMessageDto.getMessage()) - ); + SSE_TOPIC, sseMessageDto.getUserIds(), sseMessageDto.getMessage()); + }); } /** @@ -140,8 +140,8 @@ public class SseEmitterManager { public void publishAll(String message) { SseMessageDto broadcastMessage = new SseMessageDto(); broadcastMessage.setMessage(message); - RedisUtils.publish(SSE_TOPIC, broadcastMessage, consumer -> - log.info("SSE发送主题订阅消息topic:{} message:{}", SSE_TOPIC, message) - ); + RedisUtils.publish(SSE_TOPIC, broadcastMessage, consumer -> { + log.info("SSE发送主题订阅消息topic:{} message:{}", SSE_TOPIC, message); + }); } } From 0027f671d2a99b29aa0cb68c46820abdd24f906e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Thu, 12 Dec 2024 23:31:26 +0800 Subject: [PATCH 098/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E7=99=BB?= =?UTF-8?q?=E5=BD=95=E7=94=A8=E6=88=B7=E5=A2=9E=E5=8A=A0=E5=B2=97=E4=BD=8D?= =?UTF-8?q?=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dromara/web/service/SysLoginService.java | 13 ++++-- .../common/core/domain/dto/PostDTO.java | 46 +++++++++++++++++++ .../common/core/domain/model/LoginUser.java | 8 +++- .../common/core/service/PostService.java | 10 ++++ .../system/service/ISysPostService.java | 8 ++++ .../service/impl/SysPostServiceImpl.java | 14 +++++- 6 files changed, 93 insertions(+), 6 deletions(-) create mode 100644 ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/PostDTO.java create mode 100644 ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/PostService.java diff --git a/ruoyi-admin/src/main/java/org/dromara/web/service/SysLoginService.java b/ruoyi-admin/src/main/java/org/dromara/web/service/SysLoginService.java index 2eae90ab7..41a802b44 100644 --- a/ruoyi-admin/src/main/java/org/dromara/web/service/SysLoginService.java +++ b/ruoyi-admin/src/main/java/org/dromara/web/service/SysLoginService.java @@ -14,6 +14,7 @@ import org.dromara.common.core.constant.CacheConstants; import org.dromara.common.core.constant.Constants; import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.core.constant.TenantConstants; +import org.dromara.common.core.domain.dto.PostDTO; import org.dromara.common.core.domain.dto.RoleDTO; import org.dromara.common.core.domain.model.LoginUser; import org.dromara.common.core.enums.LoginType; @@ -60,6 +61,7 @@ public class SysLoginService { private final ISysSocialService sysSocialService; private final ISysRoleService roleService; private final ISysDeptService deptService; + private final ISysPostService postService; private final SysUserMapper userMapper; @@ -148,21 +150,24 @@ public class SysLoginService { */ public LoginUser buildLoginUser(SysUserVo user) { LoginUser loginUser = new LoginUser(); + Long userId = user.getUserId(); loginUser.setTenantId(user.getTenantId()); - loginUser.setUserId(user.getUserId()); + loginUser.setUserId(userId); loginUser.setDeptId(user.getDeptId()); loginUser.setUsername(user.getUserName()); loginUser.setNickname(user.getNickName()); loginUser.setUserType(user.getUserType()); - loginUser.setMenuPermission(permissionService.getMenuPermission(user.getUserId())); - loginUser.setRolePermission(permissionService.getRolePermission(user.getUserId())); + loginUser.setMenuPermission(permissionService.getMenuPermission(userId)); + loginUser.setRolePermission(permissionService.getRolePermission(userId)); if (ObjectUtil.isNotNull(user.getDeptId())) { Opt deptOpt = Opt.of(user.getDeptId()).map(deptService::selectDeptById); loginUser.setDeptName(deptOpt.map(SysDeptVo::getDeptName).orElse(StringUtils.EMPTY)); loginUser.setDeptCategory(deptOpt.map(SysDeptVo::getDeptCategory).orElse(StringUtils.EMPTY)); } - List roles = roleService.selectRolesByUserId(user.getUserId()); + List roles = roleService.selectRolesByUserId(userId); + List posts = postService.selectPostsByUserId(userId); loginUser.setRoles(BeanUtil.copyToList(roles, RoleDTO.class)); + loginUser.setPosts(BeanUtil.copyToList(posts, PostDTO.class)); return loginUser; } diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/PostDTO.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/PostDTO.java new file mode 100644 index 000000000..7536ee33d --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/PostDTO.java @@ -0,0 +1,46 @@ +package org.dromara.common.core.domain.dto; + +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serial; +import java.io.Serializable; + +/** + * 岗位 + * + * @author AprilWind + */ +@Data +@NoArgsConstructor +public class PostDTO implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 岗位ID + */ + private Long postId; + + /** + * 部门id + */ + private Long deptId; + + /** + * 岗位编码 + */ + private String postCode; + + /** + * 岗位名称 + */ + private String postName; + + /** + * 岗位类别编码 + */ + private String postCategory; + +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/model/LoginUser.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/model/LoginUser.java index c723e7668..338d4d70a 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/model/LoginUser.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/model/LoginUser.java @@ -1,8 +1,9 @@ package org.dromara.common.core.domain.model; -import org.dromara.common.core.domain.dto.RoleDTO; import lombok.Data; import lombok.NoArgsConstructor; +import org.dromara.common.core.domain.dto.PostDTO; +import org.dromara.common.core.domain.dto.RoleDTO; import java.io.Serial; import java.io.Serializable; @@ -111,6 +112,11 @@ public class LoginUser implements Serializable { */ private List roles; + /** + * 岗位对象 + */ + private List posts; + /** * 数据权限 当前角色ID */ diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/PostService.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/PostService.java new file mode 100644 index 000000000..41d4e8308 --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/PostService.java @@ -0,0 +1,10 @@ +package org.dromara.common.core.service; + +/** + * 通用 岗位服务 + * + * @author AprilWind + */ +public interface PostService { + +} diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysPostService.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysPostService.java index 3751b23be..a760d497e 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysPostService.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysPostService.java @@ -25,6 +25,14 @@ public interface ISysPostService { */ List selectPostList(SysPostBo post); + /** + * 查询用户所属岗位组 + * + * @param userId 用户ID + * @return 岗位ID + */ + List selectPostsByUserId(Long userId); + /** * 查询所有岗位 * diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysPostServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysPostServiceImpl.java index 8643f0d92..72f1a5e31 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 @@ -8,6 +8,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import lombok.RequiredArgsConstructor; import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.core.exception.ServiceException; +import org.dromara.common.core.service.PostService; import org.dromara.common.core.utils.MapstructUtils; import org.dromara.common.core.utils.StreamUtils; import org.dromara.common.core.utils.StringUtils; @@ -34,7 +35,7 @@ import java.util.List; */ @RequiredArgsConstructor @Service -public class SysPostServiceImpl implements ISysPostService { +public class SysPostServiceImpl implements ISysPostService, PostService { private final SysPostMapper baseMapper; private final SysDeptMapper deptMapper; @@ -57,6 +58,17 @@ public class SysPostServiceImpl implements ISysPostService { return baseMapper.selectVoList(buildQueryWrapper(post)); } + /** + * 查询用户所属岗位组 + * + * @param userId 用户ID + * @return 岗位ID + */ + @Override + public List selectPostsByUserId(Long userId) { + return baseMapper.selectPostsByUserId(userId); + } + /** * 根据查询条件构建查询包装器 * From ab3e4978b1be42097b269c10927bb51f11a63d78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Thu, 12 Dec 2024 23:32:33 +0800 Subject: [PATCH 099/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E4=B8=BA?= =?UTF-8?q?=E9=83=A8=E9=97=A8=E8=A7=92=E8=89=B2=E5=B2=97=E4=BD=8D=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E5=A2=9E=E5=8A=A0=E4=B8=80=E4=BA=9B=E5=B8=B8=E7=94=A8?= =?UTF-8?q?=E6=9F=A5=E8=AF=A2=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/core/domain/dto/DeptDTO.java | 37 +++++++++++++++++++ .../common/core/service/DeptService.java | 19 ++++++++++ .../common/core/service/RoleService.java | 10 +++++ .../common/core/service/UserService.java | 9 +++++ .../common/mybatis/core/page/PageQuery.java | 5 +++ .../common/satoken/utils/LoginHelper.java | 7 ++++ .../dromara/system/mapper/SysDeptMapper.java | 12 ++++++ .../service/impl/SysDeptServiceImpl.java | 27 ++++++++++++++ .../service/impl/SysRoleServiceImpl.java | 7 ++-- .../service/impl/SysUserServiceImpl.java | 23 ++++++++++++ .../resources/mapper/system/SysDeptMapper.xml | 11 ++++++ 11 files changed, 164 insertions(+), 3 deletions(-) create mode 100644 ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/DeptDTO.java create mode 100644 ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/RoleService.java diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/DeptDTO.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/DeptDTO.java new file mode 100644 index 000000000..65c012faf --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/DeptDTO.java @@ -0,0 +1,37 @@ +package org.dromara.common.core.domain.dto; + +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serial; +import java.io.Serializable; + +/** + * 部门 + * + * @author AprilWind + */ + +@Data +@NoArgsConstructor +public class DeptDTO implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 部门ID + */ + private Long deptId; + + /** + * 父部门ID + */ + private Long parentId; + + /** + * 部门名称 + */ + private String deptName; + +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/DeptService.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/DeptService.java index db9463e79..f93d1778a 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/DeptService.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/DeptService.java @@ -1,5 +1,9 @@ package org.dromara.common.core.service; +import org.dromara.common.core.domain.dto.DeptDTO; + +import java.util.List; + /** * 通用 部门服务 * @@ -15,4 +19,19 @@ public interface DeptService { */ String selectDeptNameByIds(String deptIds); + /** + * 根据部门ID查询部门负责人 + * + * @param deptId 部门ID,用于指定需要查询的部门 + * @return 返回该部门的负责人ID + */ + Long selectDeptLeaderById(Long deptId); + + /** + * 查询部门 + * + * @return 部门列表 + */ + List selectDeptsByList(); + } diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/RoleService.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/RoleService.java new file mode 100644 index 000000000..ba62c82ae --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/RoleService.java @@ -0,0 +1,10 @@ +package org.dromara.common.core.service; + +/** + * 通用 角色服务 + * + * @author AprilWind + */ +public interface RoleService { + +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/UserService.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/UserService.java index 43aef28cb..67cd54fba 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/UserService.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/UserService.java @@ -82,4 +82,13 @@ public interface UserService { * @return 用户 */ List selectUsersByDeptIds(List deptIds); + + /** + * 通过岗位ID查询用户 + * + * @param postIds 岗位ids + * @return 用户 + */ + List selectUsersByPostIds(List postIds); + } diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/core/page/PageQuery.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/core/page/PageQuery.java index 3f7797d6b..1d5c3c9da 100644 --- a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/core/page/PageQuery.java +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/core/page/PageQuery.java @@ -119,4 +119,9 @@ public class PageQuery implements Serializable { return (pageNum - 1) * pageSize; } + public PageQuery(Integer pageSize, Integer pageNum) { + this.pageSize = pageSize; + this.pageNum = pageNum; + } + } 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 cdc5684fa..19557e131 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 @@ -88,6 +88,13 @@ public class LoginHelper { return Convert.toLong(getExtra(USER_KEY)); } + /** + * 获取用户id + */ + public static String getUserIdStr() { + return Convert.toStr(getExtra(USER_KEY)); + } + /** * 获取用户账户 */ diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysDeptMapper.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysDeptMapper.java index 0f2c90667..b69624cf0 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysDeptMapper.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysDeptMapper.java @@ -3,6 +3,7 @@ package org.dromara.system.mapper; import com.baomidou.mybatisplus.core.conditions.Wrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Constants; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import org.apache.ibatis.annotations.Param; import org.dromara.common.mybatis.annotation.DataColumn; import org.dromara.common.mybatis.annotation.DataPermission; @@ -31,6 +32,17 @@ public interface SysDeptMapper extends BaseMapperPlus { }) List selectDeptList(@Param(Constants.WRAPPER) Wrapper queryWrapper); + /** + * 分页查询部门管理数据 + * + * @param queryWrapper 查询条件 + * @return 部门信息集合 + */ + @DataPermission({ + @DataColumn(key = "deptName", value = "dept_id"), + }) + Page selectPageDeptList(@Param("page") Page page, @Param(Constants.WRAPPER) Wrapper queryWrapper); + /** * 统计指定部门ID的部门数量 * 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 98c1bd644..be9e33d8b 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDeptServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDeptServiceImpl.java @@ -1,5 +1,6 @@ package org.dromara.system.service.impl; +import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.convert.Convert; import cn.hutool.core.lang.tree.Tree; @@ -10,6 +11,7 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers; import lombok.RequiredArgsConstructor; import org.dromara.common.core.constant.CacheNames; import org.dromara.common.core.constant.SystemConstants; +import org.dromara.common.core.domain.dto.DeptDTO; import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.service.DeptService; import org.dromara.common.core.utils.*; @@ -354,4 +356,29 @@ public class SysDeptServiceImpl implements ISysDeptService, DeptService { return baseMapper.deleteById(deptId); } + /** + * 根据部门ID查询部门负责人 + * + * @param deptId 部门ID,用于指定需要查询的部门 + * @return 返回该部门的负责人ID + */ + @Override + public Long selectDeptLeaderById(Long deptId) { + SysDeptVo vo = SpringUtils.getAopProxy(this).selectDeptById(deptId); + return vo.getLeader(); + } + + /** + * 查询部门 + * + * @return 部门列表 + */ + @Override + public List selectDeptsByList() { + List list = baseMapper.selectDeptList(new LambdaQueryWrapper() + .select(SysDept::getDeptId, SysDept::getDeptName, SysDept::getParentId) + .eq(SysDept::getStatus, SystemConstants.NORMAL)); + return BeanUtil.copyToList(list, DeptDTO.class); + } + } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysRoleServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysRoleServiceImpl.java index cbca57e5d..4c007358e 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysRoleServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysRoleServiceImpl.java @@ -17,6 +17,7 @@ import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.core.constant.TenantConstants; import org.dromara.common.core.domain.model.LoginUser; import org.dromara.common.core.exception.ServiceException; +import org.dromara.common.core.service.RoleService; import org.dromara.common.core.utils.MapstructUtils; import org.dromara.common.core.utils.StreamUtils; import org.dromara.common.core.utils.StringUtils; @@ -47,7 +48,7 @@ import java.util.*; */ @RequiredArgsConstructor @Service -public class SysRoleServiceImpl implements ISysRoleService { +public class SysRoleServiceImpl implements ISysRoleService, RoleService { private final SysRoleMapper baseMapper; private final SysRoleMenuMapper roleMenuMapper; @@ -351,7 +352,7 @@ public class SysRoleServiceImpl implements ISysRoleService { private int insertRoleMenu(SysRoleBo role) { int rows = 1; // 新增用户与角色管理 - List list = new ArrayList(); + List list = new ArrayList<>(); for (Long menuId : role.getMenuIds()) { SysRoleMenu rm = new SysRoleMenu(); rm.setRoleId(role.getRoleId()); @@ -372,7 +373,7 @@ public class SysRoleServiceImpl implements ISysRoleService { private int insertRoleDept(SysRoleBo role) { int rows = 1; // 新增角色与部门(数据权限)管理 - List list = new ArrayList(); + List list = new ArrayList<>(); for (Long deptId : role.getDeptIds()) { SysRoleDept rd = new SysRoleDept(); rd.setRoleId(role.getRoleId()); 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 4b5758763..40811707b 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysUserServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysUserServiceImpl.java @@ -696,4 +696,27 @@ public class SysUserServiceImpl implements ISysUserService, UserService { .in(SysUser::getDeptId, deptIds)); return BeanUtil.copyToList(list, UserDTO.class); } + + /** + * 通过岗位ID查询用户 + * + * @param postIds 岗位ids + * @return 用户 + */ + @Override + public List selectUsersByPostIds(List postIds) { + if (CollUtil.isEmpty(postIds)) { + return List.of(); + } + + // 通过岗位ID获取用户岗位信息 + List userPosts = userPostMapper.selectList( + new LambdaQueryWrapper().in(SysUserPost::getPostId, postIds)); + + // 获取用户ID列表 + Set userIds = StreamUtils.toSet(userPosts, SysUserPost::getUserId); + + return selectListByIds(new ArrayList<>(userIds)); + } + } diff --git a/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml b/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml index 6ad866f29..9057a0e22 100644 --- a/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml +++ b/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml @@ -18,6 +18,17 @@ from sys_dept ${ew.getCustomSqlSegment} + + From 29c5ff89babf045035478b66961ca8c117375f5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Thu, 12 Dec 2024 23:33:00 +0800 Subject: [PATCH 100/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E9=87=8D?= =?UTF-8?q?=E6=9E=84DateUtils=E5=B7=A5=E5=85=B7=E7=B1=BB=20=E6=9B=B4?= =?UTF-8?q?=E5=8A=A0=E5=AE=9E=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/core/enums/FormatsType.java | 146 ++++++++++ .../dromara/common/core/utils/DateUtils.java | 250 +++++++++++++----- 2 files changed, 330 insertions(+), 66 deletions(-) create mode 100644 ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/enums/FormatsType.java diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/enums/FormatsType.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/enums/FormatsType.java new file mode 100644 index 000000000..8d4b6d911 --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/enums/FormatsType.java @@ -0,0 +1,146 @@ +package org.dromara.common.core.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.dromara.common.core.utils.StringUtils; + +/* + * 日期格式 + * "yyyy":4位数的年份,例如:2023年表示为"2023"。 + * "yy":2位数的年份,例如:2023年表示为"23"。 + * "MM":2位数的月份,取值范围为01到12,例如:7月表示为"07"。 + * "M":不带前导零的月份,取值范围为1到12,例如:7月表示为"7"。 + * "dd":2位数的日期,取值范围为01到31,例如:22日表示为"22"。 + * "d":不带前导零的日期,取值范围为1到31,例如:22日表示为"22"。 + * "EEEE":星期的全名,例如:星期三表示为"Wednesday"。 + * "E":星期的缩写,例如:星期三表示为"Wed"。 + * "DDD" 或 "D":一年中的第几天,取值范围为001到366,例如:第200天表示为"200"。 + * 时间格式 + * "HH":24小时制的小时数,取值范围为00到23,例如:下午5点表示为"17"。 + * "hh":12小时制的小时数,取值范围为01到12,例如:下午5点表示为"05"。 + * "mm":分钟数,取值范围为00到59,例如:30分钟表示为"30"。 + * "ss":秒数,取值范围为00到59,例如:45秒表示为"45"。 + * "SSS":毫秒数,取值范围为000到999,例如:123毫秒表示为"123"。 + */ + +/** + * 日期格式与时间格式枚举 + */ +@Getter +@AllArgsConstructor +public enum FormatsType { + + /** + * 例如:2023年表示为"23" + */ + YY("yy"), + + /** + * 例如:2023年表示为"2023" + */ + YYYY("yyyy"), + + /** + * 例例如,2023年7月可以表示为 "2023-07" + */ + YYYY_MM("yyyy-MM"), + + /** + * 例如,日期 "2023年7月22日" 可以表示为 "2023-07-22" + */ + YYYY_MM_DD("yyyy-MM-dd"), + + /** + * 例如,当前时间如果是 "2023年7月22日下午3点30分",则可以表示为 "2023-07-22 15:30" + */ + YYYY_MM_DD_HH_MM("yyyy-MM-dd HH:mm"), + + /** + * 例如,当前时间如果是 "2023年7月22日下午3点30分45秒",则可以表示为 "2023-07-22 15:30:45" + */ + YYYY_MM_DD_HH_MM_SS("yyyy-MM-dd HH:mm:ss"), + + /** + * 例如:下午3点30分45秒,表示为 "15:30:45" + */ + HH_MM_SS("HH:mm:ss"), + + /** + * 例例如,2023年7月可以表示为 "2023/07" + */ + YYYY_MM_SLASH("yyyy/MM"), + + /** + * 例如,日期 "2023年7月22日" 可以表示为 "2023/07/22" + */ + YYYY_MM_DD_SLASH("yyyy/MM/dd"), + + /** + * 例如,当前时间如果是 "2023年7月22日下午3点30分45秒",则可以表示为 "2023/07/22 15:30:45" + */ + YYYY_MM_DD_HH_MM_SLASH("yyyy/MM/dd HH:mm"), + + /** + * 例如,当前时间如果是 "2023年7月22日下午3点30分45秒",则可以表示为 "2023/07/22 15:30:45" + */ + YYYY_MM_DD_HH_MM_SS_SLASH("yyyy/MM/dd HH:mm:ss"), + + /** + * 例例如,2023年7月可以表示为 "2023.07" + */ + YYYY_MM_DOT("yyyy.MM"), + + /** + * 例如,日期 "2023年7月22日" 可以表示为 "2023.07.22" + */ + YYYY_MM_DD_DOT("yyyy.MM.dd"), + + /** + * 例如,当前时间如果是 "2023年7月22日下午3点30分",则可以表示为 "2023.07.22 15:30" + */ + YYYY_MM_DD_HH_MM_DOT("yyyy.MM.dd HH:mm"), + + /** + * 例如,当前时间如果是 "2023年7月22日下午3点30分45秒",则可以表示为 "2023.07.22 15:30:45" + */ + YYYY_MM_DD_HH_MM_SS_DOT("yyyy.MM.dd HH:mm:ss"), + + /** + * 例如,2023年7月可以表示为 "202307" + */ + YYYYMM("yyyyMM"), + + /** + * 例如,2023年7月22日可以表示为 "20230722" + */ + YYYYMMDD("yyyyMMdd"), + + /** + * 例如,2023年7月22日下午3点可以表示为 "2023072215" + */ + YYYYMMDDHH("yyyyMMddHH"), + + /** + * 例如,2023年7月22日下午3点30分可以表示为 "202307221530" + */ + YYYYMMDDHHMM("yyyyMMddHHmm"), + + /** + * 例如,2023年7月22日下午3点30分45秒可以表示为 "20230722153045" + */ + YYYYMMDDHHMMSS("yyyyMMddHHmmss"); + + /** + * 时间格式 + */ + private final String timeFormat; + + public static FormatsType getFormatsType(String str) { + for (FormatsType value : values()) { + if (StringUtils.contains(str, value.getTimeFormat())) { + return value; + } + } + throw new RuntimeException("'FormatsType' not found By " + str); + } +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/DateUtils.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/DateUtils.java index 72178a7b6..88cdbbc72 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/DateUtils.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/DateUtils.java @@ -3,16 +3,15 @@ package org.dromara.common.core.utils; import lombok.AccessLevel; import lombok.NoArgsConstructor; import org.apache.commons.lang3.time.DateFormatUtils; +import org.dromara.common.core.enums.FormatsType; +import org.dromara.common.core.exception.ServiceException; import java.lang.management.ManagementFactory; import java.text.ParseException; import java.text.SimpleDateFormat; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.ZoneId; -import java.time.ZonedDateTime; +import java.time.*; import java.util.Date; +import java.util.concurrent.TimeUnit; /** * 时间工具类 @@ -21,86 +20,137 @@ import java.util.Date; */ @NoArgsConstructor(access = AccessLevel.PRIVATE) public class DateUtils extends org.apache.commons.lang3.time.DateUtils { - - public static final String YYYY = "yyyy"; - - public static final String YYYY_MM = "yyyy-MM"; - - public static final String YYYY_MM_DD = "yyyy-MM-dd"; - - public static final String YYYYMMDDHHMMSS = "yyyyMMddHHmmss"; - - public static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss"; - private static final String[] PARSE_PATTERNS = { "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM", "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM", "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"}; /** - * 获取当前Date型日期 + * 获取当前日期和时间 * - * @return Date() 当前日期 + * @return 当前日期和时间的 Date 对象表示 */ public static Date getNowDate() { return new Date(); } /** - * 获取当前日期, 默认格式为yyyy-MM-dd + * 获取当前日期的字符串表示,格式为YYYY-MM-DD * - * @return String + * @return 当前日期的字符串表示 */ public static String getDate() { - return dateTimeNow(YYYY_MM_DD); + return dateTimeNow(FormatsType.YYYY_MM_DD); } + /** + * 获取当前日期的字符串表示,格式为yyyyMMdd + * + * @return 当前日期的字符串表示 + */ + public static String getCurrentDate() { + return DateFormatUtils.format(new Date(), FormatsType.YYYYMMDD.getTimeFormat()); + } + + /** + * 获取当前日期的路径格式字符串,格式为"yyyy/MM/dd" + * + * @return 当前日期的路径格式字符串 + */ + public static String datePath() { + Date now = new Date(); + return DateFormatUtils.format(now, FormatsType.YYYY_MM_DD_SLASH.getTimeFormat()); + } + + /** + * 获取当前时间的字符串表示,格式为YYYY-MM-DD HH:MM:SS + * + * @return 当前时间的字符串表示 + */ public static String getTime() { - return dateTimeNow(YYYY_MM_DD_HH_MM_SS); + return dateTimeNow(FormatsType.YYYY_MM_DD_HH_MM_SS); } + /** + * 获取当前时间的字符串表示,格式为 "HH:MM:SS" + * + * @return 当前时间的字符串表示,格式为 "HH:MM:SS" + */ + public static String getTimeWithHourMinuteSecond() { + return dateTimeNow(FormatsType.HH_MM_SS); + } + + /** + * 获取当前日期和时间的字符串表示,格式为YYYYMMDDHHMMSS + * + * @return 当前日期和时间的字符串表示 + */ public static String dateTimeNow() { - return dateTimeNow(YYYYMMDDHHMMSS); + return dateTimeNow(FormatsType.YYYYMMDDHHMMSS); } - public static String dateTimeNow(final String format) { + /** + * 获取当前日期和时间的指定格式的字符串表示 + * + * @param format 日期时间格式,例如"YYYY-MM-DD HH:MM:SS" + * @return 当前日期和时间的字符串表示 + */ + public static String dateTimeNow(final FormatsType format) { return parseDateToStr(format, new Date()); } - public static String dateTime(final Date date) { - return parseDateToStr(YYYY_MM_DD, date); + /** + * 将指定日期格式化为 YYYY-MM-DD 格式的字符串 + * + * @param date 要格式化的日期对象 + * @return 格式化后的日期字符串 + */ + public static String formatDate(final Date date) { + return parseDateToStr(FormatsType.YYYY_MM_DD, date); } - public static String parseDateToStr(final String format, final Date date) { - return new SimpleDateFormat(format).format(date); + /** + * 将指定日期格式化为 YYYY-MM-DD HH:MM:SS 格式的字符串 + * + * @param date 要格式化的日期对象 + * @return 格式化后的日期时间字符串 + */ + public static String formatDateTime(final Date date) { + return parseDateToStr(FormatsType.YYYY_MM_DD_HH_MM_SS, date); } - public static Date dateTime(final String format, final String ts) { + /** + * 将指定日期按照指定格式进行格式化 + * + * @param format 要使用的日期时间格式,例如"YYYY-MM-DD HH:MM:SS" + * @param date 要格式化的日期对象 + * @return 格式化后的日期时间字符串 + */ + public static String parseDateToStr(final FormatsType format, final Date date) { + return new SimpleDateFormat(format.getTimeFormat()).format(date); + } + + /** + * 将指定格式的日期时间字符串转换为 Date 对象 + * + * @param format 要解析的日期时间格式,例如"YYYY-MM-DD HH:MM:SS" + * @param ts 要解析的日期时间字符串 + * @return 解析后的 Date 对象 + * @throws RuntimeException 如果解析过程中发生异常 + */ + public static Date parseDateTime(final FormatsType format, final String ts) { try { - return new SimpleDateFormat(format).parse(ts); + return new SimpleDateFormat(format.getTimeFormat()).parse(ts); } catch (ParseException e) { throw new RuntimeException(e); } } /** - * 日期路径 即年/月/日 如2018/08/08 - */ - public static String datePath() { - Date now = new Date(); - return DateFormatUtils.format(now, "yyyy/MM/dd"); - } - - /** - * 日期路径 即年/月/日 如20180808 - */ - public static String dateTime() { - Date now = new Date(); - return DateFormatUtils.format(now, "yyyyMMdd"); - } - - /** - * 日期型字符串转化为日期 格式 + * 将对象转换为日期对象 + * + * @param str 要转换的对象,通常是字符串 + * @return 转换后的日期对象,如果转换失败或输入为null,则返回null */ public static Date parseDate(Object str) { if (str == null) { @@ -115,6 +165,8 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils { /** * 获取服务器启动时间 + * + * @return 服务器启动时间的 Date 对象表示 */ public static Date getServerStartDate() { long time = ManagementFactory.getRuntimeMXBean().getStartTime(); @@ -122,35 +174,66 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils { } /** - * 计算相差天数 + * 计算两个日期之间的天数差(以毫秒为单位) + * + * @param date1 第一个日期 + * @param date2 第二个日期 + * @return 两个日期之间的天数差的绝对值 */ public static int differentDaysByMillisecond(Date date1, Date date2) { return Math.abs((int) ((date2.getTime() - date1.getTime()) / (1000 * 3600 * 24))); } /** - * 计算两个时间差 + * 计算两个日期之间的时间差,并以天、小时和分钟的格式返回 + * + * @param endDate 结束日期 + * @param nowDate 当前日期 + * @return 表示时间差的字符串,格式为"天 小时 分钟" */ public static String getDatePoor(Date endDate, Date nowDate) { - long nd = 1000 * 24 * 60 * 60; - long nh = 1000 * 60 * 60; - long nm = 1000 * 60; - // long ns = 1000; - // 获得两个时间的毫秒时间差异 - long diff = endDate.getTime() - nowDate.getTime(); - // 计算差多少天 - long day = diff / nd; - // 计算差多少小时 - long hour = diff % nd / nh; - // 计算差多少分钟 - long min = diff % nd % nh / nm; - // 计算差多少秒//输出结果 - // long sec = diff % nd % nh % nm / ns; - return day + "天" + hour + "小时" + min + "分钟"; + long diffInMillis = endDate.getTime() - nowDate.getTime(); + long day = TimeUnit.MILLISECONDS.toDays(diffInMillis); + long hour = TimeUnit.MILLISECONDS.toHours(diffInMillis) % 24; + long min = TimeUnit.MILLISECONDS.toMinutes(diffInMillis) % 60; + return String.format("%d天 %d小时 %d分钟", day, hour, min); } /** - * 增加 LocalDateTime ==> Date + * 计算两个时间点的差值(天、小时、分钟、秒),当值为0时不显示该单位 + * + * @param endDate 结束时间 + * @param nowDate 当前时间 + * @return 时间差字符串,格式为 "x天 x小时 x分钟 x秒",若为 0 则不显示 + */ + public static String getTimeDifference(Date endDate, Date nowDate) { + long diffInMillis = endDate.getTime() - nowDate.getTime(); + long day = TimeUnit.MILLISECONDS.toDays(diffInMillis); + long hour = TimeUnit.MILLISECONDS.toHours(diffInMillis) % 24; + long min = TimeUnit.MILLISECONDS.toMinutes(diffInMillis) % 60; + long sec = TimeUnit.MILLISECONDS.toSeconds(diffInMillis) % 60; + // 构建时间差字符串,条件是值不为0才显示 + StringBuilder result = new StringBuilder(); + if (day > 0) { + result.append(String.format("%d天 ", day)); + } + if (hour > 0) { + result.append(String.format("%d小时 ", hour)); + } + if (min > 0) { + result.append(String.format("%d分钟 ", min)); + } + if (sec > 0) { + result.append(String.format("%d秒", sec)); + } + return result.length() > 0 ? result.toString().trim() : "0秒"; + } + + /** + * 将 LocalDateTime 对象转换为 Date 对象 + * + * @param temporalAccessor 要转换的 LocalDateTime 对象 + * @return 转换后的 Date 对象 */ public static Date toDate(LocalDateTime temporalAccessor) { ZonedDateTime zdt = temporalAccessor.atZone(ZoneId.systemDefault()); @@ -158,11 +241,46 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils { } /** - * 增加 LocalDate ==> Date + * 将 LocalDate 对象转换为 Date 对象 + * + * @param temporalAccessor 要转换的 LocalDate 对象 + * @return 转换后的 Date 对象 */ public static Date toDate(LocalDate temporalAccessor) { LocalDateTime localDateTime = LocalDateTime.of(temporalAccessor, LocalTime.of(0, 0, 0)); ZonedDateTime zdt = localDateTime.atZone(ZoneId.systemDefault()); return Date.from(zdt.toInstant()); } + + /** + * 校验日期范围 + * + * @param startDate 开始日期 + * @param endDate 结束日期 + * @param maxValue 最大时间跨度的限制值 + * @param unit 时间跨度的单位,可选择 "DAYS"、"HOURS" 或 "MINUTES" + */ + public static void validateDateRange(Date startDate, Date endDate, int maxValue, TimeUnit unit) { + // 校验结束日期不能早于开始日期 + if (endDate.before(startDate)) { + throw new ServiceException("结束日期不能早于开始日期"); + } + + // 计算时间跨度 + long diffInMillis = endDate.getTime() - startDate.getTime(); + + // 根据单位转换时间跨度 + long diff = switch (unit) { + case DAYS -> TimeUnit.MILLISECONDS.toDays(diffInMillis); + case HOURS -> TimeUnit.MILLISECONDS.toHours(diffInMillis); + case MINUTES -> TimeUnit.MILLISECONDS.toMinutes(diffInMillis); + default -> throw new IllegalArgumentException("不支持的时间单位"); + }; + + // 校验时间跨度不超过最大限制 + if (diff > maxValue) { + throw new ServiceException("最大时间跨度为 " + maxValue + " " + unit.toString().toLowerCase()); + } + } + } From c566f2ae28afa2159617bcbda325afc4646e8cd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Thu, 12 Dec 2024 23:38:16 +0800 Subject: [PATCH 101/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E8=B0=83?= =?UTF-8?q?=E6=95=B4=E6=96=B9=E6=B3=95=E4=BD=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/impl/SysDeptServiceImpl.java | 50 +++++++++---------- 1 file changed, 25 insertions(+), 25 deletions(-) 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 be9e33d8b..0199ec719 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 @@ -176,6 +176,31 @@ public class SysDeptServiceImpl implements ISysDeptService, DeptService { return String.join(StringUtils.SEPARATOR, list); } + /** + * 根据部门ID查询部门负责人 + * + * @param deptId 部门ID,用于指定需要查询的部门 + * @return 返回该部门的负责人ID + */ + @Override + public Long selectDeptLeaderById(Long deptId) { + SysDeptVo vo = SpringUtils.getAopProxy(this).selectDeptById(deptId); + return vo.getLeader(); + } + + /** + * 查询部门 + * + * @return 部门列表 + */ + @Override + public List selectDeptsByList() { + List list = baseMapper.selectDeptList(new LambdaQueryWrapper() + .select(SysDept::getDeptId, SysDept::getDeptName, SysDept::getParentId) + .eq(SysDept::getStatus, SystemConstants.NORMAL)); + return BeanUtil.copyToList(list, DeptDTO.class); + } + /** * 根据ID查询所有子部门数(正常状态) * @@ -356,29 +381,4 @@ public class SysDeptServiceImpl implements ISysDeptService, DeptService { return baseMapper.deleteById(deptId); } - /** - * 根据部门ID查询部门负责人 - * - * @param deptId 部门ID,用于指定需要查询的部门 - * @return 返回该部门的负责人ID - */ - @Override - public Long selectDeptLeaderById(Long deptId) { - SysDeptVo vo = SpringUtils.getAopProxy(this).selectDeptById(deptId); - return vo.getLeader(); - } - - /** - * 查询部门 - * - * @return 部门列表 - */ - @Override - public List selectDeptsByList() { - List list = baseMapper.selectDeptList(new LambdaQueryWrapper() - .select(SysDept::getDeptId, SysDept::getDeptName, SysDept::getParentId) - .eq(SysDept::getStatus, SystemConstants.NORMAL)); - return BeanUtil.copyToList(list, DeptDTO.class); - } - } From 0185a468bdb790ace78a37c69dbccc61063b2945 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Fri, 13 Dec 2024 00:15:30 +0800 Subject: [PATCH 102/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E5=88=A0?= =?UTF-8?q?=E9=99=A4=E6=97=A0=E7=94=A8=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/dromara/system/mapper/SysDeptMapper.java | 12 ------------ .../main/resources/mapper/system/SysDeptMapper.xml | 11 ----------- 2 files changed, 23 deletions(-) diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysDeptMapper.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysDeptMapper.java index b69624cf0..0f2c90667 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysDeptMapper.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysDeptMapper.java @@ -3,7 +3,6 @@ package org.dromara.system.mapper; import com.baomidou.mybatisplus.core.conditions.Wrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Constants; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import org.apache.ibatis.annotations.Param; import org.dromara.common.mybatis.annotation.DataColumn; import org.dromara.common.mybatis.annotation.DataPermission; @@ -32,17 +31,6 @@ public interface SysDeptMapper extends BaseMapperPlus { }) List selectDeptList(@Param(Constants.WRAPPER) Wrapper queryWrapper); - /** - * 分页查询部门管理数据 - * - * @param queryWrapper 查询条件 - * @return 部门信息集合 - */ - @DataPermission({ - @DataColumn(key = "deptName", value = "dept_id"), - }) - Page selectPageDeptList(@Param("page") Page page, @Param(Constants.WRAPPER) Wrapper queryWrapper); - /** * 统计指定部门ID的部门数量 * diff --git a/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml b/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml index 9057a0e22..6ad866f29 100644 --- a/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml +++ b/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml @@ -18,17 +18,6 @@ from sys_dept ${ew.getCustomSqlSegment} - - From fcebda8987a21a1a30e1fd3ec690bafed794b91f Mon Sep 17 00:00:00 2001 From: QianRj <14974713+qianrj@user.noreply.gitee.com> Date: Fri, 13 Dec 2024 20:37:55 +0800 Subject: [PATCH 103/175] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E6=9D=83=E9=99=90=E7=BC=93=E5=AD=98=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dromara/system/service/impl/SysDataScopeServiceImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDataScopeServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDataScopeServiceImpl.java index 470646f35..12a507203 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDataScopeServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDataScopeServiceImpl.java @@ -38,7 +38,7 @@ public class SysDataScopeServiceImpl implements ISysDataScopeService { * @param roleId 角色Id * @return 部门Id组 */ - @Cacheable(cacheNames = CacheNames.SYS_ROLE_CUSTOM, key = "#roleId") + @Cacheable(cacheNames = CacheNames.SYS_ROLE_CUSTOM, key = "#roleId", condition = "#roleId != null") @Override public String getRoleCustom(Long roleId) { if (ObjectUtil.isNull(roleId)) { @@ -60,7 +60,7 @@ public class SysDataScopeServiceImpl implements ISysDataScopeService { * @param deptId 部门Id * @return 部门Id组 */ - @Cacheable(cacheNames = CacheNames.SYS_DEPT_AND_CHILD, key = "#deptId") + @Cacheable(cacheNames = CacheNames.SYS_DEPT_AND_CHILD, key = "#deptId", condition = "#deptId != null") @Override public String getDeptAndChild(Long deptId) { if (ObjectUtil.isNull(deptId)) { From df6649907dbd82b2aeb4e0e676185920241506ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Sat, 14 Dec 2024 23:05:15 +0800 Subject: [PATCH 104/175] =?UTF-8?q?update=20justauth=201.16.6=20=3D>=201.1?= =?UTF-8?q?6.7=20=E6=94=AF=E6=8C=81=E5=A4=9A=E7=A7=8D=E7=99=BB=E5=BD=95?= =?UTF-8?q?=E6=96=B9=E5=BC=8F=20=E4=B8=8D=E9=99=90=E4=BA=8E=E4=B8=89?= =?UTF-8?q?=E6=96=B9=E7=99=BB=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 58672cae4..ebf2814ed 100644 --- a/pom.xml +++ b/pom.xml @@ -36,7 +36,7 @@ 0.2.0 1.18.34 1.76 - 1.16.6 + 1.16.7 2.7.0 From c8ed71d010d957a5873730bb03e984d8cb1ec0c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Sat, 14 Dec 2024 23:06:09 +0800 Subject: [PATCH 105/175] =?UTF-8?q?update=20=E4=BD=BF=E7=94=A8justauth?= =?UTF-8?q?=E6=89=A9=E5=B1=95=E5=8A=9F=E8=83=BD=E6=94=AF=E6=8C=81=E5=BE=AE?= =?UTF-8?q?=E4=BF=A1=E5=B0=8F=E7=A8=8B=E5=BA=8F=E7=99=BB=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/service/impl/XcxAuthStrategy.java | 26 ++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/ruoyi-admin/src/main/java/org/dromara/web/service/impl/XcxAuthStrategy.java b/ruoyi-admin/src/main/java/org/dromara/web/service/impl/XcxAuthStrategy.java index 948ed9acb..fa9b61819 100644 --- a/ruoyi-admin/src/main/java/org/dromara/web/service/impl/XcxAuthStrategy.java +++ b/ruoyi-admin/src/main/java/org/dromara/web/service/impl/XcxAuthStrategy.java @@ -5,9 +5,17 @@ import cn.dev33.satoken.stp.StpUtil; import cn.hutool.core.util.ObjectUtil; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import me.zhyd.oauth.config.AuthConfig; +import me.zhyd.oauth.model.AuthCallback; +import me.zhyd.oauth.model.AuthResponse; +import me.zhyd.oauth.model.AuthToken; +import me.zhyd.oauth.model.AuthUser; +import me.zhyd.oauth.request.AuthRequest; +import me.zhyd.oauth.request.AuthWechatMiniProgramRequest; import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.core.domain.model.XcxLoginBody; import org.dromara.common.core.domain.model.XcxLoginUser; +import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.utils.ValidatorUtils; import org.dromara.common.json.utils.JsonUtils; import org.dromara.common.satoken.utils.LoginHelper; @@ -39,12 +47,24 @@ public class XcxAuthStrategy implements IAuthStrategy { // 多个小程序识别使用 String appid = loginBody.getAppid(); - // todo 以下自行实现 // 校验 appid + appsrcret + xcxCode 调用登录凭证校验接口 获取 session_key 与 openid - String openid = ""; + AuthRequest authRequest = new AuthWechatMiniProgramRequest(AuthConfig.builder() + .clientId(appid).clientSecret("自行填写密钥 可根据不同appid填入不同密钥") + .ignoreCheckRedirectUri(true).ignoreCheckState(true).build()); + AuthCallback authCallback = new AuthCallback(); + authCallback.setCode(xcxCode); + AuthResponse resp = authRequest.login(authCallback); + String openid, unionId; + if (resp.ok()) { + AuthToken token = resp.getData().getToken(); + openid = token.getOpenId(); + // 微信小程序只有关联到微信开放平台下之后才能获取到 unionId,因此unionId不一定能返回。 + unionId = token.getUnionId(); + } else { + throw new ServiceException(resp.getMsg()); + } // 框架登录不限制从什么表查询 只要最终构建出 LoginUser 即可 SysUserVo user = loadUserByOpenid(openid); - // 此处可根据登录用户的数据不同 自行创建 loginUser 属性不够用继承扩展就行了 XcxLoginUser loginUser = new XcxLoginUser(); loginUser.setTenantId(user.getTenantId()); From 7f6b71d9384d3597e3bec56753414c410bfa9f54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Sun, 15 Dec 2024 16:24:52 +0800 Subject: [PATCH 106/175] =?UTF-8?q?fix=20=E4=BF=AE=E5=A4=8D=20=E5=8D=87?= =?UTF-8?q?=E7=BA=A7justauth=E5=BA=95=E5=B1=82=E6=96=B9=E6=B3=95=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=E5=AF=BC=E8=87=B4=E4=BB=A3=E7=A0=81=E7=BC=96=E8=AF=91?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/dromara/common/social/maxkey/AuthMaxKeyRequest.java | 4 ++-- .../org/dromara/common/social/topiam/AuthTopIamRequest.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/maxkey/AuthMaxKeyRequest.java b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/maxkey/AuthMaxKeyRequest.java index b95c19ee8..97774ac5d 100644 --- a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/maxkey/AuthMaxKeyRequest.java +++ b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/maxkey/AuthMaxKeyRequest.java @@ -30,7 +30,7 @@ public class AuthMaxKeyRequest extends AuthDefaultRequest { } @Override - protected AuthToken getAccessToken(AuthCallback authCallback) { + public AuthToken getAccessToken(AuthCallback authCallback) { String body = doPostAuthorizationCode(authCallback.getCode()); Dict object = JsonUtils.parseMap(body); // oauth/token 验证异常 @@ -51,7 +51,7 @@ public class AuthMaxKeyRequest extends AuthDefaultRequest { } @Override - protected AuthUser getUserInfo(AuthToken authToken) { + public AuthUser getUserInfo(AuthToken authToken) { String body = doGetUserInfo(authToken); Dict object = JsonUtils.parseMap(body); // oauth/token 验证异常 diff --git a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/topiam/AuthTopIamRequest.java b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/topiam/AuthTopIamRequest.java index 13649f9fd..13f198daa 100644 --- a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/topiam/AuthTopIamRequest.java +++ b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/topiam/AuthTopIamRequest.java @@ -41,7 +41,7 @@ public class AuthTopIamRequest extends AuthDefaultRequest { } @Override - protected AuthToken getAccessToken(AuthCallback authCallback) { + public AuthToken getAccessToken(AuthCallback authCallback) { String body = doPostAuthorizationCode(authCallback.getCode()); Dict object = JsonUtils.parseMap(body); checkResponse(object); @@ -55,7 +55,7 @@ public class AuthTopIamRequest extends AuthDefaultRequest { } @Override - protected AuthUser getUserInfo(AuthToken authToken) { + public AuthUser getUserInfo(AuthToken authToken) { String body = doGetUserInfo(authToken); Dict object = JsonUtils.parseMap(body); checkResponse(object); From aface5ded1e2ecf0e8f98434cb69b354758cefe6 Mon Sep 17 00:00:00 2001 From: xlsea Date: Mon, 16 Dec 2024 18:53:58 +0800 Subject: [PATCH 107/175] =?UTF-8?q?update=20=E9=80=82=E9=85=8D=20TOPIAM=20?= =?UTF-8?q?2.0=20=E5=8D=95=E7=82=B9=E7=99=BB=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/application-dev.yml | 2 +- .../common/social/topiam/AuthTopIamRequest.java | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/ruoyi-admin/src/main/resources/application-dev.yml b/ruoyi-admin/src/main/resources/application-dev.yml index 283cdad44..e4f6086cc 100644 --- a/ruoyi-admin/src/main/resources/application-dev.yml +++ b/ruoyi-admin/src/main/resources/application-dev.yml @@ -200,7 +200,7 @@ justauth: redirect-uri: ${justauth.address}/social-callback?source=maxkey topiam: # topiam 服务器地址 - server-url: http://127.0.0.1:1989/api/v1/authorize/y0q************spq***********8ol + server-url: http://127.0.0.1:1898/api/v1/authorize/y0q************spq***********8ol client-id: 449c4*********937************759 client-secret: ac7***********1e0************28d redirect-uri: ${justauth.address}/social-callback?source=topiam diff --git a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/topiam/AuthTopIamRequest.java b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/topiam/AuthTopIamRequest.java index 13649f9fd..4867cdc94 100644 --- a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/topiam/AuthTopIamRequest.java +++ b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/topiam/AuthTopIamRequest.java @@ -1,7 +1,10 @@ package org.dromara.common.social.topiam; +import cn.hutool.core.codec.Base64; import cn.hutool.core.lang.Dict; import cn.hutool.core.util.StrUtil; +import cn.hutool.http.HttpRequest; +import cn.hutool.http.HttpResponse; import com.xkcoding.http.support.HttpHeader; import lombok.extern.slf4j.Slf4j; import me.zhyd.oauth.cache.AuthStateCache; @@ -70,6 +73,16 @@ public class AuthTopIamRequest extends AuthDefaultRequest { .build(); } + @Override + protected String doPostAuthorizationCode(String code) { + HttpRequest request = HttpRequest.post(source.accessToken()) + .header("Authorization", "Basic " + Base64.encode("%s:%s".formatted(config.getClientId(), config.getClientSecret()))) + .form("grant_type", "authorization_code") + .form("code", code) + .form("redirect_uri", config.getRedirectUri()); + HttpResponse response = request.execute(); + return response.body(); + } @Override protected String doGetUserInfo(AuthToken authToken) { @@ -86,7 +99,7 @@ public class AuthTopIamRequest extends AuthDefaultRequest { .build(); } - public static void checkResponse(Dict object) { + private static void checkResponse(Dict object) { // oauth/token 验证异常 if (object.containsKey("error")) { throw new AuthException(object.getStr("error_description")); From 9768023d38fe266cbd0e229a508d4e65258efa45 Mon Sep 17 00:00:00 2001 From: QianRj <14974713+qianrj@user.noreply.gitee.com> Date: Tue, 17 Dec 2024 12:35:19 +0800 Subject: [PATCH 108/175] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E6=9D=83=E9=99=90=E5=AF=BC=E8=87=B4=E7=9A=84=E4=B8=AA?= =?UTF-8?q?=E4=BA=BA=E4=B8=AD=E5=BF=83=E7=9A=84=E4=BF=AE=E6=94=B9=E5=A4=B4?= =?UTF-8?q?=E5=83=8F=E5=92=8C=E4=BF=AE=E6=94=B9=E5=AF=86=E7=A0=81=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../system/controller/system/SysProfileController.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysProfileController.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysProfileController.java index 893b381e3..5f187cb91 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysProfileController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysProfileController.java @@ -98,8 +98,8 @@ public class SysProfileController extends BaseController { if (BCrypt.checkpw(bo.getNewPassword(), password)) { return R.fail("新密码不能与旧密码相同"); } - - if (userService.resetUserPwd(user.getUserId(), BCrypt.hashpw(bo.getNewPassword())) > 0) { + int rows = DataPermissionHelper.ignore(() -> userService.resetUserPwd(user.getUserId(), BCrypt.hashpw(bo.getNewPassword()))); + if (rows > 0) { return R.ok(); } return R.fail("修改密码异常,请联系管理员"); @@ -121,7 +121,8 @@ public class SysProfileController extends BaseController { } SysOssVo oss = ossService.upload(avatarfile); String avatar = oss.getUrl(); - if (userService.updateUserAvatar(LoginHelper.getUserId(), oss.getOssId())) { + boolean updateSuccess = DataPermissionHelper.ignore(() -> userService.updateUserAvatar(LoginHelper.getUserId(), oss.getOssId())); + if (updateSuccess) { AvatarVo avatarVo = new AvatarVo(); avatarVo.setImgUrl(avatar); return R.ok(avatarVo); From 489cb52976b4597c7d2f2e0c51fc88908b2897ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=89=9B=E5=AD=90Li?= Date: Tue, 17 Dec 2024 07:34:15 +0000 Subject: [PATCH 109/175] =?UTF-8?q?!620=20update=20=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E6=97=A5=E5=BF=97=E9=A2=9C=E8=89=B2=20*=20update=20=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=E6=97=A5=E5=BF=97=E9=A2=9C=E8=89=B2=20*=20update=20?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=97=A5=E5=BF=97=E9=A2=9C=E8=89=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ruoyi-admin/src/main/resources/logback-plus.xml | 2 +- .../ruoyi-monitor-admin/src/main/resources/logback-plus.xml | 4 ++-- .../ruoyi-snailjob-server/src/main/resources/logback-plus.xml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ruoyi-admin/src/main/resources/logback-plus.xml b/ruoyi-admin/src/main/resources/logback-plus.xml index 40fa33b7c..b74289ecd 100644 --- a/ruoyi-admin/src/main/resources/logback-plus.xml +++ b/ruoyi-admin/src/main/resources/logback-plus.xml @@ -2,7 +2,7 @@ + value="%cyan(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) %highlight(%-5level) %boldMagenta(%logger{36}%n) - %msg%n"/> diff --git a/ruoyi-extend/ruoyi-monitor-admin/src/main/resources/logback-plus.xml b/ruoyi-extend/ruoyi-monitor-admin/src/main/resources/logback-plus.xml index 16bb9376b..45cbbba40 100644 --- a/ruoyi-extend/ruoyi-monitor-admin/src/main/resources/logback-plus.xml +++ b/ruoyi-extend/ruoyi-monitor-admin/src/main/resources/logback-plus.xml @@ -4,7 +4,7 @@ logback + value="%cyan(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) %highlight(%-5level) %boldMagenta(%logger{36}%n) - %msg%n"/> @@ -31,4 +31,4 @@ - \ No newline at end of file + diff --git a/ruoyi-extend/ruoyi-snailjob-server/src/main/resources/logback-plus.xml b/ruoyi-extend/ruoyi-snailjob-server/src/main/resources/logback-plus.xml index a40262c9f..be588110c 100644 --- a/ruoyi-extend/ruoyi-snailjob-server/src/main/resources/logback-plus.xml +++ b/ruoyi-extend/ruoyi-snailjob-server/src/main/resources/logback-plus.xml @@ -2,7 +2,7 @@ + value="%cyan(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) %highlight(%-5level) %boldMagenta(%logger{36}%n) - %msg%n"/> From a65baf5d67c3a3d5a3013aec89f406fc3d4b7bbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Wed, 18 Dec 2024 11:32:14 +0800 Subject: [PATCH 110/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0mybatis-plus=E4=B8=80=E9=94=AE=E5=BC=80=E5=90=AF/?= =?UTF-8?q?=E5=85=B3=E9=97=AD=E9=80=BB=E8=BE=91=E5=88=A0=E9=99=A4=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/application.yml | 2 ++ .../mybatis/config/MybatisPlusConfig.java | 10 ++++++++ .../handler/PlusPostInitTableInfoHandler.java | 24 +++++++++++++++++++ 3 files changed, 36 insertions(+) create mode 100644 ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/PlusPostInitTableInfoHandler.java diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml index dead74198..c42bb7f26 100644 --- a/ruoyi-admin/src/main/resources/application.yml +++ b/ruoyi-admin/src/main/resources/application.yml @@ -139,6 +139,8 @@ tenant: # MyBatisPlus配置 # https://baomidou.com/config/ mybatis-plus: + # 自定义配置 是否全局开启逻辑删除 关闭后 所有逻辑删除功能将失效 + enableLogicDelete: true # 多包名使用 例如 org.dromara.**.mapper,org.xxx.**.mapper mapperPackage: org.dromara.**.mapper # 对应的 XML 文件位置 diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/config/MybatisPlusConfig.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/config/MybatisPlusConfig.java index 1e8d619fa..00c26912e 100644 --- a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/config/MybatisPlusConfig.java +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/config/MybatisPlusConfig.java @@ -2,6 +2,7 @@ package org.dromara.common.mybatis.config; import cn.hutool.core.net.NetUtil; import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; +import com.baomidou.mybatisplus.core.handlers.PostInitTableInfoHandler; import com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator; import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator; import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; @@ -13,6 +14,7 @@ import org.dromara.common.core.utils.SpringUtils; import org.dromara.common.mybatis.aspect.DataPermissionAspect; import org.dromara.common.mybatis.handler.InjectionMetaObjectHandler; import org.dromara.common.mybatis.handler.MybatisExceptionHandler; +import org.dromara.common.mybatis.handler.PlusPostInitTableInfoHandler; import org.dromara.common.mybatis.interceptor.PlusDataPermissionInterceptor; import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.BeansException; @@ -105,6 +107,14 @@ public class MybatisPlusConfig { return new MybatisExceptionHandler(); } + /** + * 初始化表对象处理器 + */ + @Bean + public PostInitTableInfoHandler postInitTableInfoHandler() { + return new PlusPostInitTableInfoHandler(); + } + /** * PaginationInnerInterceptor 分页插件,自动识别数据库类型 * https://baomidou.com/pages/97710a/ diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/PlusPostInitTableInfoHandler.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/PlusPostInitTableInfoHandler.java new file mode 100644 index 000000000..2c0ec0e1d --- /dev/null +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/PlusPostInitTableInfoHandler.java @@ -0,0 +1,24 @@ +package org.dromara.common.mybatis.handler; + +import cn.hutool.core.convert.Convert; +import com.baomidou.mybatisplus.core.handlers.PostInitTableInfoHandler; +import com.baomidou.mybatisplus.core.metadata.TableInfo; +import org.apache.ibatis.session.Configuration; +import org.dromara.common.core.utils.SpringUtils; +import org.dromara.common.core.utils.reflect.ReflectUtils; + +/** + * 修改表信息初始化方式 + * 目前用于全局修改是否使用逻辑删除 + * + * @author Lion Li + */ +public class PlusPostInitTableInfoHandler implements PostInitTableInfoHandler { + + @Override + public void postTableInfo(TableInfo tableInfo, Configuration configuration) { + String flag = SpringUtils.getProperty("mybatis-plus.enableLogicDelete", "true"); + ReflectUtils.setFieldValue(tableInfo, "withLogicDelete", Convert.toBool(flag)); + } + +} From da1cd55c1d4df9c8e08f32b69257010bd548d237 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Wed, 18 Dec 2024 13:30:09 +0800 Subject: [PATCH 111/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0mybatis-plus=E4=B8=80=E9=94=AE=E5=BC=80=E5=90=AF/?= =?UTF-8?q?=E5=85=B3=E9=97=AD=E9=80=BB=E8=BE=91=E5=88=A0=E9=99=A4=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/mybatis/handler/PlusPostInitTableInfoHandler.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/PlusPostInitTableInfoHandler.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/PlusPostInitTableInfoHandler.java index 2c0ec0e1d..60ca20b4b 100644 --- a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/PlusPostInitTableInfoHandler.java +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/PlusPostInitTableInfoHandler.java @@ -18,7 +18,10 @@ public class PlusPostInitTableInfoHandler implements PostInitTableInfoHandler { @Override public void postTableInfo(TableInfo tableInfo, Configuration configuration) { String flag = SpringUtils.getProperty("mybatis-plus.enableLogicDelete", "true"); - ReflectUtils.setFieldValue(tableInfo, "withLogicDelete", Convert.toBool(flag)); + // 只有关闭时 统一设置false 为true时mp自动判断不处理 + if (!Convert.toBool(flag)) { + ReflectUtils.setFieldValue(tableInfo, "withLogicDelete", false); + } } } From ff76df9ae0f2383db903bab3efc6ef1223d0d071 Mon Sep 17 00:00:00 2001 From: liyang Date: Wed, 11 Dec 2024 11:27:13 +0800 Subject: [PATCH 112/175] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=AF=BC=E5=87=BA?= =?UTF-8?q?=E6=A8=A1=E6=9D=BF=E5=BF=85=E5=A1=AB=E3=80=81=E5=A4=87=E6=B3=A8?= =?UTF-8?q?=20=E5=A2=9E=E5=8A=A0=E5=8D=95=E7=8B=AC=E7=9A=84=E5=AF=BC?= =?UTF-8?q?=E5=87=BA=E6=A8=A1=E6=9D=BF=20=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../excel/annotation/ExcelNotation.java | 24 +++++ .../excel/annotation/ExcelRequired.java | 26 ++++++ .../excel/handler/DataWriteHandler.java | 77 +++++++++++++++ .../dromara/common/excel/utils/ExcelUtil.java | 93 +++++++++++++++++++ 4 files changed, 220 insertions(+) create mode 100644 ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/annotation/ExcelNotation.java create mode 100644 ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/annotation/ExcelRequired.java create mode 100644 ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/handler/DataWriteHandler.java diff --git a/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/annotation/ExcelNotation.java b/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/annotation/ExcelNotation.java new file mode 100644 index 000000000..f358afcd6 --- /dev/null +++ b/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/annotation/ExcelNotation.java @@ -0,0 +1,24 @@ +package org.dromara.common.excel.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 批注 + * @author guzhouyanyu + */ +@Target({ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface ExcelNotation { + + /** + * col index + */ + int index() default -1; + /** + * 批注内容 + */ + String value() default ""; +} diff --git a/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/annotation/ExcelRequired.java b/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/annotation/ExcelRequired.java new file mode 100644 index 000000000..15784e140 --- /dev/null +++ b/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/annotation/ExcelRequired.java @@ -0,0 +1,26 @@ +package org.dromara.common.excel.annotation; + +import org.apache.poi.ss.usermodel.IndexedColors; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 是否必填 + * @author guzhouyanyu + */ +@Target({ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface ExcelRequired { + + /** + * col index + */ + int index() default -1; + /** + * 字体颜色 + */ + IndexedColors fontColor() default IndexedColors.RED; +} diff --git a/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/handler/DataWriteHandler.java b/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/handler/DataWriteHandler.java new file mode 100644 index 000000000..0d11360ba --- /dev/null +++ b/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/handler/DataWriteHandler.java @@ -0,0 +1,77 @@ +package org.dromara.common.excel.handler; + +import cn.hutool.core.collection.CollUtil; +import com.alibaba.excel.metadata.data.DataFormatData; +import com.alibaba.excel.metadata.data.WriteCellData; +import com.alibaba.excel.util.StyleUtil; +import com.alibaba.excel.write.handler.CellWriteHandler; +import com.alibaba.excel.write.handler.SheetWriteHandler; +import com.alibaba.excel.write.handler.context.CellWriteHandlerContext; +import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; +import com.alibaba.excel.write.metadata.style.WriteCellStyle; +import com.alibaba.excel.write.metadata.style.WriteFont; +import lombok.Data; +import org.apache.poi.ss.usermodel.*; +import org.apache.poi.xssf.usermodel.XSSFClientAnchor; +import org.apache.poi.xssf.usermodel.XSSFRichTextString; + +import java.util.Map; + +/** + * 批注、必填 + * + * @author guzhouyanyu + */ +@Data +public class DataWriteHandler implements SheetWriteHandler, CellWriteHandler { + + /** + * 批注 + */ + private final Map notationMap; + + /** + * 头列字体颜色 + */ + private final Map headColumnMap; + + + @Override + public void afterCellDispose(CellWriteHandlerContext context) { + WriteCellData cellData = context.getFirstCellData(); + WriteCellStyle writeCellStyle = cellData.getOrCreateStyle(); + + DataFormatData dataFormatData = new DataFormatData(); + // 单元格设置为文本格式 + dataFormatData.setIndex((short) 49); + writeCellStyle.setDataFormatData(dataFormatData); + + if (context.getHead()) { + Cell cell = context.getCell(); + WriteSheetHolder writeSheetHolder = context.getWriteSheetHolder(); + Sheet sheet = writeSheetHolder.getSheet(); + Workbook workbook = writeSheetHolder.getSheet().getWorkbook(); + Drawing drawing = sheet.createDrawingPatriarch(); + // 设置标题字体样式 + WriteFont headWriteFont = new WriteFont(); + // 加粗 + headWriteFont.setBold(true); + if (CollUtil.isNotEmpty(headColumnMap) && headColumnMap.containsKey(cell.getColumnIndex())) { + // 设置字体颜色 + headWriteFont.setColor(headColumnMap.get(cell.getColumnIndex())); + } + writeCellStyle.setWriteFont(headWriteFont); + CellStyle cellStyle = StyleUtil.buildCellStyle(workbook, null, writeCellStyle); + cell.setCellStyle(cellStyle); + + if (CollUtil.isNotEmpty(notationMap) && notationMap.containsKey(cell.getColumnIndex())) { + // 批注内容 + String notationContext = notationMap.get(cell.getColumnIndex()); + // 创建绘图对象 + Comment comment = drawing.createCellComment(new XSSFClientAnchor(0, 0, 0, 0, (short) cell.getColumnIndex(), 0, (short) 5, 5)); + comment.setString(new XSSFRichTextString(notationContext)); + cell.setCellComment(comment); + } + } + } +} diff --git a/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/utils/ExcelUtil.java b/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/utils/ExcelUtil.java index a6c14ad51..fa1fb902d 100644 --- a/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/utils/ExcelUtil.java +++ b/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/utils/ExcelUtil.java @@ -16,14 +16,20 @@ import lombok.AccessLevel; import lombok.NoArgsConstructor; import org.dromara.common.core.utils.StringUtils; import org.dromara.common.core.utils.file.FileUtils; +import org.dromara.common.core.utils.reflect.ReflectUtils; +import org.dromara.common.excel.annotation.ExcelNotation; +import org.dromara.common.excel.annotation.ExcelRequired; import org.dromara.common.excel.convert.ExcelBigNumberConvert; import org.dromara.common.excel.core.*; +import org.dromara.common.excel.handler.DataWriteHandler; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.UnsupportedEncodingException; +import java.lang.reflect.Field; import java.util.Collection; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -433,4 +439,91 @@ public class ExcelUtil { return IdUtil.fastSimpleUUID() + "_" + filename + ".xlsx"; } + /** + * 获取必填列Map + * + * @param clazz 类class + * @return java.util.Map + * @author SunLingDa + * @date 2022/11/3 13:23 + */ + private static Map getRequiredMap(Class clazz) { + Map requiredMap = new HashMap<>(); + Field[] fields = clazz.getDeclaredFields(); + // 检查 fields 数组是否为空 + if (fields.length == 0) { + return requiredMap; + } + Field[] filteredFields = ReflectUtils.getFields(clazz, field -> !"serialVersionUID".equals(field.getName())); + + for (int i = 0; i < filteredFields.length; i++) { + Field field = filteredFields[i]; + if (!field.isAnnotationPresent(ExcelRequired.class)) { + continue; + } + ExcelRequired excelRequired = field.getAnnotation(ExcelRequired.class); + int columnIndex = excelRequired.index() == -1 ? i : excelRequired.index(); + requiredMap.put(columnIndex, excelRequired.fontColor().getIndex()); + } + return requiredMap; + } + + /** + * 获取批注Map + * + * @param clazz 类class + * @return java.util.Map + * @author SunLingDa + * @date 2022/11/3 13:24 + */ + private static Map getNotationMap(Class clazz) { + Map notationMap = new HashMap<>(); + Field[] fields = clazz.getDeclaredFields(); + // 检查 fields 数组是否为空 + if (fields.length == 0) { + return notationMap; + } + Field[] filteredFields = ReflectUtils.getFields(clazz, field -> !"serialVersionUID".equals(field.getName())); + for (int i = 0; i < filteredFields.length; i++) { + Field field = filteredFields[i]; + if (!field.isAnnotationPresent(ExcelNotation.class)) { + continue; + } + ExcelNotation excelNotation = field.getAnnotation(ExcelNotation.class); + int columnIndex = excelNotation.index() == -1 ? i : excelNotation.index(); + notationMap.put(columnIndex, excelNotation.value()); + } + return notationMap; + } + public static void exportExcelRequire(List list, String sheetName, Class clazz,HttpServletResponse response) { + exportExcelTemplate(list,sheetName,clazz,response); + } + /** + * 导出excel模板 + * + * @param list 导出数据集合 + * @param sheetName 工作表的名称 + * @param clazz 实体类 + * @param response 响应体 + */ + public static void exportExcelTemplate(List list, String sheetName, Class clazz, HttpServletResponse response) { + try { + Map requiredMap = getRequiredMap(clazz); + Map notationMap = getNotationMap(clazz); + resetResponse(sheetName, response); + ServletOutputStream os = response.getOutputStream(); + DataWriteHandler writeHandler = new DataWriteHandler(notationMap, requiredMap); + ExcelWriterSheetBuilder builder = EasyExcel.write(os, clazz) + .autoCloseStream(false) + // 自动适配 + .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) + .registerWriteHandler(writeHandler) + // 大数值自动转换 防止失真 + .registerConverter(new ExcelBigNumberConvert()) + .sheet(sheetName); + builder.doWrite(list); + } catch (IOException e) { + throw new RuntimeException("导出Excel异常"); + } + } } From 9ad64521d39e722b74379cc33c78de4cd0b426b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Wed, 18 Dec 2024 17:46:53 +0800 Subject: [PATCH 113/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20!pr=5F610?= =?UTF-8?q?=20=E4=BB=A3=E7=A0=81=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../excel/handler/DataWriteHandler.java | 62 ++++++++- .../dromara/common/excel/utils/ExcelUtil.java | 118 +++--------------- .../dromara/demo/domain/vo/TestDemoVo.java | 7 ++ 3 files changed, 81 insertions(+), 106 deletions(-) diff --git a/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/handler/DataWriteHandler.java b/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/handler/DataWriteHandler.java index 0d11360ba..a2aa4951b 100644 --- a/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/handler/DataWriteHandler.java +++ b/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/handler/DataWriteHandler.java @@ -10,11 +10,15 @@ import com.alibaba.excel.write.handler.context.CellWriteHandlerContext; import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; import com.alibaba.excel.write.metadata.style.WriteCellStyle; import com.alibaba.excel.write.metadata.style.WriteFont; -import lombok.Data; import org.apache.poi.ss.usermodel.*; import org.apache.poi.xssf.usermodel.XSSFClientAnchor; import org.apache.poi.xssf.usermodel.XSSFRichTextString; +import org.dromara.common.core.utils.reflect.ReflectUtils; +import org.dromara.common.excel.annotation.ExcelNotation; +import org.dromara.common.excel.annotation.ExcelRequired; +import java.lang.reflect.Field; +import java.util.HashMap; import java.util.Map; /** @@ -22,7 +26,6 @@ import java.util.Map; * * @author guzhouyanyu */ -@Data public class DataWriteHandler implements SheetWriteHandler, CellWriteHandler { /** @@ -36,8 +39,16 @@ public class DataWriteHandler implements SheetWriteHandler, CellWriteHandler { private final Map headColumnMap; + public DataWriteHandler(Class clazz) { + notationMap = getNotationMap(clazz); + headColumnMap = getRequiredMap(clazz); + } + @Override public void afterCellDispose(CellWriteHandlerContext context) { + if (CollUtil.isEmpty(notationMap) && CollUtil.isEmpty(headColumnMap)) { + return; + } WriteCellData cellData = context.getFirstCellData(); WriteCellStyle writeCellStyle = cellData.getOrCreateStyle(); @@ -74,4 +85,51 @@ public class DataWriteHandler implements SheetWriteHandler, CellWriteHandler { } } } + + /** + * 获取必填列 + */ + private static Map getRequiredMap(Class clazz) { + Map requiredMap = new HashMap<>(); + Field[] fields = clazz.getDeclaredFields(); + // 检查 fields 数组是否为空 + if (fields.length == 0) { + return requiredMap; + } + Field[] filteredFields = ReflectUtils.getFields(clazz, field -> !"serialVersionUID".equals(field.getName())); + + for (int i = 0; i < filteredFields.length; i++) { + Field field = filteredFields[i]; + if (!field.isAnnotationPresent(ExcelRequired.class)) { + continue; + } + ExcelRequired excelRequired = field.getAnnotation(ExcelRequired.class); + int columnIndex = excelRequired.index() == -1 ? i : excelRequired.index(); + requiredMap.put(columnIndex, excelRequired.fontColor().getIndex()); + } + return requiredMap; + } + + /** + * 获取批注 + */ + private static Map getNotationMap(Class clazz) { + Map notationMap = new HashMap<>(); + Field[] fields = clazz.getDeclaredFields(); + // 检查 fields 数组是否为空 + if (fields.length == 0) { + return notationMap; + } + Field[] filteredFields = ReflectUtils.getFields(clazz, field -> !"serialVersionUID".equals(field.getName())); + for (int i = 0; i < filteredFields.length; i++) { + Field field = filteredFields[i]; + if (!field.isAnnotationPresent(ExcelNotation.class)) { + continue; + } + ExcelNotation excelNotation = field.getAnnotation(ExcelNotation.class); + int columnIndex = excelNotation.index() == -1 ? i : excelNotation.index(); + notationMap.put(columnIndex, excelNotation.value()); + } + return notationMap; + } } diff --git a/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/utils/ExcelUtil.java b/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/utils/ExcelUtil.java index fa1fb902d..856699ae0 100644 --- a/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/utils/ExcelUtil.java +++ b/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/utils/ExcelUtil.java @@ -16,9 +16,6 @@ import lombok.AccessLevel; import lombok.NoArgsConstructor; import org.dromara.common.core.utils.StringUtils; import org.dromara.common.core.utils.file.FileUtils; -import org.dromara.common.core.utils.reflect.ReflectUtils; -import org.dromara.common.excel.annotation.ExcelNotation; -import org.dromara.common.excel.annotation.ExcelRequired; import org.dromara.common.excel.convert.ExcelBigNumberConvert; import org.dromara.common.excel.core.*; import org.dromara.common.excel.handler.DataWriteHandler; @@ -27,9 +24,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.UnsupportedEncodingException; -import java.lang.reflect.Field; import java.util.Collection; -import java.util.HashMap; import java.util.List; import java.util.Map; @@ -197,6 +192,7 @@ public class ExcelUtil { .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) // 大数值自动转换 防止失真 .registerConverter(new ExcelBigNumberConvert()) + .registerWriteHandler(new DataWriteHandler(list.get(0).getClass())) .sheet(sheetName); if (merge) { // 合并处理器 @@ -217,7 +213,7 @@ public class ExcelUtil { * @param data 模板需要的数据 * @param response 响应体 */ - public static void exportTemplate(List data, String filename, String templatePath, HttpServletResponse response) { + public static void exportTemplate(List data, String filename, String templatePath, HttpServletResponse response) { try { resetResponse(filename, response); ServletOutputStream os = response.getOutputStream(); @@ -236,20 +232,21 @@ public class ExcelUtil { * @param data 模板需要的数据 * @param os 输出流 */ - public static void exportTemplate(List data, String templatePath, OutputStream os) { + public static void exportTemplate(List data, String templatePath, OutputStream os) { + if (CollUtil.isEmpty(data)) { + throw new IllegalArgumentException("数据为空"); + } ClassPathResource templateResource = new ClassPathResource(templatePath); ExcelWriter excelWriter = EasyExcel.write(os) .withTemplate(templateResource.getStream()) .autoCloseStream(false) // 大数值自动转换 防止失真 .registerConverter(new ExcelBigNumberConvert()) + .registerWriteHandler(new DataWriteHandler(data.get(0).getClass())) .build(); WriteSheet writeSheet = EasyExcel.writerSheet().build(); - if (CollUtil.isEmpty(data)) { - throw new IllegalArgumentException("数据为空"); - } // 单表多数据导出 模板格式为 {.属性} - for (Object d : data) { + for (T d : data) { excelWriter.fill(d, writeSheet); } excelWriter.finish(); @@ -305,6 +302,9 @@ public class ExcelUtil { * @param os 输出流 */ public static void exportTemplateMultiList(Map data, String templatePath, OutputStream os) { + if (CollUtil.isEmpty(data)) { + throw new IllegalArgumentException("数据为空"); + } ClassPathResource templateResource = new ClassPathResource(templatePath); ExcelWriter excelWriter = EasyExcel.write(os) .withTemplate(templateResource.getStream()) @@ -313,9 +313,6 @@ public class ExcelUtil { .registerConverter(new ExcelBigNumberConvert()) .build(); WriteSheet writeSheet = EasyExcel.writerSheet().build(); - if (CollUtil.isEmpty(data)) { - throw new IllegalArgumentException("数据为空"); - } for (Map.Entry map : data.entrySet()) { // 设置列表后续还有数据 FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build(); @@ -339,6 +336,9 @@ public class ExcelUtil { * @param os 输出流 */ public static void exportTemplateMultiSheet(List> data, String templatePath, OutputStream os) { + if (CollUtil.isEmpty(data)) { + throw new IllegalArgumentException("数据为空"); + } ClassPathResource templateResource = new ClassPathResource(templatePath); ExcelWriter excelWriter = EasyExcel.write(os) .withTemplate(templateResource.getStream()) @@ -346,9 +346,6 @@ public class ExcelUtil { // 大数值自动转换 防止失真 .registerConverter(new ExcelBigNumberConvert()) .build(); - if (CollUtil.isEmpty(data)) { - throw new IllegalArgumentException("数据为空"); - } for (int i = 0; i < data.size(); i++) { WriteSheet writeSheet = EasyExcel.writerSheet(i).build(); for (Map.Entry map : data.get(i).entrySet()) { @@ -439,91 +436,4 @@ public class ExcelUtil { return IdUtil.fastSimpleUUID() + "_" + filename + ".xlsx"; } - /** - * 获取必填列Map - * - * @param clazz 类class - * @return java.util.Map - * @author SunLingDa - * @date 2022/11/3 13:23 - */ - private static Map getRequiredMap(Class clazz) { - Map requiredMap = new HashMap<>(); - Field[] fields = clazz.getDeclaredFields(); - // 检查 fields 数组是否为空 - if (fields.length == 0) { - return requiredMap; - } - Field[] filteredFields = ReflectUtils.getFields(clazz, field -> !"serialVersionUID".equals(field.getName())); - - for (int i = 0; i < filteredFields.length; i++) { - Field field = filteredFields[i]; - if (!field.isAnnotationPresent(ExcelRequired.class)) { - continue; - } - ExcelRequired excelRequired = field.getAnnotation(ExcelRequired.class); - int columnIndex = excelRequired.index() == -1 ? i : excelRequired.index(); - requiredMap.put(columnIndex, excelRequired.fontColor().getIndex()); - } - return requiredMap; - } - - /** - * 获取批注Map - * - * @param clazz 类class - * @return java.util.Map - * @author SunLingDa - * @date 2022/11/3 13:24 - */ - private static Map getNotationMap(Class clazz) { - Map notationMap = new HashMap<>(); - Field[] fields = clazz.getDeclaredFields(); - // 检查 fields 数组是否为空 - if (fields.length == 0) { - return notationMap; - } - Field[] filteredFields = ReflectUtils.getFields(clazz, field -> !"serialVersionUID".equals(field.getName())); - for (int i = 0; i < filteredFields.length; i++) { - Field field = filteredFields[i]; - if (!field.isAnnotationPresent(ExcelNotation.class)) { - continue; - } - ExcelNotation excelNotation = field.getAnnotation(ExcelNotation.class); - int columnIndex = excelNotation.index() == -1 ? i : excelNotation.index(); - notationMap.put(columnIndex, excelNotation.value()); - } - return notationMap; - } - public static void exportExcelRequire(List list, String sheetName, Class clazz,HttpServletResponse response) { - exportExcelTemplate(list,sheetName,clazz,response); - } - /** - * 导出excel模板 - * - * @param list 导出数据集合 - * @param sheetName 工作表的名称 - * @param clazz 实体类 - * @param response 响应体 - */ - public static void exportExcelTemplate(List list, String sheetName, Class clazz, HttpServletResponse response) { - try { - Map requiredMap = getRequiredMap(clazz); - Map notationMap = getNotationMap(clazz); - resetResponse(sheetName, response); - ServletOutputStream os = response.getOutputStream(); - DataWriteHandler writeHandler = new DataWriteHandler(notationMap, requiredMap); - ExcelWriterSheetBuilder builder = EasyExcel.write(os, clazz) - .autoCloseStream(false) - // 自动适配 - .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) - .registerWriteHandler(writeHandler) - // 大数值自动转换 防止失真 - .registerConverter(new ExcelBigNumberConvert()) - .sheet(sheetName); - builder.doWrite(list); - } catch (IOException e) { - throw new RuntimeException("导出Excel异常"); - } - } } diff --git a/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/vo/TestDemoVo.java b/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/vo/TestDemoVo.java index 016c2f7dc..e7ea8075c 100644 --- a/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/vo/TestDemoVo.java +++ b/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/vo/TestDemoVo.java @@ -2,6 +2,8 @@ package org.dromara.demo.domain.vo; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.alibaba.excel.annotation.ExcelProperty; +import org.dromara.common.excel.annotation.ExcelNotation; +import org.dromara.common.excel.annotation.ExcelRequired; import org.dromara.common.translation.annotation.Translation; import org.dromara.common.translation.constant.TransConstant; import org.dromara.demo.domain.TestDemo; @@ -36,30 +38,35 @@ public class TestDemoVo implements Serializable { /** * 部门id */ + @ExcelRequired @ExcelProperty(value = "部门id") private Long deptId; /** * 用户id */ + @ExcelRequired @ExcelProperty(value = "用户id") private Long userId; /** * 排序号 */ + @ExcelRequired @ExcelProperty(value = "排序号") private Integer orderNum; /** * key键 */ + @ExcelNotation(value = "测试key") @ExcelProperty(value = "key键") private String testKey; /** * 值 */ + @ExcelNotation(value = "测试value") @ExcelProperty(value = "值") private String value; From 1a403361c951b91f6e3a33da1d8c0ee77e07bb86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Thu, 19 Dec 2024 09:19:12 +0800 Subject: [PATCH 114/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E5=85=B3?= =?UTF-8?q?=E9=97=ADsse=E5=90=8E=20=E4=BD=BF=E7=94=A8=E5=B7=A5=E5=85=B7?= =?UTF-8?q?=E6=8A=A5=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dromara/common/sse/utils/SseMessageUtils.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/ruoyi-common/ruoyi-common-sse/src/main/java/org/dromara/common/sse/utils/SseMessageUtils.java b/ruoyi-common/ruoyi-common-sse/src/main/java/org/dromara/common/sse/utils/SseMessageUtils.java index c6abdc8fd..ff79a15c2 100644 --- a/ruoyi-common/ruoyi-common-sse/src/main/java/org/dromara/common/sse/utils/SseMessageUtils.java +++ b/ruoyi-common/ruoyi-common-sse/src/main/java/org/dromara/common/sse/utils/SseMessageUtils.java @@ -16,6 +16,7 @@ import org.dromara.common.sse.dto.SseMessageDto; @NoArgsConstructor(access = AccessLevel.PRIVATE) public class SseMessageUtils { + private final static Boolean SSE_ENABLE = SpringUtils.getProperty("sse.enabled", Boolean.class, true); private final static SseEmitterManager MANAGER = SpringUtils.getBean(SseEmitterManager.class); /** @@ -25,6 +26,9 @@ public class SseMessageUtils { * @param message 要发送的消息内容 */ public static void sendMessage(Long userId, String message) { + if (SSE_ENABLE) { + return; + } MANAGER.sendMessage(userId, message); } @@ -34,6 +38,9 @@ public class SseMessageUtils { * @param message 要发送的消息内容 */ public static void sendMessage(String message) { + if (SSE_ENABLE) { + return; + } MANAGER.sendMessage(message); } @@ -43,6 +50,9 @@ public class SseMessageUtils { * @param sseMessageDto 要发布的SSE消息对象 */ public static void publishMessage(SseMessageDto sseMessageDto) { + if (SSE_ENABLE) { + return; + } MANAGER.publishMessage(sseMessageDto); } @@ -52,6 +62,9 @@ public class SseMessageUtils { * @param message 要发布的消息内容 */ public static void publishAll(String message) { + if (SSE_ENABLE) { + return; + } MANAGER.publishAll(message); } From ad85fa201649695919b037b028e53d19932c4a1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Thu, 19 Dec 2024 10:54:08 +0800 Subject: [PATCH 115/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20sse?= =?UTF-8?q?=E5=B7=A5=E5=85=B7=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dromara/common/sse/utils/SseMessageUtils.java | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/ruoyi-common/ruoyi-common-sse/src/main/java/org/dromara/common/sse/utils/SseMessageUtils.java b/ruoyi-common/ruoyi-common-sse/src/main/java/org/dromara/common/sse/utils/SseMessageUtils.java index ff79a15c2..45f354ce7 100644 --- a/ruoyi-common/ruoyi-common-sse/src/main/java/org/dromara/common/sse/utils/SseMessageUtils.java +++ b/ruoyi-common/ruoyi-common-sse/src/main/java/org/dromara/common/sse/utils/SseMessageUtils.java @@ -26,7 +26,7 @@ public class SseMessageUtils { * @param message 要发送的消息内容 */ public static void sendMessage(Long userId, String message) { - if (SSE_ENABLE) { + if (!isEnable()) { return; } MANAGER.sendMessage(userId, message); @@ -38,7 +38,7 @@ public class SseMessageUtils { * @param message 要发送的消息内容 */ public static void sendMessage(String message) { - if (SSE_ENABLE) { + if (!isEnable()) { return; } MANAGER.sendMessage(message); @@ -50,7 +50,7 @@ public class SseMessageUtils { * @param sseMessageDto 要发布的SSE消息对象 */ public static void publishMessage(SseMessageDto sseMessageDto) { - if (SSE_ENABLE) { + if (!isEnable()) { return; } MANAGER.publishMessage(sseMessageDto); @@ -62,10 +62,17 @@ public class SseMessageUtils { * @param message 要发布的消息内容 */ public static void publishAll(String message) { - if (SSE_ENABLE) { + if (!isEnable()) { return; } MANAGER.publishAll(message); } + /** + * 是否开启 + */ + public static Boolean isEnable() { + return SSE_ENABLE; + } + } From f20c27197278ce133f0d605618702f8e629e6678 Mon Sep 17 00:00:00 2001 From: zst_2001 <1493232063@qq.com> Date: Thu, 19 Dec 2024 16:26:26 +0000 Subject: [PATCH 116/175] =?UTF-8?q?!622=20fix=20=E4=BF=AE=E6=AD=A3?= =?UTF-8?q?=E6=B3=A8=E9=87=8A=E9=94=99=E5=88=AB=E5=AD=97=E5=92=8C=E9=A1=BA?= =?UTF-8?q?=E5=BA=8F=20*=20fix=20=E4=BF=AE=E6=AD=A3=E6=B3=A8=E9=87=8A?= =?UTF-8?q?=E9=94=99=E5=88=AB=E5=AD=97=E5=92=8C=E9=A1=BA=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/dromara/common/json/handler/BigNumberSerializer.java | 2 +- .../org/dromara/common/sensitive/core/SensitiveStrategy.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ruoyi-common/ruoyi-common-json/src/main/java/org/dromara/common/json/handler/BigNumberSerializer.java b/ruoyi-common/ruoyi-common-json/src/main/java/org/dromara/common/json/handler/BigNumberSerializer.java index f2a7c2d8c..8752353c5 100644 --- a/ruoyi-common/ruoyi-common-json/src/main/java/org/dromara/common/json/handler/BigNumberSerializer.java +++ b/ruoyi-common/ruoyi-common-json/src/main/java/org/dromara/common/json/handler/BigNumberSerializer.java @@ -32,7 +32,7 @@ public class BigNumberSerializer extends NumberSerializer { @Override public void serialize(Number value, JsonGenerator gen, SerializerProvider provider) throws IOException { - // 超出范围 序列化位字符串 + // 超出范围 序列化为字符串 if (value.longValue() > MIN_SAFE_INTEGER && value.longValue() < MAX_SAFE_INTEGER) { super.serialize(value, gen, provider); } else { diff --git a/ruoyi-common/ruoyi-common-sensitive/src/main/java/org/dromara/common/sensitive/core/SensitiveStrategy.java b/ruoyi-common/ruoyi-common-sensitive/src/main/java/org/dromara/common/sensitive/core/SensitiveStrategy.java index 995dcbd96..7af5cee9e 100644 --- a/ruoyi-common/ruoyi-common-sensitive/src/main/java/org/dromara/common/sensitive/core/SensitiveStrategy.java +++ b/ruoyi-common/ruoyi-common-sensitive/src/main/java/org/dromara/common/sensitive/core/SensitiveStrategy.java @@ -80,12 +80,12 @@ public enum SensitiveStrategy { FIRST_MASK(DesensitizedUtil::firstMask), /** - * 清空为null + * 清空为"" */ CLEAR(s -> DesensitizedUtil.clear()), /** - * 清空为"" + * 清空为null */ CLEAR_TO_NULL(s -> DesensitizedUtil.clearToNull()); From 3a0fbd45ae107e0805dbca4cfa1042892a6c9fc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Sat, 21 Dec 2024 13:30:19 +0800 Subject: [PATCH 117/175] =?UTF-8?q?update=20=E5=A2=9E=E5=8A=A0=20=E8=B5=9E?= =?UTF-8?q?=E5=8A=A9=E5=95=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 5ed7878f1..37ca4c3c3 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,7 @@ MaxKey 业界领先单点登录产品 - https://gitee.com/dromara/MaxKey
CCFlow 驰聘低代码-流程-表单 - https://gitee.com/opencc/RuoYi-JFlow
数舵科技 软件定制开发APP小程序等 - http://www.shuduokeji.com/
引迈信息 软件开发平台 - https://www.jnpfsoft.com/index.html?from=plus-doc
+启山商城系统 多租户商城源码可免费商用可二次开发 - https://www.73app.cn/
[如何成为赞助商 加群联系作者详谈](https://plus-doc.dromara.org/#/common/add_group) # 本框架与RuoYi的功能差异 From f4f052deb49afe0fed71af3e92cdbefeaae81c19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Sat, 21 Dec 2024 13:32:19 +0800 Subject: [PATCH 118/175] =?UTF-8?q?update=20=E5=A2=9E=E5=8A=A0=20=E8=B5=9E?= =?UTF-8?q?=E5=8A=A9=E5=95=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 37ca4c3c3..42a76367e 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ MaxKey 业界领先单点登录产品 - https://gitee.com/dromara/MaxKey
CCFlow 驰聘低代码-流程-表单 - https://gitee.com/opencc/RuoYi-JFlow
数舵科技 软件定制开发APP小程序等 - http://www.shuduokeji.com/
引迈信息 软件开发平台 - https://www.jnpfsoft.com/index.html?from=plus-doc
-启山商城系统 多租户商城源码可免费商用可二次开发 - https://www.73app.cn/
+启山商城系统 多租户商城源码可免费商用可二次开发 - https://www.73app.cn/
[如何成为赞助商 加群联系作者详谈](https://plus-doc.dromara.org/#/common/add_group) # 本框架与RuoYi的功能差异 From 36de389fa48c9ce5a2b916c740d7e143c42a40f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Sat, 21 Dec 2024 13:38:24 +0800 Subject: [PATCH 119/175] =?UTF-8?q?update=20=E5=A2=9E=E5=8A=A0=20=E8=B5=9E?= =?UTF-8?q?=E5=8A=A9=E5=95=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 42a76367e..7a8864116 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ MaxKey 业界领先单点登录产品 - https://gitee.com/dromara/MaxKey
CCFlow 驰聘低代码-流程-表单 - https://gitee.com/opencc/RuoYi-JFlow
数舵科技 软件定制开发APP小程序等 - http://www.shuduokeji.com/
引迈信息 软件开发平台 - https://www.jnpfsoft.com/index.html?from=plus-doc
-启山商城系统 多租户商城源码可免费商用可二次开发 - https://www.73app.cn/
+**启山商城系统 多租户商城源码可免费商用可二次开发 - https://www.73app.cn/**
[如何成为赞助商 加群联系作者详谈](https://plus-doc.dromara.org/#/common/add_group) # 本框架与RuoYi的功能差异 From 251a617ecc57276bde7da7440cf954bb2adb53fb Mon Sep 17 00:00:00 2001 From: QianRj <14974713+qianrj@user.noreply.gitee.com> Date: Tue, 24 Dec 2024 03:04:27 +0000 Subject: [PATCH 120/175] =?UTF-8?q?!626=20fix=20=E4=BF=AE=E5=A4=8Dexcel?= =?UTF-8?q?=E6=A8=A1=E6=9D=BF=E5=AF=BC=E5=87=BA=E5=BC=82=E5=B8=B8=20*=20fi?= =?UTF-8?q?x:=20=E4=BF=AE=E5=A4=8Dexcel=E6=A8=A1=E6=9D=BF=E5=AF=BC?= =?UTF-8?q?=E5=87=BA=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/org/dromara/common/excel/utils/ExcelUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/utils/ExcelUtil.java b/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/utils/ExcelUtil.java index 856699ae0..b22e6f987 100644 --- a/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/utils/ExcelUtil.java +++ b/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/utils/ExcelUtil.java @@ -192,7 +192,7 @@ public class ExcelUtil { .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) // 大数值自动转换 防止失真 .registerConverter(new ExcelBigNumberConvert()) - .registerWriteHandler(new DataWriteHandler(list.get(0).getClass())) + .registerWriteHandler(new DataWriteHandler(clazz)) .sheet(sheetName); if (merge) { // 合并处理器 From 5480e419b6fb47e239ab28240252bb7f4a101e2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Wed, 25 Dec 2024 09:23:08 +0800 Subject: [PATCH 121/175] update sqlkeyword --- .../main/java/org/dromara/common/core/utils/sql/SqlUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/sql/SqlUtil.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/sql/SqlUtil.java index fcf9fb4b6..1020c81eb 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/sql/SqlUtil.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/sql/SqlUtil.java @@ -15,7 +15,7 @@ public class SqlUtil { /** * 定义常用的 sql关键字 */ - public static String SQL_REGEX = "and |extractvalue|updatexml|sleep|exec |insert |select |delete |update |drop |count |chr |mid |master |truncate |char |declare |or |union |like |+|/*|user()"; + public static String SQL_REGEX = "\u000B|and |extractvalue|updatexml|sleep|exec |insert |select |delete |update |drop |count |chr |mid |master |truncate |char |declare |or |union |like |+|/*|user()"; /** * 仅支持字母、数字、下划线、空格、逗号、小数点(支持多个字段排序) From 492e7dab26b9efff7a68962f1dfffd5fa583c464 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Wed, 25 Dec 2024 09:30:14 +0800 Subject: [PATCH 122/175] =?UTF-8?q?fix=20=E4=BF=AE=E5=A4=8D=20=E6=9C=AA?= =?UTF-8?q?=E5=BC=80=E5=90=AFsse=20=E6=89=BE=E4=B8=8D=E5=88=B0bean?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/dromara/common/sse/utils/SseMessageUtils.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/ruoyi-common/ruoyi-common-sse/src/main/java/org/dromara/common/sse/utils/SseMessageUtils.java b/ruoyi-common/ruoyi-common-sse/src/main/java/org/dromara/common/sse/utils/SseMessageUtils.java index 45f354ce7..586103417 100644 --- a/ruoyi-common/ruoyi-common-sse/src/main/java/org/dromara/common/sse/utils/SseMessageUtils.java +++ b/ruoyi-common/ruoyi-common-sse/src/main/java/org/dromara/common/sse/utils/SseMessageUtils.java @@ -17,7 +17,13 @@ import org.dromara.common.sse.dto.SseMessageDto; public class SseMessageUtils { private final static Boolean SSE_ENABLE = SpringUtils.getProperty("sse.enabled", Boolean.class, true); - private final static SseEmitterManager MANAGER = SpringUtils.getBean(SseEmitterManager.class); + private static SseEmitterManager MANAGER; + + static { + if (isEnable() && MANAGER == null) { + MANAGER = SpringUtils.getBean(SseEmitterManager.class); + } + } /** * 向指定的WebSocket会话发送消息 From c2746c23923b7f28219f670a8cd13ac70cd17668 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Thu, 26 Dec 2024 13:26:18 +0800 Subject: [PATCH 123/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E6=9D=83=E9=99=90=E5=A4=84=E7=90=86=E5=99=A8=20?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E9=BB=98=E8=AE=A4=E5=80=BC=E5=A4=84=E7=90=86?= =?UTF-8?q?=20=E9=92=88=E5=AF=B9=E4=BA=8E=E8=A1=A8=E8=BE=BE=E5=BC=8F?= =?UTF-8?q?=E5=8F=98=E9=87=8F=E4=B8=8E=E6=B3=A8=E8=A7=A3=E4=B8=8D=E5=AF=B9?= =?UTF-8?q?=E5=BA=94=E6=88=96=E8=80=85=E8=A1=A8=E8=BE=BE=E5=BC=8F=E5=8F=98?= =?UTF-8?q?=E9=87=8F=E4=B8=BAnull=E7=9A=84=E6=83=85=E5=86=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../handler/PlusDataPermissionHandler.java | 69 +++++++++++++++++-- 1 file changed, 65 insertions(+), 4 deletions(-) diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/PlusDataPermissionHandler.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/PlusDataPermissionHandler.java index c529c5332..783d3526e 100644 --- a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/PlusDataPermissionHandler.java +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/PlusDataPermissionHandler.java @@ -3,6 +3,7 @@ package org.dromara.common.mybatis.handler; import cn.hutool.core.annotation.AnnotationUtil; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; +import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import net.sf.jsqlparser.JSQLParserException; import net.sf.jsqlparser.expression.Expression; @@ -28,9 +29,7 @@ import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.core.io.support.ResourcePatternResolver; import org.springframework.core.type.ClassMetadata; import org.springframework.core.type.classreading.CachingMetadataReaderFactory; -import org.springframework.expression.BeanResolver; -import org.springframework.expression.ExpressionParser; -import org.springframework.expression.ParserContext; +import org.springframework.expression.*; import org.springframework.expression.common.TemplateParserContext; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.expression.spel.support.StandardEvaluationContext; @@ -130,7 +129,9 @@ public class PlusDataPermissionHandler { joinStr = " " + dataPermission.joinStr() + " "; } LoginUser user = DataPermissionHelper.getVariable("user"); - StandardEvaluationContext context = new StandardEvaluationContext(); + Object defaultValue = "-1"; + NullSafeStandardEvaluationContext context = new NullSafeStandardEvaluationContext(defaultValue); + context.addPropertyAccessor(new NullSafePropertyAccessor(context.getPropertyAccessors().get(0), defaultValue)); context.setBeanResolver(beanResolver); DataPermissionHelper.getContext().forEach(context::setVariable); Set conditions = new HashSet<>(); @@ -257,4 +258,64 @@ public class PlusDataPermissionHandler { return getDataPermission(mapperId) == null; } + /** + * 对所有null变量找不到的变量返回默认值 + */ + @AllArgsConstructor + private static class NullSafeStandardEvaluationContext extends StandardEvaluationContext { + + private final Object defaultValue; + + @Override + public Object lookupVariable(String name) { + Object obj = super.lookupVariable(name); + // 如果读取到的值是 null,则返回默认值 + if (obj == null) { + return defaultValue; + } + return obj; + } + + } + + /** + * 对所有null变量找不到的变量返回默认值 委托模式 将不需要处理的方法委托给原处理器 + */ + @AllArgsConstructor + private static class NullSafePropertyAccessor implements PropertyAccessor { + + private final PropertyAccessor delegate; + private final Object defaultValue; + + @Override + public Class[] getSpecificTargetClasses() { + return delegate.getSpecificTargetClasses(); + } + + @Override + public boolean canRead(EvaluationContext context, Object target, String name) throws AccessException { + return delegate.canRead(context, target, name); + } + + @Override + public TypedValue read(EvaluationContext context, Object target, String name) throws AccessException { + TypedValue value = delegate.read(context, target, name); + // 如果读取到的值是 null,则返回默认值 + if (value.getValue() == null) { + return new TypedValue(defaultValue); + } + return value; + } + + @Override + public boolean canWrite(EvaluationContext context, Object target, String name) throws AccessException { + return delegate.canWrite(context, target, name); + } + + @Override + public void write(EvaluationContext context, Object target, String name, Object newValue) throws AccessException { + delegate.write(context, target, name, newValue); + } + } + } From a7b83672ba4241ad3a16e81b155266f888a396ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Fri, 27 Dec 2024 11:17:09 +0800 Subject: [PATCH 124/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20sse=20?= =?UTF-8?q?=E5=A6=82=E6=9E=9C=E8=8E=B7=E5=8F=96token=E5=88=97=E8=A1=A8?= =?UTF-8?q?=E4=B8=BA=E7=A9=BA=20=E5=88=A0=E9=99=A4userid=E5=AF=B9=E5=BA=94?= =?UTF-8?q?=E7=9A=84=E5=AD=98=E5=82=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/dromara/common/sse/core/SseEmitterManager.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/ruoyi-common/ruoyi-common-sse/src/main/java/org/dromara/common/sse/core/SseEmitterManager.java b/ruoyi-common/ruoyi-common-sse/src/main/java/org/dromara/common/sse/core/SseEmitterManager.java index c26adca50..ba1ce5696 100644 --- a/ruoyi-common/ruoyi-common-sse/src/main/java/org/dromara/common/sse/core/SseEmitterManager.java +++ b/ruoyi-common/ruoyi-common-sse/src/main/java/org/dromara/common/sse/core/SseEmitterManager.java @@ -1,5 +1,6 @@ package org.dromara.common.sse.core; +import cn.hutool.core.map.MapUtil; import lombok.extern.slf4j.Slf4j; import org.dromara.common.redis.utils.RedisUtils; import org.dromara.common.sse.dto.SseMessageDto; @@ -65,7 +66,7 @@ public class SseEmitterManager { */ public void disconnect(Long userId, String token) { Map emitters = USER_TOKEN_EMITTERS.get(userId); - if (emitters != null) { + if (MapUtil.isNotEmpty(emitters)) { try { SseEmitter sseEmitter = emitters.get(token); sseEmitter.send(SseEmitter.event().comment("disconnected")); @@ -73,6 +74,8 @@ public class SseEmitterManager { } catch (Exception ignore) { } emitters.remove(token); + } else { + USER_TOKEN_EMITTERS.remove(userId); } } @@ -93,7 +96,7 @@ public class SseEmitterManager { */ public void sendMessage(Long userId, String message) { Map emitters = USER_TOKEN_EMITTERS.get(userId); - if (emitters != null) { + if (MapUtil.isNotEmpty(emitters)) { for (Map.Entry entry : emitters.entrySet()) { try { entry.getValue().send(SseEmitter.event() @@ -103,6 +106,8 @@ public class SseEmitterManager { emitters.remove(entry.getKey()); } } + } else { + USER_TOKEN_EMITTERS.remove(userId); } } From 41a3bdf73dc7fdbbbe69a9b943ff6f8552a463e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A7=8B=E8=BE=9E=E6=9C=AA=E5=AF=92?= <545073804@qq.com> Date: Thu, 2 Jan 2025 07:34:40 +0000 Subject: [PATCH 125/175] =?UTF-8?q?!629=20update=20=E4=BC=98=E5=8C=96jdk21?= =?UTF-8?q?=E7=8E=AF=E5=A2=83=E5=BC=80=E5=90=AF=E8=99=9A=E6=8B=9F=E7=BA=BF?= =?UTF-8?q?=E7=A8=8B=E6=97=B6=E7=9A=84=E5=AE=9A=E6=97=B6=E4=BB=BB=E5=8A=A1?= =?UTF-8?q?=E6=B1=A0=20*=20update=20=E4=BC=98=E5=8C=96jdk21=E7=8E=AF?= =?UTF-8?q?=E5=A2=83=E5=BC=80=E5=90=AF=E8=99=9A=E6=8B=9F=E7=BA=BF=E7=A8=8B?= =?UTF-8?q?=E6=97=B6=E7=9A=84=E5=AE=9A=E6=97=B6=E4=BB=BB=E5=8A=A1=E6=B1=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/core/config/ThreadPoolConfig.java | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/config/ThreadPoolConfig.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/config/ThreadPoolConfig.java index b4d452817..7040330be 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/config/ThreadPoolConfig.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/config/ThreadPoolConfig.java @@ -4,6 +4,7 @@ import jakarta.annotation.PreDestroy; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.concurrent.BasicThreadFactory; import org.dromara.common.core.config.properties.ThreadPoolProperties; +import org.dromara.common.core.utils.SpringUtils; import org.dromara.common.core.utils.Threads; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @@ -13,6 +14,7 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; /** @@ -49,8 +51,23 @@ public class ThreadPoolConfig { */ @Bean(name = "scheduledExecutorService") protected ScheduledExecutorService scheduledExecutorService() { + ThreadFactory threadFactory; + // 是否启用虚拟线程 + if (SpringUtils.isVirtual()) { + // 虚拟线程必须为守护线程,即 daemon 只能是 true + threadFactory = new BasicThreadFactory.Builder() + .daemon(true) + .namingPattern("virtual-schedule-pool-%d") + .wrappedFactory(Thread.ofVirtual().factory()) + .build(); + } else { + threadFactory = new BasicThreadFactory.Builder() + .daemon(true) + .namingPattern("schedule-pool-%d") + .build(); + } ScheduledThreadPoolExecutor scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(core, - new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build(), + threadFactory, new ThreadPoolExecutor.CallerRunsPolicy()) { @Override protected void afterExecute(Runnable r, Throwable t) { From a46c798e017a0f6ce0ded81b6970bc9084d11957 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Thu, 2 Jan 2025 15:42:24 +0800 Subject: [PATCH 126/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E5=BB=B6?= =?UTF-8?q?=E8=BF=9F=E7=BA=BF=E7=A8=8B=E6=B1=A0=20=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E8=99=9A=E6=8B=9F=E7=BA=BF=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/core/config/ThreadPoolConfig.java | 20 ++++++------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/config/ThreadPoolConfig.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/config/ThreadPoolConfig.java index 7040330be..2630485a4 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/config/ThreadPoolConfig.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/config/ThreadPoolConfig.java @@ -10,11 +10,11 @@ import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; +import org.springframework.core.task.VirtualThreadTaskExecutor; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledThreadPoolExecutor; -import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; /** @@ -51,23 +51,15 @@ public class ThreadPoolConfig { */ @Bean(name = "scheduledExecutorService") protected ScheduledExecutorService scheduledExecutorService() { - ThreadFactory threadFactory; - // 是否启用虚拟线程 + // daemon 必须为 true + BasicThreadFactory.Builder builder = new BasicThreadFactory.Builder().daemon(true); if (SpringUtils.isVirtual()) { - // 虚拟线程必须为守护线程,即 daemon 只能是 true - threadFactory = new BasicThreadFactory.Builder() - .daemon(true) - .namingPattern("virtual-schedule-pool-%d") - .wrappedFactory(Thread.ofVirtual().factory()) - .build(); + builder.namingPattern("virtual-schedule-pool-%d").wrappedFactory(new VirtualThreadTaskExecutor().getVirtualThreadFactory()); } else { - threadFactory = new BasicThreadFactory.Builder() - .daemon(true) - .namingPattern("schedule-pool-%d") - .build(); + builder.namingPattern("schedule-pool-%d"); } ScheduledThreadPoolExecutor scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(core, - threadFactory, + builder.build(), new ThreadPoolExecutor.CallerRunsPolicy()) { @Override protected void afterExecute(Runnable r, Throwable t) { From ec5ca0a08faaf6e69f83d292b3ec909294a7dc39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A7=8B=E8=BE=9E=E6=9C=AA=E5=AF=92?= <545073804@qq.com> Date: Fri, 3 Jan 2025 01:44:39 +0000 Subject: [PATCH 127/175] =?UTF-8?q?fix=20=E4=BF=AE=E5=A4=8D=20redisson?= =?UTF-8?q?=E5=8F=91=E5=8F=B7=E5=99=A8=E6=9C=AA=E5=88=9D=E5=A7=8B=E5=8C=96?= =?UTF-8?q?=E5=8F=91=E5=8F=B7=E5=99=A8=E6=AD=A5=E9=95=BF=E5=AF=BC=E8=87=B4?= =?UTF-8?q?=E8=BF=87=E6=9C=9F=E6=97=B6=E9=97=B4=E6=9C=AA=E7=94=9F=E6=95=88?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 秋辞未寒 <545073804@qq.com> --- .../java/org/dromara/common/redis/utils/SequenceUtils.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/SequenceUtils.java b/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/SequenceUtils.java index 3c2f70329..e28c84e89 100644 --- a/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/SequenceUtils.java +++ b/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/SequenceUtils.java @@ -59,10 +59,10 @@ public class SequenceUtils { stepValue = DEFAULT_STEP_VALUE; } RIdGenerator idGenerator = REDISSON_CLIENT.getIdGenerator(key); - // 设置过期时间 - idGenerator.expire(expireTime); // 设置初始值和步长 idGenerator.tryInit(initValue, stepValue); + // 设置过期时间 + idGenerator.expire(expireTime); return idGenerator; } From d023510f7e4dc71de2f5c0832409471f9cf087d4 Mon Sep 17 00:00:00 2001 From: dhb52 Date: Fri, 3 Jan 2025 07:13:22 +0000 Subject: [PATCH 128/175] !632 update snailjob 1.2.0 => 1.3.0-beta1 * update snailjob 1.2.0 => 1.3.0-beta1 --- README.md | 4 +- pom.xml | 2 +- .../src/main/resources/application-dev.yml | 6 ++- .../src/main/resources/application-prod.yml | 6 ++- .../src/main/resources/application-dev.yml | 7 ++- .../src/main/resources/application-prod.yml | 7 ++- script/sql/oracle/oracle_ry_job.sql | 18 +++++--- script/sql/postgres/postgres_ry_job.sql | 18 +++++--- script/sql/ry_job.sql | 10 +++-- script/sql/sqlserver/sqlserver_ry_job.sql | 45 ++++++++++++++++--- 10 files changed, 92 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index 7a8864116..96708e355 100644 --- a/README.md +++ b/README.md @@ -169,8 +169,8 @@ CCFlow 驰聘低代码-流程-表单 - https://gitee.com/opencc/RuoYi-JFlow
| ![输入图片说明](https://foruda.gitee.com/images/1680078779416197879/75e3ed02_1766278.png "屏幕截图") | ![输入图片说明](https://foruda.gitee.com/images/1680078802329118061/77e10915_1766278.png "屏幕截图") | | ![输入图片说明](https://foruda.gitee.com/images/1680078893627848351/34a1c342_1766278.png "屏幕截图") | ![输入图片说明](https://foruda.gitee.com/images/1680078928175016986/f126ec4a_1766278.png "屏幕截图") | | ![输入图片说明](https://foruda.gitee.com/images/1680078941718318363/b68a0f72_1766278.png "屏幕截图") | ![输入图片说明](https://foruda.gitee.com/images/1680078963175518631/3bb769a1_1766278.png "屏幕截图") | -| ![输入图片说明](https://foruda.gitee.com/images/1680078982294090567/b31c343d_1766278.png "屏幕截图") | ![输入图片说明](https://foruda.gitee.com/images/1680079000642440444/77ca82a9_1766278.png "屏幕截图") | -| ![输入图片说明](https://foruda.gitee.com/images/1680079020995074177/03b7d52e_1766278.png "屏幕截图") | ![输入图片说明](https://foruda.gitee.com/images/1680079039367822173/76811806_1766278.png "屏幕截图") | +| ![输入图片说明](https://foruda.gitee.com/images/1735829153637063344/3c21fd4c_1419627.png "屏幕截图") | ![输入图片说明](https://foruda.gitee.com/images/1735829181303499815/4522cefa_1419627.png "屏幕截图") | +| ![输入图片说明](https://foruda.gitee.com/images/1735829377205259767/76a705d7_1419627.png "屏幕截图") | ![输入图片说明](https://foruda.gitee.com/images/1722959592856812900/e2d0d342_1419627.png "屏幕截图") | | ![输入图片说明](https://foruda.gitee.com/images/1680079274333484664/4dfdc7c0_1766278.png "屏幕截图") | ![输入图片说明](https://foruda.gitee.com/images/1680079290467458224/d6715fcf_1766278.png "屏幕截图") | diff --git a/pom.xml b/pom.xml index ebf2814ed..63b9d0226 100644 --- a/pom.xml +++ b/pom.xml @@ -31,7 +31,7 @@ 3.39.0 2.2.7 4.3.1 - 1.2.0 + 1.3.0-beta1 1.4.5 0.2.0 1.18.34 diff --git a/ruoyi-admin/src/main/resources/application-dev.yml b/ruoyi-admin/src/main/resources/application-dev.yml index e4f6086cc..685708316 100644 --- a/ruoyi-admin/src/main/resources/application-dev.yml +++ b/ruoyi-admin/src/main/resources/application-dev.yml @@ -16,17 +16,19 @@ snail-job: enabled: true # 需要在 SnailJob 后台组管理创建对应名称的组,然后创建任务的时候选择对应的组,才能正确分派任务 group: "ruoyi_group" - # SnailJob 接入验证令牌 详见 script/sql/snail_job.sql `sj_group_config` 表 + # SnailJob 接入验证令牌 详见 script/sql/ry_job.sql `sj_group_config` 表 token: "SJ_cKqBTPzCsWA3VyuCfFoccmuIEGXjr5KT" server: host: 127.0.0.1 port: 17888 - # 详见 script/sql/snail_job.sql `sj_namespace` 表 + # 命名空间UUID 详见 script/sql/ry_job.sql `sj_namespace`表`unique_id`字段 namespace: ${spring.profiles.active} # 随主应用端口飘逸 port: 2${server.port} # 客户端ip指定 host: + # RPC类型: netty, grpc + rpc-type: grpc --- # 数据源配置 spring: diff --git a/ruoyi-admin/src/main/resources/application-prod.yml b/ruoyi-admin/src/main/resources/application-prod.yml index 2002e9eee..a8c54bcb6 100644 --- a/ruoyi-admin/src/main/resources/application-prod.yml +++ b/ruoyi-admin/src/main/resources/application-prod.yml @@ -19,17 +19,19 @@ snail-job: enabled: true # 需要在 SnailJob 后台组管理创建对应名称的组,然后创建任务的时候选择对应的组,才能正确分派任务 group: "ruoyi_group" - # SnailJob 接入验证令牌 详见 script/sql/snail_job.sql `sj_group_config` 表 + # SnailJob 接入验证令牌 详见 script/sql/ry_job.sql `sj_group_config`表 token: "SJ_cKqBTPzCsWA3VyuCfFoccmuIEGXjr5KT" server: host: 127.0.0.1 port: 17888 - # 详见 script/sql/snail_job.sql `sj_namespace` 表 + # 命名空间UUID 详见 script/sql/ry_job.sql `sj_namespace`表`unique_id`字段 namespace: ${spring.profiles.active} # 随主应用端口飘逸 port: 2${server.port} # 客户端ip指定 host: + # RPC类型: netty, grpc + rpc-type: grpc --- # 数据源配置 spring: diff --git a/ruoyi-extend/ruoyi-snailjob-server/src/main/resources/application-dev.yml b/ruoyi-extend/ruoyi-snailjob-server/src/main/resources/application-dev.yml index 579f376db..44f298aba 100644 --- a/ruoyi-extend/ruoyi-snailjob-server/src/main/resources/application-dev.yml +++ b/ruoyi-extend/ruoyi-snailjob-server/src/main/resources/application-dev.yml @@ -20,8 +20,8 @@ snail-job: retry-pull-page-size: 1000 # 拉取重试数据的每批次的大小 job-pull-page-size: 1000 - # 服务端netty端口 - netty-port: 17888 + # 服务器端口 + server-port: 17888 # 一个客户端每秒最多接收的重试数量指令 limiter: 1000 # 号段模式下步长配置 @@ -34,7 +34,10 @@ snail-job: max-count: 288 #间隔时间 trigger-interval: 900 + # 重试每次拉取的次数 retry-max-pull-count: 10 + # RPC通讯类型: netty,grpc + rpc-type: grpc --- # 监控中心配置 spring.boot.admin.client: diff --git a/ruoyi-extend/ruoyi-snailjob-server/src/main/resources/application-prod.yml b/ruoyi-extend/ruoyi-snailjob-server/src/main/resources/application-prod.yml index dffe05777..44f298aba 100644 --- a/ruoyi-extend/ruoyi-snailjob-server/src/main/resources/application-prod.yml +++ b/ruoyi-extend/ruoyi-snailjob-server/src/main/resources/application-prod.yml @@ -20,8 +20,8 @@ snail-job: retry-pull-page-size: 1000 # 拉取重试数据的每批次的大小 job-pull-page-size: 1000 - # 服务端 netty 端口 - netty-port: 17888 + # 服务器端口 + server-port: 17888 # 一个客户端每秒最多接收的重试数量指令 limiter: 1000 # 号段模式下步长配置 @@ -34,7 +34,10 @@ snail-job: max-count: 288 #间隔时间 trigger-interval: 900 + # 重试每次拉取的次数 retry-max-pull-count: 10 + # RPC通讯类型: netty,grpc + rpc-type: grpc --- # 监控中心配置 spring.boot.admin.client: diff --git a/script/sql/oracle/oracle_ry_job.sql b/script/sql/oracle/oracle_ry_job.sql index da65dbbf6..c2dbbfa52 100644 --- a/script/sql/oracle/oracle_ry_job.sql +++ b/script/sql/oracle/oracle_ry_job.sql @@ -2,7 +2,7 @@ SnailJob Database Transfer Tool Source Server Type : MySQL Target Server Type : Oracle - Date: 2024-07-06 12:49:36 + Date: 2024-12-27 22:22:15 */ @@ -82,7 +82,7 @@ CREATE TABLE sj_notify_config id number GENERATED ALWAYS AS IDENTITY, namespace_id varchar2(64) DEFAULT '764d604ec6fc45f68cd92514c40e9e1a' NULL, group_name varchar2(64) NULL, - business_id varchar2(64) NULL, + notify_name varchar2(64) DEFAULT '' NULL, system_task_type smallint DEFAULT 3 NOT NULL, notify_status smallint DEFAULT 0 NOT NULL, recipient_ids varchar2(128) NULL, @@ -98,12 +98,12 @@ CREATE TABLE sj_notify_config ALTER TABLE sj_notify_config ADD CONSTRAINT pk_sj_notify_config PRIMARY KEY (id); -CREATE INDEX idx_sj_notify_config_01 ON sj_notify_config (namespace_id, group_name, business_id); +CREATE INDEX idx_sj_notify_config_01 ON sj_notify_config (namespace_id, group_name); COMMENT ON COLUMN sj_notify_config.id IS '主键'; COMMENT ON COLUMN sj_notify_config.namespace_id IS '命名空间id'; COMMENT ON COLUMN sj_notify_config.group_name IS '组名称'; -COMMENT ON COLUMN sj_notify_config.business_id IS '业务id ( job_id或workflow_id或scene_name ) '; +COMMENT ON COLUMN sj_notify_config.notify_name IS '通知名称'; COMMENT ON COLUMN sj_notify_config.system_task_type IS '任务类型 1. 重试任务 2. 重试回调 3、JOB任务 4、WORKFLOW任务'; COMMENT ON COLUMN sj_notify_config.notify_status IS '通知状态 0、未启用 1、启用'; COMMENT ON COLUMN sj_notify_config.recipient_ids IS '接收人id列表'; @@ -321,6 +321,7 @@ CREATE TABLE sj_retry_scene_config max_retry_count number DEFAULT 5 NOT NULL, back_off smallint DEFAULT 1 NOT NULL, trigger_interval varchar2(16) DEFAULT '' NULL, + notify_ids varchar2(128) DEFAULT '' NULL, deadline_request number DEFAULT 60000 NOT NULL, executor_timeout number DEFAULT 5 NOT NULL, route_key smallint DEFAULT 4 NOT NULL, @@ -342,6 +343,7 @@ COMMENT ON COLUMN sj_retry_scene_config.scene_status IS '组状态 0、未启用 COMMENT ON COLUMN sj_retry_scene_config.max_retry_count IS '最大重试次数'; COMMENT ON COLUMN sj_retry_scene_config.back_off IS '1、默认等级 2、固定间隔时间 3、CRON 表达式'; COMMENT ON COLUMN sj_retry_scene_config.trigger_interval IS '间隔时长'; +COMMENT ON COLUMN sj_retry_scene_config.notify_ids IS '通知告警场景配置id列表'; COMMENT ON COLUMN sj_retry_scene_config.deadline_request IS 'Deadline Request 调用链超时 单位毫秒'; COMMENT ON COLUMN sj_retry_scene_config.executor_timeout IS '任务执行超时时间,单位秒'; COMMENT ON COLUMN sj_retry_scene_config.route_key IS '路由策略'; @@ -506,6 +508,8 @@ CREATE TABLE sj_job retry_interval number DEFAULT 0 NOT NULL, bucket_index number DEFAULT 0 NOT NULL, resident smallint DEFAULT 0 NOT NULL, + notify_ids varchar2(128) DEFAULT '' NULL, + owner_id number NULL, description varchar2(256) DEFAULT '' NULL, ext_attrs varchar2(256) DEFAULT '' NULL, deleted smallint DEFAULT 0 NOT NULL, @@ -541,6 +545,8 @@ COMMENT ON COLUMN sj_job.parallel_num IS '并行数'; COMMENT ON COLUMN sj_job.retry_interval IS '重试间隔 ( s ) '; COMMENT ON COLUMN sj_job.bucket_index IS 'bucket'; COMMENT ON COLUMN sj_job.resident IS '是否是常驻任务'; +COMMENT ON COLUMN sj_job.notify_ids IS '通知告警场景配置id列表'; +COMMENT ON COLUMN sj_job.owner_id IS '负责人id'; COMMENT ON COLUMN sj_job.description IS '描述'; COMMENT ON COLUMN sj_job.ext_attrs IS '扩展字段'; COMMENT ON COLUMN sj_job.deleted IS '逻辑删除 1、删除'; @@ -548,7 +554,7 @@ COMMENT ON COLUMN sj_job.create_dt IS '创建时间'; COMMENT ON COLUMN sj_job.update_dt IS '修改时间'; COMMENT ON TABLE sj_job IS '任务信息'; -INSERT INTO sj_job(namespace_id, group_name, job_name, args_str, args_type, next_trigger_at, job_status, task_type, route_key, executor_type, executor_info, trigger_type, trigger_interval, block_strategy,executor_timeout, max_retry_times, parallel_num, retry_interval, bucket_index, resident, description, ext_attrs, deleted, create_dt, update_dt) VALUES ('dev', 'ruoyi_group', 'demo-job', NULL, 1, 1710344035622, 1, 1, 4, 1, 'testJobExecutor', 2, '60', 1, 60, 3, 1, 1, 116, 0, '', '', 0, sysdate, sysdate); +INSERT INTO sj_job(namespace_id, group_name, job_name, args_str, args_type, next_trigger_at, job_status, task_type, route_key, executor_type, executor_info, trigger_type, trigger_interval, block_strategy,executor_timeout, max_retry_times, parallel_num, retry_interval, bucket_index, resident, notify_ids, owner_id, description, ext_attrs, deleted, create_dt, update_dt) VALUES ('dev', 'ruoyi_group', 'demo-job', NULL, 1, 1710344035622, 1, 1, 4, 1, 'testJobExecutor', 2, '60', 1, 60, 3, 1, 1, 116, 0, '', 1,'', '', 0, sysdate, sysdate); -- sj_job_log_message CREATE TABLE sj_job_log_message @@ -781,6 +787,7 @@ CREATE TABLE sj_workflow description varchar2(256) DEFAULT '' NULL, flow_info clob DEFAULT NULL NULL, wf_context clob DEFAULT NULL NULL, + notify_ids varchar2(128) DEFAULT '' NULL, bucket_index number DEFAULT 0 NOT NULL, version number NOT NULL, ext_attrs varchar2(256) DEFAULT '' NULL, @@ -808,6 +815,7 @@ COMMENT ON COLUMN sj_workflow.executor_timeout IS '任务执行超时时间, COMMENT ON COLUMN sj_workflow.description IS '描述'; COMMENT ON COLUMN sj_workflow.flow_info IS '流程信息'; COMMENT ON COLUMN sj_workflow.wf_context IS '上下文'; +COMMENT ON COLUMN sj_workflow.notify_ids IS '通知告警场景配置id列表'; COMMENT ON COLUMN sj_workflow.bucket_index IS 'bucket'; COMMENT ON COLUMN sj_workflow.version IS '版本号'; COMMENT ON COLUMN sj_workflow.ext_attrs IS '扩展字段'; diff --git a/script/sql/postgres/postgres_ry_job.sql b/script/sql/postgres/postgres_ry_job.sql index 546db3cc8..1a08a9990 100644 --- a/script/sql/postgres/postgres_ry_job.sql +++ b/script/sql/postgres/postgres_ry_job.sql @@ -2,7 +2,7 @@ SnailJob Database Transfer Tool Source Server Type : MySQL Target Server Type : PostgreSQL - Date: 2024-07-06 11:45:40 + Date: 2024-12-27 22:13:49 */ @@ -76,7 +76,7 @@ CREATE TABLE sj_notify_config id bigserial PRIMARY KEY, namespace_id varchar(64) NOT NULL DEFAULT '764d604ec6fc45f68cd92514c40e9e1a', group_name varchar(64) NOT NULL, - business_id varchar(64) NOT NULL, + notify_name varchar(64) NOT NULL DEFAULT '', system_task_type smallint NOT NULL DEFAULT 3, notify_status smallint NOT NULL DEFAULT 0, recipient_ids varchar(128) NOT NULL, @@ -89,12 +89,12 @@ CREATE TABLE sj_notify_config update_dt timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ); -CREATE INDEX idx_sj_notify_config_01 ON sj_notify_config (namespace_id, group_name, business_id); +CREATE INDEX idx_sj_notify_config_01 ON sj_notify_config (namespace_id, group_name); COMMENT ON COLUMN sj_notify_config.id IS '主键'; COMMENT ON COLUMN sj_notify_config.namespace_id IS '命名空间id'; COMMENT ON COLUMN sj_notify_config.group_name IS '组名称'; -COMMENT ON COLUMN sj_notify_config.business_id IS '业务id ( job_id或workflow_id或scene_name ) '; +COMMENT ON COLUMN sj_notify_config.notify_name IS '通知名称'; COMMENT ON COLUMN sj_notify_config.system_task_type IS '任务类型 1. 重试任务 2. 重试回调 3、JOB任务 4、WORKFLOW任务'; COMMENT ON COLUMN sj_notify_config.notify_status IS '通知状态 0、未启用 1、启用'; COMMENT ON COLUMN sj_notify_config.recipient_ids IS '接收人id列表'; @@ -297,6 +297,7 @@ CREATE TABLE sj_retry_scene_config max_retry_count int NOT NULL DEFAULT 5, back_off smallint NOT NULL DEFAULT 1, trigger_interval varchar(16) NOT NULL DEFAULT '', + notify_ids varchar(128) NOT NULL DEFAULT '', deadline_request bigint NOT NULL DEFAULT 60000, executor_timeout int NOT NULL DEFAULT 5, route_key smallint NOT NULL DEFAULT 4, @@ -315,6 +316,7 @@ COMMENT ON COLUMN sj_retry_scene_config.scene_status IS '组状态 0、未启用 COMMENT ON COLUMN sj_retry_scene_config.max_retry_count IS '最大重试次数'; COMMENT ON COLUMN sj_retry_scene_config.back_off IS '1、默认等级 2、固定间隔时间 3、CRON 表达式'; COMMENT ON COLUMN sj_retry_scene_config.trigger_interval IS '间隔时长'; +COMMENT ON COLUMN sj_retry_scene_config.notify_ids IS '通知告警场景配置id列表'; COMMENT ON COLUMN sj_retry_scene_config.deadline_request IS 'Deadline Request 调用链超时 单位毫秒'; COMMENT ON COLUMN sj_retry_scene_config.executor_timeout IS '任务执行超时时间,单位秒'; COMMENT ON COLUMN sj_retry_scene_config.route_key IS '路由策略'; @@ -464,6 +466,8 @@ CREATE TABLE sj_job retry_interval int NOT NULL DEFAULT 0, bucket_index int NOT NULL DEFAULT 0, resident smallint NOT NULL DEFAULT 0, + notify_ids varchar(128) NOT NULL DEFAULT '', + owner_id bigint NULL, description varchar(256) NOT NULL DEFAULT '', ext_attrs varchar(256) NULL DEFAULT '', deleted smallint NOT NULL DEFAULT 0, @@ -496,6 +500,8 @@ COMMENT ON COLUMN sj_job.parallel_num IS '并行数'; COMMENT ON COLUMN sj_job.retry_interval IS '重试间隔 ( s ) '; COMMENT ON COLUMN sj_job.bucket_index IS 'bucket'; COMMENT ON COLUMN sj_job.resident IS '是否是常驻任务'; +COMMENT ON COLUMN sj_job.notify_ids IS '通知告警场景配置id列表'; +COMMENT ON COLUMN sj_job.owner_id IS '负责人id'; COMMENT ON COLUMN sj_job.description IS '描述'; COMMENT ON COLUMN sj_job.ext_attrs IS '扩展字段'; COMMENT ON COLUMN sj_job.deleted IS '逻辑删除 1、删除'; @@ -503,7 +509,7 @@ COMMENT ON COLUMN sj_job.create_dt IS '创建时间'; COMMENT ON COLUMN sj_job.update_dt IS '修改时间'; COMMENT ON TABLE sj_job IS '任务信息'; -INSERT INTO sj_job VALUES (1, 'dev', 'ruoyi_group', 'demo-job', null, 1, 1710344035622, 1, 1, 4, 1, 'testJobExecutor', 2, '60', 1, 60, 3, 1, 1, 116, 0, '', '', 0, now(), now()); +INSERT INTO sj_job VALUES (1, 'dev', 'ruoyi_group', 'demo-job', null, 1, 1710344035622, 1, 1, 4, 1, 'testJobExecutor', 2, '60', 1, 60, 3, 1, 1, 116, 0, '', 1, '', '', 0, now(), now()); -- sj_job_log_message CREATE TABLE sj_job_log_message @@ -721,6 +727,7 @@ CREATE TABLE sj_workflow description varchar(256) NOT NULL DEFAULT '', flow_info text NULL DEFAULT NULL, wf_context text NULL DEFAULT NULL, + notify_ids varchar(128) NOT NULL DEFAULT '', bucket_index int NOT NULL DEFAULT 0, version int NOT NULL, ext_attrs varchar(256) NULL DEFAULT '', @@ -745,6 +752,7 @@ COMMENT ON COLUMN sj_workflow.executor_timeout IS '任务执行超时时间, COMMENT ON COLUMN sj_workflow.description IS '描述'; COMMENT ON COLUMN sj_workflow.flow_info IS '流程信息'; COMMENT ON COLUMN sj_workflow.wf_context IS '上下文'; +COMMENT ON COLUMN sj_workflow.notify_ids IS '通知告警场景配置id列表'; COMMENT ON COLUMN sj_workflow.bucket_index IS 'bucket'; COMMENT ON COLUMN sj_workflow.version IS '版本号'; COMMENT ON COLUMN sj_workflow.ext_attrs IS '扩展字段'; diff --git a/script/sql/ry_job.sql b/script/sql/ry_job.sql index 396798ee0..c6ec01b45 100644 --- a/script/sql/ry_job.sql +++ b/script/sql/ry_job.sql @@ -47,7 +47,7 @@ CREATE TABLE `sj_notify_config` `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', `namespace_id` varchar(64) NOT NULL DEFAULT '764d604ec6fc45f68cd92514c40e9e1a' COMMENT '命名空间id', `group_name` varchar(64) NOT NULL COMMENT '组名称', - `business_id` varchar(64) NOT NULL COMMENT '业务id (job_id或workflow_id或scene_name)', + `notify_name` varchar(64) NOT NULL DEFAULT '' COMMENT '通知名称', `system_task_type` tinyint(4) NOT NULL DEFAULT 3 COMMENT '任务类型 1. 重试任务 2. 重试回调 3、JOB任务 4、WORKFLOW任务', `notify_status` tinyint(4) NOT NULL DEFAULT 0 COMMENT '通知状态 0、未启用 1、启用', `recipient_ids` varchar(128) NOT NULL COMMENT '接收人id列表', @@ -59,7 +59,7 @@ CREATE TABLE `sj_notify_config` `create_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间', PRIMARY KEY (`id`), - KEY `idx_namespace_id_group_name_scene_name` (`namespace_id`, `group_name`, `business_id`) + KEY `idx_namespace_id_group_name_scene_name` (`namespace_id`, `group_name`) ) ENGINE = InnoDB AUTO_INCREMENT = 0 DEFAULT CHARSET = utf8mb4 COMMENT ='通知配置'; @@ -188,6 +188,7 @@ CREATE TABLE `sj_retry_scene_config` `max_retry_count` int(11) NOT NULL DEFAULT 5 COMMENT '最大重试次数', `back_off` tinyint(4) NOT NULL DEFAULT 1 COMMENT '1、默认等级 2、固定间隔时间 3、CRON 表达式', `trigger_interval` varchar(16) NOT NULL DEFAULT '' COMMENT '间隔时长', + `notify_ids` varchar(128) NOT NULL DEFAULT '' COMMENT '通知告警场景配置id列表', `deadline_request` bigint(20) unsigned NOT NULL DEFAULT 60000 COMMENT 'Deadline Request 调用链超时 单位毫秒', `executor_timeout` int(11) unsigned NOT NULL DEFAULT 5 COMMENT '任务执行超时时间,单位秒', `route_key` tinyint(4) NOT NULL DEFAULT 4 COMMENT '路由策略', @@ -300,6 +301,8 @@ CREATE TABLE `sj_job` `retry_interval` int(11) NOT NULL DEFAULT 0 COMMENT '重试间隔(s)', `bucket_index` int(11) NOT NULL DEFAULT 0 COMMENT 'bucket', `resident` tinyint(4) NOT NULL DEFAULT 0 COMMENT '是否是常驻任务', + `notify_ids` varchar(128) NOT NULL DEFAULT '' COMMENT '通知告警场景配置id列表', + `owner_id` bigint(20) NULL COMMENT '负责人id', `description` varchar(256) NOT NULL DEFAULT '' COMMENT '描述', `ext_attrs` varchar(256) NULL DEFAULT '' COMMENT '扩展字段', `deleted` tinyint(4) NOT NULL DEFAULT 0 COMMENT '逻辑删除 1、删除', @@ -313,7 +316,7 @@ CREATE TABLE `sj_job` AUTO_INCREMENT = 0 DEFAULT CHARSET = utf8mb4 COMMENT ='任务信息'; -INSERT INTO `sj_job` VALUES (1, 'dev', 'ruoyi_group', 'demo-job', null, 1, 1710344035622, 1, 1, 4, 1, 'testJobExecutor', 2, '60', 1, 60, 3, 1, 1, 116, 0, '', '', 0 , now(), now()); +INSERT INTO `sj_job` VALUES (1, 'dev', 'ruoyi_group', 'demo-job', null, 1, 1710344035622, 1, 1, 4, 1, 'testJobExecutor', 2, '60', 1, 60, 3, 1, 1, 116, 0, '', 1, '', '', 0 , now(), now()); CREATE TABLE `sj_job_log_message` ( @@ -451,6 +454,7 @@ CREATE TABLE `sj_workflow` `description` varchar(256) NOT NULL DEFAULT '' COMMENT '描述', `flow_info` text DEFAULT NULL COMMENT '流程信息', `wf_context` text DEFAULT NULL COMMENT '上下文', + `notify_ids` varchar(128) NOT NULL DEFAULT '' COMMENT '通知告警场景配置id列表', `bucket_index` int(11) NOT NULL DEFAULT 0 COMMENT 'bucket', `version` int(11) NOT NULL COMMENT '版本号', `ext_attrs` varchar(256) NULL DEFAULT '' COMMENT '扩展字段', diff --git a/script/sql/sqlserver/sqlserver_ry_job.sql b/script/sql/sqlserver/sqlserver_ry_job.sql index bcf87f668..97addc3aa 100644 --- a/script/sql/sqlserver/sqlserver_ry_job.sql +++ b/script/sql/sqlserver/sqlserver_ry_job.sql @@ -2,7 +2,7 @@ SnailJob Database Transfer Tool Source Server Type : MySQL Target Server Type : Microsoft SQL Server - Date: 2024-07-06 12:55:47 + Date: 2024-12-27 22:24:37 */ @@ -212,7 +212,7 @@ CREATE TABLE sj_notify_config id bigint NOT NULL PRIMARY KEY IDENTITY, namespace_id nvarchar(64) NOT NULL DEFAULT '764d604ec6fc45f68cd92514c40e9e1a', group_name nvarchar(64) NOT NULL, - business_id nvarchar(64) NOT NULL, + notify_name nvarchar(64) NOT NULL DEFAULT '', system_task_type tinyint NOT NULL DEFAULT 3, notify_status tinyint NOT NULL DEFAULT 0, recipient_ids nvarchar(128) NOT NULL, @@ -226,7 +226,7 @@ CREATE TABLE sj_notify_config ) GO -CREATE INDEX idx_sj_notify_config_01 ON sj_notify_config (namespace_id, group_name, business_id) +CREATE INDEX idx_sj_notify_config_01 ON sj_notify_config (namespace_id, group_name) GO EXEC sp_addextendedproperty @@ -251,10 +251,10 @@ EXEC sp_addextendedproperty GO EXEC sp_addextendedproperty - 'MS_Description', N'业务id ( job_id或workflow_id或scene_name ) ', + 'MS_Description', N'通知名称', 'SCHEMA', N'dbo', 'TABLE', N'sj_notify_config', - 'COLUMN', N'business_id' + 'COLUMN', N'notify_name' GO EXEC sp_addextendedproperty @@ -917,6 +917,7 @@ CREATE TABLE sj_retry_scene_config max_retry_count int NOT NULL DEFAULT 5, back_off tinyint NOT NULL DEFAULT 1, trigger_interval nvarchar(16) NOT NULL DEFAULT '', + notify_ids nvarchar(128) NOT NULL DEFAULT '', deadline_request bigint NOT NULL DEFAULT 60000, executor_timeout int NOT NULL DEFAULT 5, route_key tinyint NOT NULL DEFAULT 4, @@ -985,6 +986,13 @@ EXEC sp_addextendedproperty 'COLUMN', N'trigger_interval' GO +EXEC sp_addextendedproperty + 'MS_Description', N'通知告警场景配置id列表', + 'SCHEMA', N'dbo', + 'TABLE', N'sj_retry_scene_config', + 'COLUMN', N'notify_ids' +GO + EXEC sp_addextendedproperty 'MS_Description', N'Deadline Request 调用链超时 单位毫秒', 'SCHEMA', N'dbo', @@ -1415,6 +1423,8 @@ CREATE TABLE sj_job retry_interval int NOT NULL DEFAULT 0, bucket_index int NOT NULL DEFAULT 0, resident tinyint NOT NULL DEFAULT 0, + notify_ids nvarchar(128) NOT NULL DEFAULT '', + owner_id bigint NULL, description nvarchar(256) NOT NULL DEFAULT '', ext_attrs nvarchar(256) NULL DEFAULT '', deleted tinyint NOT NULL DEFAULT 0, @@ -1577,6 +1587,20 @@ EXEC sp_addextendedproperty 'COLUMN', N'resident' GO +EXEC sp_addextendedproperty + 'MS_Description', N'通知告警场景配置id列表', + 'SCHEMA', N'dbo', + 'TABLE', N'sj_job', + 'COLUMN', N'notify_ids' +GO + +EXEC sp_addextendedproperty + 'MS_Description', N'负责人id', + 'SCHEMA', N'dbo', + 'TABLE', N'sj_job', + 'COLUMN', N'owner_id' +GO + EXEC sp_addextendedproperty 'MS_Description', N'描述', 'SCHEMA', N'dbo', @@ -1618,7 +1642,7 @@ EXEC sp_addextendedproperty 'TABLE', N'sj_job' GO -INSERT INTO sj_job (namespace_id, group_name, job_name, args_str, args_type, next_trigger_at, job_status, task_type, route_key, executor_type, executor_info, trigger_type, trigger_interval, block_strategy,executor_timeout, max_retry_times, parallel_num, retry_interval, bucket_index, resident, description, ext_attrs, deleted, create_dt, update_dt) VALUES (N'dev', N'ruoyi_group', N'demo-job', null, 1, 1710344035622, 1, 1, 4, 1, N'testJobExecutor', 2, N'60', 1, 60, 3, 1, 1, 116, 0, N'', N'', 0, getdate(), getdate()) +INSERT INTO sj_job (namespace_id, group_name, job_name, args_str, args_type, next_trigger_at, job_status, task_type, route_key, executor_type, executor_info, trigger_type, trigger_interval, block_strategy,executor_timeout, max_retry_times, parallel_num, retry_interval, bucket_index, resident, notify_ids, owner_id, description, ext_attrs, deleted, create_dt, update_dt) VALUES (N'dev', N'ruoyi_group', N'demo-job', null, 1, 1710344035622, 1, 1, 4, 1, N'testJobExecutor', 2, N'60', 1, 60, 3, 1, 1, 116, 0, N'', 1, N'', N'', 0, getdate(), getdate()) GO -- sj_job_log_message @@ -2308,6 +2332,7 @@ CREATE TABLE sj_workflow description nvarchar(256) NOT NULL DEFAULT '', flow_info nvarchar(max) NULL DEFAULT NULL, wf_context nvarchar(max) NULL DEFAULT NULL, + notify_ids nvarchar(128) NOT NULL DEFAULT '', bucket_index int NOT NULL DEFAULT 0, version int NOT NULL, ext_attrs nvarchar(256) NULL DEFAULT '', @@ -2413,6 +2438,13 @@ EXEC sp_addextendedproperty 'COLUMN', N'wf_context' GO +EXEC sp_addextendedproperty + 'MS_Description', N'通知告警场景配置id列表', + 'SCHEMA', N'dbo', + 'TABLE', N'sj_workflow', + 'COLUMN', N'notify_ids' +GO + EXEC sp_addextendedproperty 'MS_Description', N'bucket', 'SCHEMA', N'dbo', @@ -2744,4 +2776,3 @@ EXEC sp_addextendedproperty 'SCHEMA', N'dbo', 'TABLE', N'sj_workflow_task_batch' GO - From 8bd2e27653dd3d1304166edb24d82c818608b052 Mon Sep 17 00:00:00 2001 From: dap <15891557205@163.com> Date: Sat, 4 Jan 2025 16:08:57 +0800 Subject: [PATCH 129/175] =?UTF-8?q?update:=20=E5=A2=9E=E5=8A=A0=E8=8F=9C?= =?UTF-8?q?=E5=8D=95=E9=80=89=E6=8B=A9=E6=8B=93=E5=B1=95=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dromara/system/service/impl/SysMenuServiceImpl.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysMenuServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysMenuServiceImpl.java index 354d4b4d9..40643e13d 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysMenuServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysMenuServiceImpl.java @@ -242,11 +242,14 @@ public class SysMenuServiceImpl implements ISysMenuService { if (CollUtil.isEmpty(menus)) { return CollUtil.newArrayList(); } - return TreeBuildUtils.build(menus, (menu, tree) -> - tree.setId(menu.getMenuId()) + return TreeBuildUtils.build(menus, (menu, tree) -> { + Tree menuTree = tree.setId(menu.getMenuId()) .setParentId(menu.getParentId()) .setName(menu.getMenuName()) - .setWeight(menu.getOrderNum())); + .setWeight(menu.getOrderNum()); + menuTree.put("menuType", menu.getMenuType()); + menuTree.put("icon", menu.getIcon()); + }); } /** From 08e40b611b2bdc97361d4a6d753b788b83818623 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Sun, 5 Jan 2025 23:00:56 +0800 Subject: [PATCH 130/175] =?UTF-8?q?fix=20=E4=BF=AE=E5=A4=8D=20=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E6=9D=83=E9=99=90=20=E5=A4=9A=E8=A7=92=E8=89=B2?= =?UTF-8?q?=E5=A4=9A=E6=B3=A8=E8=A7=A3=E5=8C=85=E5=90=AB=E5=BF=BD=E7=95=A5?= =?UTF-8?q?=E6=9D=83=E9=99=90=E6=A0=87=E8=AF=86=E7=AC=A6=E9=80=BB=E8=BE=91?= =?UTF-8?q?=E4=B8=8D=E6=AD=A3=E7=A1=AE=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../handler/PlusDataPermissionHandler.java | 48 +++++++++++-------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/PlusDataPermissionHandler.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/PlusDataPermissionHandler.java index 783d3526e..07baedb39 100644 --- a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/PlusDataPermissionHandler.java +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/PlusDataPermissionHandler.java @@ -135,6 +135,27 @@ public class PlusDataPermissionHandler { context.setBeanResolver(beanResolver); DataPermissionHelper.getContext().forEach(context::setVariable); Set conditions = new HashSet<>(); + // 优先设置变量 + List keys = new ArrayList<>(); + Map ignoreMap = new HashMap<>(); + for (DataColumn dataColumn : dataPermission.value()) { + if (dataColumn.key().length != dataColumn.value().length) { + throw new ServiceException("角色数据范围异常 => key与value长度不匹配"); + } + // 包含权限标识符 这直接跳过 + if (StringUtils.isNotBlank(dataColumn.permission()) && + CollUtil.contains(user.getMenuPermission(), dataColumn.permission()) + ) { + ignoreMap.put(dataColumn, Boolean.TRUE); + continue; + } + // 设置注解变量 key 为表达式变量 value 为变量值 + for (int i = 0; i < dataColumn.key().length; i++) { + context.setVariable(dataColumn.key()[i], dataColumn.value()[i]); + } + keys.addAll(Arrays.stream(dataColumn.key()).map(key -> "#" + key).toList()); + } + for (RoleDTO role : user.getRoles()) { user.setRoleId(role.getRoleId()); // 获取角色权限泛型 @@ -144,34 +165,21 @@ public class PlusDataPermissionHandler { } // 全部数据权限直接返回 if (type == DataScopeType.ALL) { - return ""; + return StringUtils.EMPTY; } boolean isSuccess = false; - List keys = new ArrayList<>(); for (DataColumn dataColumn : dataPermission.value()) { - if (dataColumn.key().length != dataColumn.value().length) { - throw new ServiceException("角色数据范围异常 => key与value长度不匹配"); - } - // 设置注解变量 key 为表达式变量 value 为变量值 - for (int i = 0; i < dataColumn.key().length; i++) { - context.setVariable(dataColumn.key()[i], dataColumn.value()[i]); - } - keys.addAll(Arrays.stream(dataColumn.key()).map(key -> "#" + key).toList()); - } - for (DataColumn dataColumn : dataPermission.value()) { - // 不包含 key 变量 则不处理 - if (!StringUtils.containsAny(type.getSqlTemplate(), keys.toArray(String[]::new))) { - continue; - } // 包含权限标识符 这直接跳过 - if (StringUtils.isNotBlank(dataColumn.permission()) && - CollUtil.contains(user.getMenuPermission(), dataColumn.permission()) - ) { + if (ignoreMap.containsKey(dataColumn)) { // 修复多角色与权限标识符共用问题 https://gitee.com/dromara/RuoYi-Vue-Plus/issues/IB4CS4 conditions.add(joinStr + " 1 = 1 "); isSuccess = true; continue; } + // 不包含 key 变量 则不处理 + if (!StringUtils.containsAny(type.getSqlTemplate(), keys.toArray(String[]::new))) { + continue; + } // 忽略数据权限 防止spel表达式内有其他sql查询导致死循环调用 String sql = DataPermissionHelper.ignore(() -> @@ -191,7 +199,7 @@ public class PlusDataPermissionHandler { String sql = StreamUtils.join(conditions, Function.identity(), ""); return sql.substring(joinStr.length()); } - return ""; + return StringUtils.EMPTY; } /** From 4de9fa33b7261081a47d8b3bc4ae437a026c9716 Mon Sep 17 00:00:00 2001 From: AprilWind <2100166581@qq.com> Date: Tue, 7 Jan 2025 05:23:27 +0800 Subject: [PATCH 131/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=E9=83=A8=E9=97=A8=E4=BF=A1=E6=81=AF=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E4=BA=8B=E5=8A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/dromara/system/service/impl/SysDeptServiceImpl.java | 2 ++ 1 file changed, 2 insertions(+) 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 0199ec719..ca062bee6 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDeptServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDeptServiceImpl.java @@ -31,6 +31,7 @@ import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.Cacheable; import org.springframework.cache.annotation.Caching; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import java.util.ArrayList; import java.util.Arrays; @@ -301,6 +302,7 @@ public class SysDeptServiceImpl implements ISysDeptService, DeptService { @CacheEvict(cacheNames = CacheNames.SYS_DEPT_AND_CHILD, allEntries = true) }) @Override + @Transactional(rollbackFor = Exception.class) public int updateDept(SysDeptBo bo) { SysDept dept = MapstructUtils.convert(bo, SysDept.class); SysDept oldDept = baseMapper.selectById(dept.getDeptId()); From ad53965626f393e418a06b264a11550539419807 Mon Sep 17 00:00:00 2001 From: CoderKK Date: Tue, 7 Jan 2025 03:59:34 +0000 Subject: [PATCH 132/175] =?UTF-8?q?!634=20docs:=20=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E5=BA=94=E7=94=A8=E9=85=8D=E7=BD=AE=E6=96=87=E4=BB=B6=E4=B8=AD?= =?UTF-8?q?=E7=9A=84=E6=B3=A8=E9=87=8A=E9=94=99=E5=88=AB=E5=AD=97=20*=20do?= =?UTF-8?q?cs:=20=E4=BF=AE=E6=94=B9=E5=BA=94=E7=94=A8=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E4=B8=AD=E7=9A=84=E6=B3=A8=E9=87=8A=E9=94=99?= =?UTF-8?q?=E5=88=AB=E5=AD=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ruoyi-admin/src/main/resources/application-dev.yml | 2 +- ruoyi-admin/src/main/resources/application-prod.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ruoyi-admin/src/main/resources/application-dev.yml b/ruoyi-admin/src/main/resources/application-dev.yml index 685708316..6a804a947 100644 --- a/ruoyi-admin/src/main/resources/application-dev.yml +++ b/ruoyi-admin/src/main/resources/application-dev.yml @@ -23,7 +23,7 @@ snail-job: port: 17888 # 命名空间UUID 详见 script/sql/ry_job.sql `sj_namespace`表`unique_id`字段 namespace: ${spring.profiles.active} - # 随主应用端口飘逸 + # 随主应用端口漂移 port: 2${server.port} # 客户端ip指定 host: diff --git a/ruoyi-admin/src/main/resources/application-prod.yml b/ruoyi-admin/src/main/resources/application-prod.yml index a8c54bcb6..15f2c5243 100644 --- a/ruoyi-admin/src/main/resources/application-prod.yml +++ b/ruoyi-admin/src/main/resources/application-prod.yml @@ -26,7 +26,7 @@ snail-job: port: 17888 # 命名空间UUID 详见 script/sql/ry_job.sql `sj_namespace`表`unique_id`字段 namespace: ${spring.profiles.active} - # 随主应用端口飘逸 + # 随主应用端口漂移 port: 2${server.port} # 客户端ip指定 host: From 254e61ab019e7c6826b5811024b387dd495c2299 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Tue, 7 Jan 2025 13:52:21 +0800 Subject: [PATCH 133/175] =?UTF-8?q?fix=20=E4=BF=AE=E5=A4=8D=20postgresql?= =?UTF-8?q?=E7=9A=84=E8=A1=A8=E5=85=83=E6=95=B0=E6=8D=AE=E6=B2=A1=E6=9C=89?= =?UTF-8?q?=E5=88=9B=E5=BB=BA=E6=97=B6=E9=97=B4=E8=BF=99=E4=B8=AA=E4=B8=9C?= =?UTF-8?q?=E8=A5=BF(=E5=A5=BD=E5=A5=87=E8=91=A9)=20=E5=8F=AA=E8=83=BDnew?= =?UTF-8?q?=20Date=E4=BB=A3=E6=9B=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/dromara/generator/service/GenTableServiceImpl.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java b/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java index 7eb99eb59..acf5bf820 100644 --- a/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java +++ b/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java @@ -162,7 +162,8 @@ public class GenTableServiceImpl implements IGenTableService { GenTable gen = new GenTable(); gen.setTableName(x.getName()); gen.setTableComment(x.getComment()); - gen.setCreateTime(x.getCreateTime()); + // postgresql的表元数据没有创建时间这个东西(好奇葩) 只能new Date代替 + gen.setCreateTime(ObjectUtil.defaultIfNull(x.getCreateTime(), new Date())); gen.setUpdateTime(x.getUpdateTime()); return gen; }).sorted(Comparator.comparing(GenTable::getCreateTime).reversed()) From 820db87604a8a21db5a84ed3fc9334c0c2a41f5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Wed, 8 Jan 2025 10:57:14 +0800 Subject: [PATCH 134/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E4=BD=BF?= =?UTF-8?q?=E7=94=A8request=E5=AD=98=E5=82=A8=E5=8A=A8=E6=80=81=E7=A7=9F?= =?UTF-8?q?=E6=88=B7=20=E9=81=BF=E5=85=8D=E5=8D=95=E8=AF=B7=E6=B1=82?= =?UTF-8?q?=E5=A4=9A=E6=AC=A1=E6=9F=A5=E8=AF=A2redis=E8=8E=B7=E5=8F=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dromara/common/tenant/helper/TenantHelper.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/helper/TenantHelper.java b/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/helper/TenantHelper.java index 1a5ea1a76..74c31107d 100644 --- a/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/helper/TenantHelper.java +++ b/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/helper/TenantHelper.java @@ -5,10 +5,12 @@ import cn.hutool.core.convert.Convert; import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.plugins.IgnoreStrategy; import com.baomidou.mybatisplus.core.plugins.InterceptorIgnoreHelper; +import jakarta.servlet.http.HttpServletRequest; import lombok.AccessLevel; import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.dromara.common.core.constant.GlobalConstants; +import org.dromara.common.core.utils.ServletUtils; import org.dromara.common.core.utils.SpringUtils; import org.dromara.common.core.utils.StringUtils; import org.dromara.common.core.utils.reflect.ReflectUtils; @@ -135,6 +137,7 @@ public class TenantHelper { } String cacheKey = DYNAMIC_TENANT_KEY + ":" + LoginHelper.getUserId(); RedisUtils.setCacheObject(cacheKey, tenantId); + ServletUtils.getRequest().setAttribute(cacheKey, tenantId); } /** @@ -154,8 +157,15 @@ public class TenantHelper { if (StringUtils.isNotBlank(tenantId)) { return tenantId; } + HttpServletRequest request = ServletUtils.getRequest(); String cacheKey = DYNAMIC_TENANT_KEY + ":" + LoginHelper.getUserId(); + tenantId = (String) request.getAttribute(cacheKey); + // 如果为 -1 说明已经查过redis并且不存在值 则直接返回null + if (StringUtils.isNotBlank(tenantId)) { + return tenantId.equals("-1") ? null : tenantId; + } tenantId = RedisUtils.getCacheObject(cacheKey); + request.setAttribute(cacheKey, StringUtils.isBlank(tenantId) ? "-1" : tenantId); return tenantId; } @@ -173,6 +183,7 @@ public class TenantHelper { TEMP_DYNAMIC_TENANT.remove(); String cacheKey = DYNAMIC_TENANT_KEY + ":" + LoginHelper.getUserId(); RedisUtils.deleteObject(cacheKey); + ServletUtils.getRequest().removeAttribute(cacheKey); } /** From a58f72868a5763d32c35742b254408eeb1b4ca61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Wed, 8 Jan 2025 14:47:57 +0800 Subject: [PATCH 135/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E5=B7=A5?= =?UTF-8?q?=E5=85=B7=E7=B1=BB=E5=B0=81=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dromara/common/core/utils/StringUtils.java | 17 +++++++++++++++++ .../generator/service/GenTableServiceImpl.java | 14 ++------------ 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/StringUtils.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/StringUtils.java index dd6ebb119..897ab920a 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/StringUtils.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/StringUtils.java @@ -320,4 +320,21 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils { .collect(Collectors.toList()); } + /** + * 不区分大小写检查 CharSequence 是否以指定的前缀开头。 + * + * @param str 要检查的 CharSequence 可能为 null + * @param prefixs 要查找的前缀可能为 null + * @return 是否包含 + */ + public static boolean startWithAnyIgnoreCase(CharSequence str, CharSequence... prefixs) { + // 判断是否是以指定字符串开头 + for (CharSequence prefix : prefixs) { + if (StringUtils.startsWithIgnoreCase(str, prefix)) { + return true; + } + } + return false; + } + } diff --git a/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java b/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java index acf5bf820..37299804a 100644 --- a/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java +++ b/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java @@ -137,7 +137,7 @@ public class GenTableServiceImpl implements IGenTableService { } // 过滤并转换表格数据 List tables = tablesMap.values().stream() - .filter(x -> !startWithAnyIgnoreCase(x.getName(), TABLE_IGNORE)) + .filter(x -> !StringUtils.startWithAnyIgnoreCase(x.getName(), TABLE_IGNORE)) .filter(x -> { if (CollUtil.isEmpty(tableNames)) { return true; @@ -176,16 +176,6 @@ public class GenTableServiceImpl implements IGenTableService { return TableDataInfo.build(page); } - public static boolean startWithAnyIgnoreCase(CharSequence cs, CharSequence... searchCharSequences) { - // 判断是否是以指定字符串开头 - for (CharSequence searchCharSequence : searchCharSequences) { - if (StringUtils.startsWithIgnoreCase(cs, searchCharSequence)) { - return true; - } - } - return false; - } - /** * 查询据库列表 * @@ -204,7 +194,7 @@ public class GenTableServiceImpl implements IGenTableService { } List> tableList = tablesMap.values().stream() - .filter(x -> !startWithAnyIgnoreCase(x.getName(), TABLE_IGNORE)) + .filter(x -> !StringUtils.startWithAnyIgnoreCase(x.getName(), TABLE_IGNORE)) .filter(x -> tableNameSet.contains(x.getName())).toList(); if (CollUtil.isEmpty(tableList)) { From 9a95c46578a7a6e805ef1d2b2688fda41e8457c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Wed, 8 Jan 2025 15:50:38 +0800 Subject: [PATCH 136/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E5=B0=86?= =?UTF-8?q?servlet=E6=94=B9=E4=B8=BAsaholder=20=E5=85=BC=E5=AE=B9=E5=85=B6?= =?UTF-8?q?=E4=BB=96=E5=9C=BA=E6=99=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dromara/common/tenant/helper/TenantHelper.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/helper/TenantHelper.java b/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/helper/TenantHelper.java index 74c31107d..4b6981a10 100644 --- a/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/helper/TenantHelper.java +++ b/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/helper/TenantHelper.java @@ -1,16 +1,16 @@ package org.dromara.common.tenant.helper; +import cn.dev33.satoken.context.SaHolder; +import cn.dev33.satoken.context.model.SaStorage; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.convert.Convert; import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.plugins.IgnoreStrategy; import com.baomidou.mybatisplus.core.plugins.InterceptorIgnoreHelper; -import jakarta.servlet.http.HttpServletRequest; import lombok.AccessLevel; import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.dromara.common.core.constant.GlobalConstants; -import org.dromara.common.core.utils.ServletUtils; import org.dromara.common.core.utils.SpringUtils; import org.dromara.common.core.utils.StringUtils; import org.dromara.common.core.utils.reflect.ReflectUtils; @@ -137,7 +137,7 @@ public class TenantHelper { } String cacheKey = DYNAMIC_TENANT_KEY + ":" + LoginHelper.getUserId(); RedisUtils.setCacheObject(cacheKey, tenantId); - ServletUtils.getRequest().setAttribute(cacheKey, tenantId); + SaHolder.getStorage().set(cacheKey, tenantId); } /** @@ -157,15 +157,15 @@ public class TenantHelper { if (StringUtils.isNotBlank(tenantId)) { return tenantId; } - HttpServletRequest request = ServletUtils.getRequest(); + SaStorage storage = SaHolder.getStorage(); String cacheKey = DYNAMIC_TENANT_KEY + ":" + LoginHelper.getUserId(); - tenantId = (String) request.getAttribute(cacheKey); + tenantId = storage.getString(cacheKey); // 如果为 -1 说明已经查过redis并且不存在值 则直接返回null if (StringUtils.isNotBlank(tenantId)) { return tenantId.equals("-1") ? null : tenantId; } tenantId = RedisUtils.getCacheObject(cacheKey); - request.setAttribute(cacheKey, StringUtils.isBlank(tenantId) ? "-1" : tenantId); + storage.set(cacheKey, StringUtils.isBlank(tenantId) ? "-1" : tenantId); return tenantId; } @@ -183,7 +183,7 @@ public class TenantHelper { TEMP_DYNAMIC_TENANT.remove(); String cacheKey = DYNAMIC_TENANT_KEY + ":" + LoginHelper.getUserId(); RedisUtils.deleteObject(cacheKey); - ServletUtils.getRequest().removeAttribute(cacheKey); + SaHolder.getStorage().delete(cacheKey); } /** From d2b9cd27970c754da35e951b4cb5f6e7a6fcdea1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Thu, 9 Jan 2025 14:27:52 +0800 Subject: [PATCH 137/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E6=9D=83=E9=99=90=20=E5=88=A4=E6=96=AD=E5=BD=93?= =?UTF-8?q?=E5=89=8D=E6=B3=A8=E8=A7=A3=E4=B8=8D=E6=BB=A1=E8=B6=B3=E6=A8=A1?= =?UTF-8?q?=E6=9D=BF=E5=88=99=E8=B7=B3=E8=BF=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/mybatis/handler/PlusDataPermissionHandler.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/PlusDataPermissionHandler.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/PlusDataPermissionHandler.java index 07baedb39..a3547075b 100644 --- a/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/PlusDataPermissionHandler.java +++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/PlusDataPermissionHandler.java @@ -180,7 +180,10 @@ public class PlusDataPermissionHandler { if (!StringUtils.containsAny(type.getSqlTemplate(), keys.toArray(String[]::new))) { continue; } - + // 当前注解不满足模板 不处理 + if (!StringUtils.containsAny(type.getSqlTemplate(), dataColumn.key())) { + continue; + } // 忽略数据权限 防止spel表达式内有其他sql查询导致死循环调用 String sql = DataPermissionHelper.ignore(() -> parser.parseExpression(type.getSqlTemplate(), parserContext).getValue(context, String.class) From 55b1a67637cf63504ca207181a0df7753e2b030e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Sun, 12 Jan 2025 20:35:11 +0800 Subject: [PATCH 138/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E9=81=BF?= =?UTF-8?q?=E5=85=8D=E9=87=8D=E5=A4=8D=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/tenant/handle/TenantKeyPrefixHandler.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/handle/TenantKeyPrefixHandler.java b/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/handle/TenantKeyPrefixHandler.java index fbf210df1..dcdef6e62 100644 --- a/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/handle/TenantKeyPrefixHandler.java +++ b/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/handle/TenantKeyPrefixHandler.java @@ -60,18 +60,18 @@ public class TenantKeyPrefixHandler extends KeyPrefixHandler { } try { if (InterceptorIgnoreHelper.willIgnoreTenantLine("")) { - return super.unmap(name); + return unmap; } } catch (NoClassDefFoundError ignore) { // 有些服务不需要mp导致类不存在 忽略即可 } if (StringUtils.contains(name, GlobalConstants.GLOBAL_REDIS_KEY)) { - return super.unmap(name); + return unmap; } String tenantId = TenantHelper.getTenantId(); if (StringUtils.isBlank(tenantId)) { log.debug("无法获取有效的租户id -> Null"); - return super.unmap(name); + return unmap; } if (StringUtils.startsWith(unmap, tenantId + "")) { // 如果存在则删除 From b47798ef198d725ec63800f73d3e7a3a61f7fdcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Sun, 12 Jan 2025 20:35:39 +0800 Subject: [PATCH 139/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E6=97=A0?= =?UTF-8?q?=E9=9C=80=E5=A4=9A=E4=BD=99set=E5=8F=98=E9=87=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/org/dromara/common/tenant/config/TenantConfig.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/config/TenantConfig.java b/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/config/TenantConfig.java index 2513aac92..3767fa2f1 100644 --- a/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/config/TenantConfig.java +++ b/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/config/TenantConfig.java @@ -55,14 +55,12 @@ public class TenantConfig { // 使用单机模式 // 设置多租户 redis key前缀 singleServerConfig.setNameMapper(nameMapper); - ReflectUtils.invokeSetter(config, "singleServerConfig", singleServerConfig); } ClusterServersConfig clusterServersConfig = ReflectUtils.invokeGetter(config, "clusterServersConfig"); // 集群配置方式 参考下方注释 if (ObjectUtil.isNotNull(clusterServersConfig)) { // 设置多租户 redis key前缀 clusterServersConfig.setNameMapper(nameMapper); - ReflectUtils.invokeSetter(config, "clusterServersConfig", clusterServersConfig); } }; } From e36e8f77581314541b27bcf43dd99bbc2c916255 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Mon, 13 Jan 2025 13:35:57 +0800 Subject: [PATCH 140/175] =?UTF-8?q?fix=20=E4=BF=AE=E5=A4=8D=20satoken=20da?= =?UTF-8?q?o=E5=B1=82=E8=8E=B7=E5=8F=96timeout=E4=B8=BA=E7=A7=92=E5=AF=BC?= =?UTF-8?q?=E8=87=B4=E4=B8=A2=E5=A4=B1=E6=AF=AB=E7=A7=92=E8=BF=9B=E5=BA=A6?= =?UTF-8?q?=E9=97=AE=E9=A2=98(=E4=B8=B4=E6=97=B6=E4=BF=AE=E5=A4=8D=20?= =?UTF-8?q?=E7=AD=89satoken=E5=AE=98=E6=96=B9=E8=A7=A3=E5=86=B3)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/satoken/core/dao/PlusSaTokenDao.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/core/dao/PlusSaTokenDao.java b/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/core/dao/PlusSaTokenDao.java index 38e12c315..a2a152003 100644 --- a/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/core/dao/PlusSaTokenDao.java +++ b/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/core/dao/PlusSaTokenDao.java @@ -51,7 +51,11 @@ public class PlusSaTokenDao implements SaTokenDao { if (timeout == NEVER_EXPIRE) { RedisUtils.setCacheObject(key, value); } else { - RedisUtils.setCacheObject(key, value, Duration.ofSeconds(timeout)); + if (RedisUtils.hasKey(key)) { + RedisUtils.setCacheObject(key, value, true); + } else { + RedisUtils.setCacheObject(key, value, Duration.ofSeconds(timeout)); + } } CAFFEINE.invalidate(key); } @@ -114,7 +118,11 @@ public class PlusSaTokenDao implements SaTokenDao { if (timeout == NEVER_EXPIRE) { RedisUtils.setCacheObject(key, object); } else { - RedisUtils.setCacheObject(key, object, Duration.ofSeconds(timeout)); + if (RedisUtils.hasKey(key)) { + RedisUtils.setCacheObject(key, object, true); + } else { + RedisUtils.setCacheObject(key, object, Duration.ofSeconds(timeout)); + } } CAFFEINE.invalidate(key); } From ae584d54a63306840172add6da2643cf93d6a234 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Mon, 13 Jan 2025 06:08:15 +0000 Subject: [PATCH 141/175] =?UTF-8?q?!635=20=E5=90=88=E5=B9=B6=20warmflow=20?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=88=86=E6=94=AF=20*=20update=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96=20=E5=B7=A5=E4=BD=9C=E6=B5=81=E8=AE=BE=E8=AE=A1?= =?UTF-8?q?=E5=99=A8=E6=94=AF=E6=8C=81token=E4=BC=A0=E8=BE=93=20=E5=8F=AA?= =?UTF-8?q?=E9=9C=80=E8=A6=81=E6=94=BE=E8=A1=8Ctoken=E5=A4=B4=E8=8E=B7?= =?UTF-8?q?=E5=8F=96=E5=8D=B3=E5=8F=AF=20*=20Merge=20remote-tracking=20bra?= =?UTF-8?q?nch=20'origin/dev'=20into=20warm-flow-future=20*=20update=20?= =?UTF-8?q?=E4=BC=98=E5=8C=96=20=E6=97=A0=E9=9C=80=E5=A4=9A=E4=BD=99set?= =?UTF-8?q?=E5=8F=98=E9=87=8F=20*=20update=20=E4=BC=98=E5=8C=96=20?= =?UTF-8?q?=E9=81=BF=E5=85=8D=E9=87=8D=E5=A4=8D=E5=A4=84=E7=90=86=20*=20up?= =?UTF-8?q?date=20=E4=BC=98=E5=8C=96=20=E5=AE=9E=E4=BD=93=E7=B1=BB?= =?UTF-8?q?=E9=9A=94=E7=A6=BB=20*=20add=20=E5=A2=9E=E5=8A=A0=E6=B5=81?= =?UTF-8?q?=E7=A8=8B=E5=90=AF=E5=8A=A8=EF=BC=8C=E5=8A=9E=E7=90=86=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=20*=20update=20=E8=B0=83=E6=95=B4=E6=B5=81=E7=A8=8B?= =?UTF-8?q?=E9=A9=B3=E5=9B=9E=20*=20Merge=20remote-tracking=20branch=20'or?= =?UTF-8?q?igin/dev'=20into=20warm-flow-future=20*=20update=20warmflow=201?= =?UTF-8?q?.3.7=20*=20update=20=E5=A2=9E=E5=8A=A0=20warmflow=20oracle=20pg?= =?UTF-8?q?=20sqlserver=20sql=E8=84=9A=E6=9C=AC=E6=96=87=E4=BB=B6=20*=20up?= =?UTF-8?q?date=20=E5=A2=9E=E5=8A=A0=20warmflow=20oracle=20pg=20sqlserver?= =?UTF-8?q?=20sql=E8=84=9A=E6=9C=AC=E6=96=87=E4=BB=B6=20*=20add=20?= =?UTF-8?q?=E6=96=B0=E5=A2=9Eworkflow=E4=B8=8D=E5=90=8C=E7=9A=84sql?= =?UTF-8?q?=E8=AF=AD=E5=8F=A5=20*=20add=20=E6=96=B0=E5=A2=9E=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E7=A7=9F=E6=88=B7=E5=90=8C=E6=AD=A5=E9=BB=98=E8=AE=A4?= =?UTF-8?q?=E6=B5=81=E7=A8=8B=E5=AE=9A=E4=B9=89=20*=20update=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96=20=E6=B5=81=E7=A8=8B=E5=88=97=E8=A1=A8=E6=9F=A5?= =?UTF-8?q?=E8=AF=A2=20=E5=88=A0=E9=99=A4=E6=97=A0=E7=94=A8mapper=20*=20up?= =?UTF-8?q?date=20=E5=AF=BC=E5=85=A5=E6=B5=81=E7=A8=8B=20=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E5=B9=B6=E5=8F=91=E5=A4=9A=E6=96=87=E4=BB=B6=E4=B8=8A?= =?UTF-8?q?=E4=BC=A0=20*=20update=20=E8=B0=83=E6=95=B4=E6=B5=81=E7=A8=8B?= =?UTF-8?q?=E5=AE=9A=E4=B9=89=E6=9F=A5=E8=AF=A2=20*=20update=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96=20=E7=BB=9F=E4=B8=80=E4=B9=A6=E5=86=99=E6=A0=BC?= =?UTF-8?q?=E5=BC=8F=20*=20Merge=20remote-tracking=20branch=20'origin/dev'?= =?UTF-8?q?=20into=20warm-flow-future=20*=20update=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E5=8F=91=E5=B8=83=E4=BA=8B=E4=BB=B6=E5=A2=9E=E5=8A=A0=E7=A7=9F?= =?UTF-8?q?=E6=88=B7ID=20*=20update=20=E8=B0=83=E6=95=B4=E9=A9=B3=E5=9B=9E?= =?UTF-8?q?=E8=AE=B0=E5=BD=95=20*=20Revert=20"update=20=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E7=AE=80=E7=95=A5=E4=BF=A1=E6=81=AF=EF=BC=8C?= =?UTF-8?q?=E7=A5=96=E7=BA=A7=E9=83=A8=E9=97=A8=E5=88=97=E8=A1=A8=EF=BC=8C?= =?UTF-8?q?=E9=83=A8=E9=97=A8=E8=B4=9F=E8=B4=A3=E4=BA=BA=E7=AD=89"=20*=20u?= =?UTF-8?q?pdate=20=E8=8E=B7=E5=8F=96=E7=94=A8=E6=88=B7=E7=AE=80=E7=95=A5?= =?UTF-8?q?=E4=BF=A1=E6=81=AF=EF=BC=8C=E7=A5=96=E7=BA=A7=E9=83=A8=E9=97=A8?= =?UTF-8?q?=E5=88=97=E8=A1=A8=EF=BC=8C=E9=83=A8=E9=97=A8=E8=B4=9F=E8=B4=A3?= =?UTF-8?q?=E4=BA=BA=E7=AD=89=20*=20update=20=E6=9B=B4=E6=96=B0warm-flow?= =?UTF-8?q?=E7=89=88=E6=9C=AC=E5=88=B0v1.3.6-m1=20*=20update=20=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E6=B3=A8=E9=87=8A=E4=BF=A1=E6=81=AF=20*=20fix=20?= =?UTF-8?q?=E4=B8=B4=E6=97=B6=E4=BF=AE=E5=A4=8D=20warm=E5=8F=82=E6=95=B0?= =?UTF-8?q?=E8=AF=BB=E5=8F=96=E9=97=AE=E9=A2=98=20*=20update=20warm-flow?= =?UTF-8?q?=201.3.4=20=3D>=201.3.5=20=E4=BC=98=E5=8C=96=E6=B5=81=E7=A8=8B?= =?UTF-8?q?=E5=9B=BE=E5=AF=BC=E5=85=A5=20*=20update=20=E6=9B=B4=E6=96=B0wa?= =?UTF-8?q?rm-flow=E7=89=88=E6=9C=AC=E5=88=B0v1.3.5=202024-12-20=20*=20upd?= =?UTF-8?q?ate=20=E5=A2=9E=E5=8A=A0=E6=8A=84=E9=80=81=E4=BA=BA=E5=90=8D?= =?UTF-8?q?=E7=A7=B0=20*=20update=20=E6=88=91=E7=9A=84=E6=8A=84=E9=80=81?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E7=94=B3=E8=AF=B7=E4=BA=BA=E4=BB=A5=E5=8F=8A?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=97=B6=E9=97=B4=20*=20update=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E7=9B=91=E5=90=AC=E4=BA=8B=E4=BB=B6=E6=B3=A8=E9=87=8A?= =?UTF-8?q?=20*=20update=20=E4=BC=98=E5=8C=96=E6=B5=81=E7=A8=8B=E5=88=86?= =?UTF-8?q?=E7=B1=BB=E5=90=8D=E7=A7=B0=E7=BF=BB=E8=AF=91=E5=9B=9E=E6=98=BE?= =?UTF-8?q?=20*=20fix=20=E4=BF=AE=E6=94=B9=E6=A0=B9=E6=8D=AE=E6=B5=81?= =?UTF-8?q?=E7=A8=8B=E5=88=86=E7=B1=BBid=E6=9F=A5=E8=AF=A2=20*=20update=20?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=B5=81=E7=A8=8B=E5=88=86=E7=B1=BBid?= =?UTF-8?q?=E6=9F=A5=E8=AF=A2=20*=20fix=20=E4=BF=AE=E5=A4=8D=E6=8A=84?= =?UTF-8?q?=E9=80=81=E9=94=99=E8=AF=AF=20*=20fix=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E9=94=99=E8=AF=AF=E5=88=A4=E7=A9=BA=20*=20fix=20=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E9=94=99=E8=AF=AF=E5=88=A4=E7=A9=BA=20*=20update=20?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=88=A0=E9=99=A4=E6=B5=81=E7=A8=8B=E4=BA=8B?= =?UTF-8?q?=E4=BB=B6=20*=20Merge=20remote-tracking=20branch=20'origin/dev'?= =?UTF-8?q?=20into=20warm-flow-future=20*=20Merge=20remote-tracking=20bran?= =?UTF-8?q?ch=20'origin/dev'=20into=20warm-flow-future=20*=20update=20?= =?UTF-8?q?=E8=B0=83=E6=95=B4sql=E4=B9=A6=E5=86=99=E9=A1=BA=E5=BA=8F=20*?= =?UTF-8?q?=20fix=20=E4=BF=AE=E5=A4=8D=20=E6=8A=84=E9=80=81=E7=BC=BA?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E9=97=AE=E9=A2=98=20=E4=B8=8E=20=E5=B7=B2?= =?UTF-8?q?=E5=AE=8C=E6=88=90=E4=BB=BB=E5=8A=A1=E6=95=B0=E6=8D=AE=E5=8F=96?= =?UTF-8?q?=E9=94=99=E9=97=AE=E9=A2=98=20*=20update=20=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E6=A0=B9=E6=8D=AE=E4=B8=9A=E5=8A=A1id=E6=9F=A5=E8=AF=A2?= =?UTF-8?q?=E6=B5=81=E7=A8=8B=E5=AE=9E=E4=BE=8B=E8=AF=A6=E7=BB=86=E4=BF=A1?= =?UTF-8?q?=E6=81=AF=20*=20update=20=E8=B0=83=E6=95=B4=E5=8F=98=E9=87=8F?= =?UTF-8?q?=E5=8F=82=E6=95=B0=20*=20update=20=E8=B0=83=E6=95=B4=E5=88=86?= =?UTF-8?q?=E7=B1=BB=E6=8E=A5=E5=8F=A3=20*=20update=20=E7=BB=9F=E4=B8=80?= =?UTF-8?q?=E4=B8=9A=E5=8A=A1id=E5=8F=82=E6=95=B0=20*=20update=20=E8=B0=83?= =?UTF-8?q?=E6=95=B4=E8=BF=94=E5=9B=9E=E5=8F=82=E6=95=B0=20*=20update=20?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=B8=9A=E5=8A=A1id=E9=80=9A=E7=94=A8?= =?UTF-8?q?=E6=9F=A5=E8=AF=A2=E6=9D=A1=E4=BB=B6=20*=20update=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E4=BB=A3=E7=A0=81=20=E4=BF=AE=E5=A4=8Dbug=20*=20updat?= =?UTF-8?q?e=20=E4=BC=98=E5=8C=96=E6=96=B0=E5=A2=9E=E6=B5=81=E7=A8=8B?= =?UTF-8?q?=E5=88=86=E7=B1=BB=E5=88=A4=E6=96=AD=20*=20Merge=20remote-track?= =?UTF-8?q?ing=20branch=20'origin/dev'=20into=20warm-flow-future=20*=20upd?= =?UTF-8?q?ate=20=E8=B0=83=E6=95=B4=E9=A9=B3=E5=9B=9E=20*=20update=20?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E9=94=99=E8=AF=AF=E6=B3=A8=E9=87=8A=20*=20up?= =?UTF-8?q?date=20=E4=BC=98=E5=8C=96=E6=B5=81=E7=A8=8B=E5=88=86=E7=B1=BBsq?= =?UTF-8?q?l=E8=AF=AD=E5=8F=A5=20*=20update=20=E8=B0=83=E6=95=B4=E9=A9=B3?= =?UTF-8?q?=E5=9B=9E=20*=20update=20=E5=88=A0=E9=99=A4=E6=B5=81=E7=A8=8B?= =?UTF-8?q?=E5=88=86=E7=B1=BB=E7=8A=B6=E6=80=81=20*=20update=20=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E6=B5=81=E7=A8=8B=E5=AE=9A=E4=B9=89=E9=98=B2=E9=87=8D?= =?UTF-8?q?=20*=20[fix]=20*=20update=20=E4=BC=98=E5=8C=96=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=20=E4=BF=AE=E5=A4=8Dbug=20*=20update=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E6=B5=81=E7=A8=8B=E5=AE=9A=E4=B9=89=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E7=B1=BB=E5=88=AB=E6=A0=91=E6=9F=A5=E8=AF=A2=20*=20update=20?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E7=BF=BB=E8=AF=91=E6=A0=B9=E6=8D=AE=E6=B5=81?= =?UTF-8?q?=E7=A8=8B=E5=88=86=E7=B1=BBID=E6=9F=A5=E8=AF=A2=E6=B5=81?= =?UTF-8?q?=E7=A8=8B=E5=88=86=E7=B1=BB=E5=90=8D=E7=A7=B0=20*=20update=20?= =?UTF-8?q?=E6=A0=B9=E6=8D=AE=E5=88=86=E9=A1=B5=E5=AF=B9=E8=B1=A1=E6=9E=84?= =?UTF-8?q?=E5=BB=BA=E8=A1=A8=E6=A0=BC=E5=88=86=E9=A1=B5=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E5=AF=B9=E8=B1=A1=20*=20update=20=E4=BC=98=E5=8C=96=E6=B5=81?= =?UTF-8?q?=E7=A8=8B=E5=AE=9A=E4=B9=89=E5=88=97=E8=A1=A8=E5=90=8D=E7=A7=B0?= =?UTF-8?q?=20*=20update=20=E4=BC=98=E5=8C=96=E6=B5=81=E7=A8=8B=E5=88=86?= =?UTF-8?q?=E7=B1=BB=E6=A0=A1=E9=AA=8C=20*=20update=20=E5=AF=BC=E5=85=A5?= =?UTF-8?q?=E6=B5=81=E7=A8=8B=20=E6=94=AF=E6=8C=81=E8=87=AA=E5=AE=9A?= =?UTF-8?q?=E4=B9=89=E7=B1=BB=E5=88=AB=20*=20update=20=E6=B5=81=E7=A8=8B?= =?UTF-8?q?=E6=A1=88=E4=BE=8B=20=E5=A2=9E=E5=8A=A0=E8=A1=A8=E5=8D=95?= =?UTF-8?q?=E8=B7=AF=E5=BE=84=20*=20update=20=E6=B5=81=E7=A8=8B=E5=AE=9A?= =?UTF-8?q?=E4=B9=89=E6=9F=A5=E8=AF=A2=E8=BF=94=E5=9B=9E=E8=A1=A8=E5=8D=95?= =?UTF-8?q?=E8=B7=AF=E5=BE=84=20*=20update=20=E4=BC=98=E5=8C=96=E4=BB=BB?= =?UTF-8?q?=E5=8A=A1=E4=B8=9A=E5=8A=A1=E5=B1=82=20*=20fix=20=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=20=E8=AF=B7=E5=81=87=E5=A4=A9=E6=95=B0=E4=B8=8D?= =?UTF-8?q?=E5=87=86=E7=A1=AE=E9=97=AE=E9=A2=98=20*=20update=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E9=A9=B3=E5=9B=9E=20=E6=92=A4=E9=94=80=20*=20update?= =?UTF-8?q?=20=E5=88=A0=E9=99=A4=E7=B1=BB=E5=88=AB=E6=9F=A5=E8=AF=A2?= =?UTF-8?q?=E6=9D=83=E9=99=90=20=E9=80=9A=E7=94=A8=E6=9F=A5=E8=AF=A2?= =?UTF-8?q?=E4=B8=8D=E9=9C=80=E8=A6=81=E5=8A=A0=E6=9D=83=E9=99=90=20*=20fi?= =?UTF-8?q?x=20=E4=BF=AE=E5=A4=8D=20=E5=8F=98=E9=87=8F=E5=90=8D=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=E9=94=99=E8=AF=AF=20*=20Merge=20branch=20'warm-flow-f?= =?UTF-8?q?uture'=20of=20https://gitee.com/dromara/RuoYi-Vue=E2=80=A6=20*?= =?UTF-8?q?=20update=20=E8=B0=83=E6=95=B4=E9=A9=B3=E5=9B=9E=20*=20update?= =?UTF-8?q?=20=E8=A1=A8=E5=90=8D=E7=B1=BB=E5=90=8D=E7=BB=9F=E4=B8=80?= =?UTF-8?q?=E5=91=BD=E5=90=8D=20*=20Merge=20branch=20'warm-flow-future'=20?= =?UTF-8?q?of=20https://gitee.com/dromara/RuoYi-Vue=E2=80=A6=20*=20update?= =?UTF-8?q?=20=E6=8C=91=E6=88=98=E8=80=85=E9=A9=B3=E5=9B=9E=20=E6=92=A4?= =?UTF-8?q?=E9=94=80=20*=20Merge=20remote-tracking=20branch=20'origin/dev'?= =?UTF-8?q?=20into=20warm-flow-future=20*=20fix=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E4=BC=9A=E7=AD=BE=20=E7=A5=A8=E7=AD=BE=E6=92=A4=E9=94=80?= =?UTF-8?q?=E9=97=AE=E9=A2=98=20*=20update=20=E8=B0=83=E6=95=B4=E5=B9=B6?= =?UTF-8?q?=E8=A1=8C=E7=8E=AF=E8=8A=82=E6=92=A4=E9=94=80=E9=94=99=E8=AF=AF?= =?UTF-8?q?=20=E5=A2=9E=E5=8A=A0=E5=8A=9E=E7=90=86=E6=A0=A1=E9=AA=8C=20*?= =?UTF-8?q?=20Merge=20branch=20'warm-flow-future'=20of=20https://gitee.com?= =?UTF-8?q?/dromara/RuoYi-Vue=E2=80=A6=20*=20update=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=E5=8A=9E=E7=90=86=E4=BA=BA=20*=20update=20?= =?UTF-8?q?=E4=BC=98=E5=8C=96=20workflow=E6=A8=A1=E5=9D=97=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0doc=E4=BE=9D=E8=B5=96=E8=BE=93=E5=87=BA=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E6=96=87=E6=A1=A3=20*=20Revert=20"update=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96=20=E5=88=A0=E9=99=A4=E6=97=A0=E7=94=A8=E6=96=B9?= =?UTF-8?q?=E6=B3=95"=20*=20Merge=20remote-tracking=20branch=20'origin/dev?= =?UTF-8?q?'=20into=20warm-flow-future=20*=20Merge=20branch=20'warm-flow-f?= =?UTF-8?q?uture'=20of=20https://gitee.com/dromara/RuoYi-Vue=E2=80=A6=20*?= =?UTF-8?q?=20update=20=E8=B0=83=E6=95=B4=E4=BB=A3=E5=8A=9E=E4=BA=BA?= =?UTF-8?q?=E6=9F=A5=E8=AF=A2=E9=94=99=E8=AF=AF=20=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E7=A4=BA=E4=BE=8B=20*=20update=20=E4=BC=98=E5=8C=96=20?= =?UTF-8?q?=E9=87=8D=E6=9E=84=E4=BB=A3=E7=A0=81=20*=20update=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96=20=E9=87=8D=E6=9E=84=E4=BB=A3=E7=A0=81=20*=20update?= =?UTF-8?q?=20=E4=BC=98=E5=8C=96=20=E5=B0=86=E5=B7=A5=E4=BD=9C=E6=B5=81?= =?UTF-8?q?=E6=B6=88=E6=81=AF=E6=8E=A8=E9=80=81=E6=94=B9=E4=B8=BAsse=20*?= =?UTF-8?q?=20add=20=E6=B7=BB=E5=8A=A0=E6=A8=A1=E5=9E=8B=20*=20update=20?= =?UTF-8?q?=E8=B0=83=E6=95=B4=E5=AE=A1=E6=89=B9=E8=AE=B0=E5=BD=95=20*=20up?= =?UTF-8?q?date=20=E8=B0=83=E6=95=B4=E8=AF=B7=E5=81=87=E6=A1=88=E4=BE=8B?= =?UTF-8?q?=20*=20fix=20=E4=BF=AE=E5=A4=8D=E6=B5=81=E7=A8=8B=E5=AE=9A?= =?UTF-8?q?=E4=B9=89=E6=9F=A5=E8=AF=A2=E9=94=99=E8=AF=AF=20*=20update=20?= =?UTF-8?q?=E8=B0=83=E6=95=B4=E6=B5=81=E7=A8=8B=E5=AE=9E=E4=BE=8B=E6=9F=A5?= =?UTF-8?q?=E8=AF=A2=E9=94=99=E8=AF=AF=20*=20update=20=E8=B0=83=E6=95=B4?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=E5=BD=93=E5=89=8D=E7=99=BB=E5=BD=95=E4=BB=BB?= =?UTF-8?q?=E5=8A=A1=E5=AE=9E=E4=BE=8B=20*=20add=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E6=B6=88=E6=81=AF=E5=8F=91=E9=80=81=20*=20update=20=E8=B0=83?= =?UTF-8?q?=E6=95=B4=E5=8A=9E=E7=90=86=E7=9B=91=E5=90=AC=20*=20[add]=20*?= =?UTF-8?q?=20[fix]=20*=20update=20=E9=87=8D=E6=9E=84=20=E5=B0=86=E5=B7=A5?= =?UTF-8?q?=E4=BD=9C=E6=B5=81=E6=9F=A5=E8=AF=A2=E9=80=BB=E8=BE=91=E5=B0=81?= =?UTF-8?q?=E8=A3=85=E4=B8=BA=E5=8D=95=E7=8B=AC=E7=9A=84service=E7=B1=BB?= =?UTF-8?q?=20*=20[update]=20*=20[add]=20*=20=E5=8A=9E=E7=90=86=E9=99=84?= =?UTF-8?q?=E4=BB=B6=E6=8F=90=E4=BA=A4=20*=20=E7=94=B3=E8=AF=B7=E4=BA=BA?= =?UTF-8?q?=E6=9F=A5=E8=AF=A2=E4=BF=AE=E6=94=B9=20*=20update=20=E5=9B=9E?= =?UTF-8?q?=E9=80=80=E4=BC=98=E5=8C=96=20=E5=88=A0=E9=99=A4=E6=97=A0?= =?UTF-8?q?=E7=94=A8=E6=96=B9=E6=B3=95=20*=20update=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E4=BB=BB=E5=8A=A1=E5=8A=9E=E7=90=86=E4=BA=BA=E7=BF=BB=E8=AF=91?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0=20*=20update=20=E4=BC=98=E5=8C=96=E4=BB=BB?= =?UTF-8?q?=E5=8A=A1=E5=88=86=E9=85=8D=E4=BA=BA=E6=9E=9A=E4=B8=BE=20*=20up?= =?UTF-8?q?date=20=E4=BC=98=E5=8C=96=20=E5=88=A0=E9=99=A4=E6=97=A0?= =?UTF-8?q?=E7=94=A8=E6=96=B9=E6=B3=95=20*=20Merge=20remote-tracking=20bra?= =?UTF-8?q?nch=20'origin/dev'=20into=20warm-flow-future=20*=20Merge=20remo?= =?UTF-8?q?te-tracking=20branch=20'origin/dev'=20into=20warm-flow-future?= =?UTF-8?q?=20*=20[add]=20*=20update=20=E4=BC=98=E5=8C=96=E5=85=A8?= =?UTF-8?q?=E5=B1=80=E4=BB=BB=E5=8A=A1=E5=8A=9E=E7=90=86=E7=9B=91=E5=90=AC?= =?UTF-8?q?=20*=20update=20=E5=88=A0=E9=99=A4=E6=97=A0=E7=94=A8=E5=BC=95?= =?UTF-8?q?=E5=85=A5=20*=20Merge=20remote-tracking=20branch=20'origin/dev'?= =?UTF-8?q?=20into=20warm-flow-future=20*=20update=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E6=BF=80=E6=B4=BB/=E6=8C=82=E8=B5=B7=E5=8F=96=E5=8F=8D?= =?UTF-8?q?=E9=80=BB=E8=BE=91=20*=20!614=20style=20workflow=20xml=20?= =?UTF-8?q?=E6=A0=BC=E5=BC=8F=20*=20style=20workflow=20xml=20=E6=A0=BC?= =?UTF-8?q?=E5=BC=8F=20*=20!612=20fix=20FlwInstanceMapper=20xml=E9=94=99?= =?UTF-8?q?=E8=AF=AF=20*=20fix=20FlwInstanceMapper=20xml=E9=94=99=E8=AF=AF?= =?UTF-8?q?=20*=20update=20=E4=BC=98=E5=8C=96=20=E5=90=8E=E7=AB=AF?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=20*=20update=20=E4=BC=98=E5=8C=96=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E8=AF=B7=E6=B1=82=E8=B7=AF=E5=BE=84=20*=20update=20?= =?UTF-8?q?=E8=B0=83=E6=95=B4=E5=B7=B2=E5=8A=9E=E6=8E=92=E5=BA=8F=20*=20ad?= =?UTF-8?q?d=20=E6=B7=BB=E5=8A=A0=E4=BB=BB=E5=8A=A1=E4=BD=9C=E5=BA=9F=20*?= =?UTF-8?q?=20update=20=E8=B0=83=E6=95=B4=E4=BB=BB=E5=8A=A1=E5=8A=9E?= =?UTF-8?q?=E7=90=86=E6=93=8D=E4=BD=9C=20*=20update=20=E8=B0=83=E6=95=B4?= =?UTF-8?q?=E5=8A=A0=E7=AD=BE=EF=BC=8C=E5=87=8F=E7=AD=BE=E6=A0=A1=E9=AA=8C?= =?UTF-8?q?=20*=20update=20=E8=B0=83=E6=95=B4=E5=8A=A0=E7=AD=BE=20*=20add?= =?UTF-8?q?=20=E6=B7=BB=E5=8A=A0=E8=8E=B7=E5=8F=96=E5=BD=93=E5=89=8D?= =?UTF-8?q?=E4=BB=BB=E5=8A=A1=E7=9A=84=E5=8A=9E=E7=90=86=E4=BA=BA=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=20*=20add=20=E6=B7=BB=E5=8A=A0=E4=BB=BB=E5=8A=A1?= =?UTF-8?q?=E6=9F=A5=E8=AF=A2=E4=BC=9A=E7=AD=BE=EF=BC=8C=E7=A5=A8=E7=AD=BE?= =?UTF-8?q?=E6=AF=94=E4=BE=8B=20*=20update=20=E8=B0=83=E6=95=B4=E4=BB=BB?= =?UTF-8?q?=E5=8A=A1=EF=BC=8C=E5=AE=9E=E4=BE=8B=E6=9F=A5=E8=AF=A2=20*=20up?= =?UTF-8?q?date=20=E8=B0=83=E6=95=B4=E4=BB=BB=E5=8A=A1=E5=A7=94=E6=89=98?= =?UTF-8?q?=EF=BC=8C=E8=BD=AC=E5=8A=9E=EF=BC=8C=E4=BC=98=E5=8C=96=E9=83=A8?= =?UTF-8?q?=E5=88=86=E4=BB=A3=E7=A0=81=E7=AD=89=20*=20update=20=E8=B0=83?= =?UTF-8?q?=E6=95=B4=E6=B5=81=E7=A8=8B=E5=AE=9A=E4=B9=89=E8=A7=86=E5=9B=BE?= =?UTF-8?q?=20*=20add=20=E6=B7=BB=E5=8A=A0=E4=BB=BB=E5=8A=A1=EF=BC=8C?= =?UTF-8?q?=E6=B5=81=E7=A8=8B=E5=AE=9E=E4=BE=8B=E5=B8=B8=E7=94=A8=E6=9F=A5?= =?UTF-8?q?=E8=AF=A2=E6=8E=A5=E5=8F=A3=20*=20Merge=20branch=20'dev'=20into?= =?UTF-8?q?=20warm-flow-future=20*=20update=20=E4=BC=98=E5=8C=96=E5=B7=A5?= =?UTF-8?q?=E4=BD=9C=E6=B5=81=E5=B8=B8=E9=87=8F=E4=BD=BF=E7=94=A8=20*=20up?= =?UTF-8?q?date=20=E4=BC=98=E5=8C=96=E6=B5=81=E7=A8=8B=E8=AE=B0=E5=BD=95?= =?UTF-8?q?=E8=BF=90=E8=A1=8C=E6=97=B6=E9=95=BF=E8=8E=B7=E5=8F=96=20*=20up?= =?UTF-8?q?date=20=E4=BC=98=E5=8C=96=E4=BB=BB=E5=8A=A1=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E6=8E=A7=E5=88=B6=E5=B1=82=20*=20update=20=E5=9B=9E=E5=A4=8D?= =?UTF-8?q?=E4=B8=9A=E5=8A=A1=E7=8A=B6=E6=80=81=E6=9E=9A=E4=B8=BE=20*=20up?= =?UTF-8?q?date=20=E4=BC=98=E5=8C=96=E4=B8=9A=E5=8A=A1=E7=8A=B6=E6=80=81?= =?UTF-8?q?=E6=9E=9A=E4=B8=BE=20*=20update=20=E8=B0=83=E6=95=B4=E6=98=B5?= =?UTF-8?q?=E7=A7=B0=E7=BF=BB=E8=AF=91=20*=20update=20=E8=B0=83=E6=95=B4?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=8A=9E=E7=90=86=E4=BA=BA=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=20*=20update=20=E8=B0=83=E6=95=B4=E6=B5=81=E7=A8=8B=E5=85=A8?= =?UTF-8?q?=E5=B1=80=E7=9B=91=E5=90=AC=EF=BC=8C=E8=B0=83=E6=95=B4=E4=BB=BB?= =?UTF-8?q?=E5=8A=A1=E5=8A=9E=E7=90=86=E4=BA=BA=E6=89=B9=E9=87=8F=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=EF=BC=8C=E4=BC=98=E5=8C=96=E4=BB=A3=E7=A0=81=20*=20up?= =?UTF-8?q?date=20=E4=BC=98=E5=8C=96=E6=9F=A5=E8=AF=A2=E5=8F=AF=E9=A9=B3?= =?UTF-8?q?=E5=9B=9E=E8=8A=82=E7=82=B9=20*=20update=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=8A=84=E9=80=81=E4=BA=BA=20*=20update=20?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=A2=9E=E5=8A=A0=E4=BA=BA=E5=91=98=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B=E6=9E=9A=E4=B8=BE=EF=BC=8C=E5=88=A0=E9=99=A4=E6=97=A0?= =?UTF-8?q?=E7=94=A8=E5=B8=B8=E9=87=8F=20*=20update=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E8=AF=B7=E5=81=87=E5=A4=A9=E6=95=B0=E5=B7=A5=E5=85=B7=E7=B1=BB?= =?UTF-8?q?=EF=BC=8C=E5=88=A0=E9=99=A4=E7=BC=93=E5=AD=98=EF=BC=8C=E5=8A=A0?= =?UTF-8?q?=E9=94=81=E5=A4=84=E7=90=86=EF=BC=8C=E5=8F=AF=E4=BB=A5=E9=87=87?= =?UTF-8?q?=E7=94=A8=E5=A4=96=E9=83=A8=E4=BC=A0=E5=8F=82=E7=9A=84=E5=BD=A2?= =?UTF-8?q?=E5=BC=8F=E5=A4=84=E7=90=86redis=E9=83=A8=E5=88=86=20*=20update?= =?UTF-8?q?=20=E4=BC=98=E5=8C=96=E8=AF=B7=E5=81=87=E5=A4=A9=E6=95=B0?= =?UTF-8?q?=E8=AE=A1=E7=AE=97=20*=20update=20=E4=BC=98=E5=8C=96=E4=BB=BB?= =?UTF-8?q?=E5=8A=A1=E5=AE=8C=E6=88=90=E6=97=B6=E9=97=B4=E5=A4=84=E7=90=86?= =?UTF-8?q?=20*=20update=20=E4=BC=98=E5=8C=96=E4=BB=BB=E5=8A=A1=E5=8A=9E?= =?UTF-8?q?=E7=90=86=E4=BA=BA=E8=8E=B7=E5=8F=96=20*=20update=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E4=BB=BB=E5=8A=A1=E6=93=8D=E4=BD=9C=EF=BC=8C=E5=A7=94?= =?UTF-8?q?=E6=B4=BE=E3=80=81=E8=BD=AC=E5=8A=9E=E3=80=81=E5=8A=A0=E7=AD=BE?= =?UTF-8?q?=E3=80=81=E5=87=8F=E7=AD=BE=E3=80=81=E4=BF=AE=E6=94=B9=E5=8A=9E?= =?UTF-8?q?=E7=90=86=E4=BA=BA=E7=AD=89=20*=20add=20=E6=96=B0=E5=A2=9Ewarm-?= =?UTF-8?q?flow-all.sql=20*=20del=20=E5=88=A0=E9=99=A4=E5=A4=9A=E4=BD=99SQ?= =?UTF-8?q?L=20*=20del=20=E5=88=A0=E9=99=A4=E6=97=A0=E7=94=A8vo=20*=20del?= =?UTF-8?q?=20=E5=88=A0=E9=99=A4=E8=A1=A8=E5=8D=95=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E4=BF=A1=E6=81=AF=20*=20del=20=E5=88=A0=E9=99=A4=E8=8A=82?= =?UTF-8?q?=E7=82=B9=E9=85=8D=E7=BD=AE=E4=BF=A1=E6=81=AF=20*=20update=20?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E8=8A=82=E7=82=B9=E7=B1=BB=E5=9E=8B=E5=B8=B8?= =?UTF-8?q?=E9=87=8F=E8=8E=B7=E5=8F=96=20*=20update=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E6=9D=83=E9=99=90=E5=8A=9E=E7=90=86=E4=BA=BA=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=20*=20update=20=E4=BC=98=E5=8C=96=E6=9D=83=E9=99=90=E5=8A=9E?= =?UTF-8?q?=E7=90=86=E4=BA=BA=E8=8E=B7=E5=8F=96=E5=88=A4=E6=96=AD=20*=20up?= =?UTF-8?q?date=20=E6=8F=90=E4=BA=A4=E7=AD=89=E5=BE=85=E6=96=B0=E7=89=88?= =?UTF-8?q?=E6=9C=AC=E5=BE=85=E4=BC=98=E5=8C=96=E7=9A=84=E5=BC=80=E5=A7=8B?= =?UTF-8?q?=E7=9B=91=E5=90=AC=E4=BF=A1=E6=81=AF=20*=20update=20=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E8=8E=B7=E5=8F=96=E9=83=A8=E9=97=A8=E8=B4=9F=E8=B4=A3?= =?UTF-8?q?=E4=BA=BA=20*=20add=20=E6=96=B0=E5=A2=9E=E5=88=86=E6=B4=BE?= =?UTF-8?q?=E5=8A=9E=E7=90=86=E4=BA=BA=E7=9B=91=E5=90=AC=E5=99=A8=20*=20up?= =?UTF-8?q?date=20=E4=BC=98=E5=8C=96=E6=88=96=E8=80=85=E5=AD=97=E7=AC=A6?= =?UTF-8?q?=E4=B8=B2=E7=94=A8=E6=88=B7ID=20*=20update=20=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E5=89=8D=E7=BC=80=E5=8E=BB=E6=8E=89=20*=20update=20=E8=B0=83?= =?UTF-8?q?=E6=95=B4=E6=B5=81=E7=A8=8B=E5=AE=9E=E4=BE=8B=E7=8A=B6=E6=80=81?= =?UTF-8?q?=E6=9F=A5=E8=AF=A2=20*=20add=20=E6=B7=BB=E5=8A=A0=E6=B5=81?= =?UTF-8?q?=E7=A8=8B=E6=92=A4=E9=94=80=20*=20add=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E6=B5=81=E7=A8=8B=E6=8A=84=E9=80=81=20*=20add=20=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E5=8A=9E=E7=90=86=E4=BA=BA=E6=9D=83=E9=99=90=E5=A4=84?= =?UTF-8?q?=E7=90=86=E5=99=A8=20*=20update=20=E5=8D=87=E7=BA=A7warm-flow1.?= =?UTF-8?q?3.4=20*=20Merge=20branch=20'dev'=20into=20warm-flow-future=20*?= =?UTF-8?q?=20update=20=E8=B0=83=E6=95=B4=E6=B5=81=E7=A8=8B=E5=AE=9A?= =?UTF-8?q?=E4=B9=89=E5=A4=8D=E5=88=B6=20*=20update=20=E8=B0=83=E6=95=B4?= =?UTF-8?q?=E6=B5=81=E7=A8=8B=E5=90=AF=E5=8A=A8=E8=AE=BE=E7=BD=AE=E5=90=AF?= =?UTF-8?q?=E5=8A=A8=E4=BA=BA=E5=8F=98=E9=87=8F=20*=20update=20=E8=B0=83?= =?UTF-8?q?=E6=95=B4=E6=B5=81=E7=A8=8B=E5=AE=9A=E4=B9=89=E5=88=A0=E9=99=A4?= =?UTF-8?q?=20*=20update=20=E8=B0=83=E6=95=B4=E6=B5=81=E7=A8=8B=E5=AE=9A?= =?UTF-8?q?=E4=B9=89=E5=AF=BC=E5=85=A5=20*=20update=20=E8=B0=83=E6=95=B4?= =?UTF-8?q?=E5=B7=A5=E4=BD=9C=E6=B5=81=E4=BB=BB=E5=8A=A1=EF=BC=8C=E6=B5=81?= =?UTF-8?q?=E7=A8=8B=E5=AE=9A=E4=B9=89=E7=AD=89=E6=9F=A5=E8=AF=A2=20*=20up?= =?UTF-8?q?date=20=E8=B0=83=E6=95=B4=E5=B7=A5=E4=BD=9C=E6=B5=81=E4=BA=BA?= =?UTF-8?q?=E5=91=98=E7=BF=BB=E8=AF=91=E6=9F=A5=E8=AF=A2=20*=20update=20?= =?UTF-8?q?=E8=B0=83=E6=95=B4=E8=BD=AC=E5=8A=9E=EF=BC=8C=E5=8A=A0=E7=AD=BE?= =?UTF-8?q?=E7=AD=89=E5=8F=82=E6=95=B0=20*=20update=20=E8=B0=83=E6=95=B4?= =?UTF-8?q?=E6=B5=81=E7=A8=8B=E5=8A=9E=E7=90=86=E8=AE=BE=E7=BD=AE=E5=8A=9E?= =?UTF-8?q?=E7=90=86=E4=BA=BA=20*=20update=20=E8=B0=83=E6=95=B4=E6=B5=81?= =?UTF-8?q?=E7=A8=8B=E8=AE=BE=E8=AE=A1=E4=BF=9D=E5=AD=98=20*=20update=20?= =?UTF-8?q?=E8=B0=83=E6=95=B4=E6=B5=81=E7=A8=8B=E7=8A=B6=E6=80=81=EF=BC=8C?= =?UTF-8?q?=E7=A7=BB=E9=99=A4=E8=BF=87=E6=97=B6=E6=96=B9=E6=B3=95=EF=BC=8C?= =?UTF-8?q?=E8=B0=83=E6=95=B4=E6=9F=A5=E8=AF=A2=E5=8A=9E=E7=90=86=E4=BA=BA?= =?UTF-8?q?=20*=20update=20=E8=A1=A5=E5=85=85=E5=B7=A5=E4=BD=9C=E6=B5=81?= =?UTF-8?q?=E8=AF=B7=E6=B1=82=E5=A2=9E=E5=8A=A0=E9=89=B4=E6=9D=83=20*=20up?= =?UTF-8?q?date=20=E5=B7=A5=E4=BD=9C=E6=B5=81=E8=AF=B7=E6=B1=82=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E9=89=B4=E6=9D=83=20*=20update=20=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E6=B5=81=E7=A8=8B=E5=AE=8C=E6=88=90=E7=9B=91=E5=90=AC=E5=99=A8?= =?UTF-8?q?=20*=20update=20=E6=96=B0=E5=A2=9E=E6=B5=81=E7=A8=8B=E5=90=AF?= =?UTF-8?q?=E5=8A=A8=E7=9B=91=E5=90=AC=E5=99=A8=20*=20Merge=20remote-track?= =?UTF-8?q?ing=20branch=20'origin/dev'=20into=20warm-flow-future=20*=20upd?= =?UTF-8?q?ate=20=E6=9B=B4=E6=96=B0warm-flow=E7=89=88=E6=9C=AC=20*=20updat?= =?UTF-8?q?e=20=E4=BC=98=E5=8C=96workflow=E8=A1=A8sql=E6=A0=BC=E5=BC=8F=20?= =?UTF-8?q?*=20update=20=E4=BC=98=E5=8C=96=EF=BC=8C=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E5=B2=97=E4=BD=8D=E6=9D=83=E9=99=90=E5=88=A4=E7=A9=BA=E5=A4=84?= =?UTF-8?q?=E7=90=86=20*=20update=20=E5=BD=93=E5=89=8D=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E6=89=80=E6=9C=89=E6=9D=83=E9=99=90=E5=B2=97=E4=BD=8DID?= =?UTF-8?q?=E6=94=B9=E4=B8=BA=E4=BB=8Etoken=E8=8E=B7=E5=8F=96=20*=20update?= =?UTF-8?q?=20=E5=BD=93=E5=89=8D=E7=94=A8=E6=88=B7=E6=89=80=E6=9C=89?= =?UTF-8?q?=E6=9D=83=E9=99=90=E5=A2=9E=E5=8A=A0=E5=B2=97=E4=BD=8DID?= =?UTF-8?q?=E6=9D=83=E9=99=90=20*=20update=20=E6=9B=B4=E6=96=B0=E9=80=9A?= =?UTF-8?q?=E8=BF=87=E5=B2=97=E4=BD=8DID=E6=9F=A5=E8=AF=A2=E7=94=A8?= =?UTF-8?q?=E6=88=B7=20*=20update=20=E4=BC=98=E5=8C=96=E6=BF=80=E6=B4=BB/?= =?UTF-8?q?=E6=8C=82=E8=B5=B7=E6=B5=81=E7=A8=8B=E5=AE=9A=E4=B9=89=E5=88=A4?= =?UTF-8?q?=E6=96=AD=20*=20Revert=20"add=20=E6=96=B0=E5=A2=9E=E5=BC=82?= =?UTF-8?q?=E5=B8=B8=E5=A4=84=E7=90=86=E5=99=A8=E5=92=8C=E5=B7=A5=E4=BD=9C?= =?UTF-8?q?=E6=B5=81=E5=B0=81=E8=A3=85=E5=8C=85"=20*=20add=20=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E5=BC=82=E5=B8=B8=E5=A4=84=E7=90=86=E5=99=A8=E5=92=8C?= =?UTF-8?q?=E5=B7=A5=E4=BD=9C=E6=B5=81=E5=B0=81=E8=A3=85=E5=8C=85=20*=20up?= =?UTF-8?q?date=20=E4=BC=98=E5=8C=96=E5=BE=85=E5=8A=9E=E4=BB=BB=E5=8A=A1?= =?UTF-8?q?=E6=9F=A5=E8=AF=A2=E4=BB=A5=E5=8F=8A=E4=BB=BB=E5=8A=A1=E6=B5=81?= =?UTF-8?q?=E8=BD=AC=20*=20update=20=E4=BC=98=E5=8C=96=E5=B7=A5=E4=BD=9C?= =?UTF-8?q?=E6=B5=81=E5=B7=A5=E5=85=B7=EF=BC=8C=E9=81=BF=E5=85=8D=E5=A4=9A?= =?UTF-8?q?=E6=AC=A1=E8=8E=B7=E5=8F=96=E8=AF=B7=E6=B1=82=20*=20fix=20?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=97=A0=E6=95=88=E6=A0=87=E8=AF=86=20*=20Me?= =?UTF-8?q?rge=20remote-tracking=20branch=20'origin/dev'=20into=20warm-flo?= =?UTF-8?q?w-future=20*=20update=20=E6=9F=A5=E8=AF=A2=E9=83=A8=E9=97=A8?= =?UTF-8?q?=E5=B9=B6=E8=BF=94=E5=9B=9E=E4=BB=BB=E5=8A=A1=E6=8C=87=E6=B4=BE?= =?UTF-8?q?=E7=9A=84=E5=88=97=E8=A1=A8=E6=A0=B9=E6=8D=AE=E9=83=A8=E9=97=A8?= =?UTF-8?q?=E6=A0=91=E6=90=9C=E7=B4=A2=20*=20Merge=20remote-tracking=20bra?= =?UTF-8?q?nch=20'origin/dev'=20into=20warm-flow-future=20*=20update=20?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BB=BB=E5=8A=A1=E5=8A=9E=E7=90=86=E4=BA=BA?= =?UTF-8?q?=E5=88=86=E7=BB=84=20*=20update=20=E4=BC=98=E5=8C=96=E4=BB=BB?= =?UTF-8?q?=E5=8A=A1=E5=8A=9E=E7=90=86=E4=BA=BA=E6=9F=A5=E8=AF=A2=20*=20up?= =?UTF-8?q?date=20=E4=BC=98=E5=8C=96=E4=BB=BB=E5=8A=A1=E5=8A=9E=E7=90=86?= =?UTF-8?q?=E4=BA=BA=E6=9F=A5=E8=AF=A2=20*=20update=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E4=BB=BB=E5=8A=A1=E5=8A=9E=E7=90=86=E4=BA=BA=20*=20update=20?= =?UTF-8?q?=E5=AE=8C=E5=96=84=E4=BB=BB=E5=8A=A1=E5=8A=9E=E7=90=86=E4=BA=BA?= =?UTF-8?q?=20*=20add=20=E6=96=B0=E5=A2=9E=E8=A7=92=E8=89=B2=E5=8A=9E?= =?UTF-8?q?=E7=90=86=E4=BA=BA=20*=20!596=20=E4=BC=98=E5=8C=96=E5=B7=A5?= =?UTF-8?q?=E4=BD=9C=E6=B5=81=E4=BB=A3=E7=A0=81=E9=80=BB=E8=BE=91=20*=20up?= =?UTF-8?q?date=20=E4=BC=98=E5=8C=96=E5=B7=A5=E4=BD=9C=E6=B5=81=E5=B7=A5?= =?UTF-8?q?=E5=85=B7=E5=86=97=E4=BD=99=E4=BB=A3=E7=A0=81=20*=20update=20?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=B7=A5=E4=BD=9C=E6=B5=81=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E9=80=BB=E8=BE=91=20*=20update=20=E8=B0=83=E6=95=B4=E5=8A=9E?= =?UTF-8?q?=E7=90=86=20=E9=A9=B3=E5=9B=9E=20=E7=BB=88=E6=AD=A2=E7=AD=89?= =?UTF-8?q?=E7=8A=B6=E6=80=81=20*=20update=20=E8=B0=83=E6=95=B4=E6=B5=81?= =?UTF-8?q?=E7=A8=8B=E5=AE=9A=E4=B9=89=E6=9F=A5=E8=AF=A2=20*=20=E8=A7=A3?= =?UTF-8?q?=E5=86=B3=E5=86=B2=E7=AA=81=E6=8F=90=E4=BA=A4=20warmflow?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=20*=20update=20=E5=8D=87=E7=BA=A7warm-flow?= =?UTF-8?q?=E5=88=B01.3.0=20=E8=B0=83=E6=95=B4=E6=B5=81=E7=A8=8B=E5=8A=9E?= =?UTF-8?q?=E7=90=86=20=EF=BC=8C=E9=A9=B3=E5=9B=9E=EF=BC=8C=E7=BB=88?= =?UTF-8?q?=E6=AD=A2=E7=AD=89=20=E6=B7=BB=E5=8A=A0=E8=87=AA=E5=AE=9A?= =?UTF-8?q?=E4=B9=89=E7=9B=91=E5=90=AC=20*=20Merge=20remote-tracking=20bra?= =?UTF-8?q?nch=20'origin/dev'=20into=20warm-flow-future=20*=20update=20?= =?UTF-8?q?=E8=B0=83=E6=95=B4=E6=B5=81=E7=A8=8Bxml=E6=9F=A5=E8=AF=A2=20*?= =?UTF-8?q?=20update=20=E8=B0=83=E6=95=B4=E9=A9=B3=E5=9B=9E=20*=20update?= =?UTF-8?q?=20=E5=8D=87=E7=BA=A7warm-flow=20*=20update=20=E8=B0=83?= =?UTF-8?q?=E6=95=B4=E4=BB=BB=E5=8A=A1=E5=8A=9E=E7=90=86=E8=AE=BE=E7=BD=AE?= =?UTF-8?q?=E5=8A=9E=E7=90=86=E4=BA=BA=20*=20=E8=B0=83=E6=95=B4=E8=BD=AC?= =?UTF-8?q?=E5=8A=9E=EF=BC=8C=E5=A7=94=E6=89=98=E5=8F=82=E6=95=B0=20*=20up?= =?UTF-8?q?date=20warm-flow=201.2.4=20=3D>=201.2.7=20*=20Merge=20remote-tr?= =?UTF-8?q?acking=20branch=20'origin/dev'=20into=20warm-flow-future=20*=20?= =?UTF-8?q?update=20=E8=B0=83=E6=95=B4=E6=8A=84=E9=80=81=E9=94=99=E8=AF=AF?= =?UTF-8?q?=20*=20=E6=B7=BB=E5=8A=A0=E5=B7=B2=E5=8A=9E=EF=BC=8C=E6=9C=AA?= =?UTF-8?q?=E5=8A=9E=20*=20Merge=20branch=20'warm-flow-future'=20of=20http?= =?UTF-8?q?s://gitee.com/dromara/RuoYi-Vue=E2=80=A6=20*=20add=20=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E6=88=91=E5=8F=91=E8=B5=B7=E7=9A=84=E5=8D=95=E6=8D=AE?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=20*=20Merge=20remote-tracking=20branch=20'or?= =?UTF-8?q?igin/dev'=20into=20warm-flow-future=20*=20update=20=E8=B0=83?= =?UTF-8?q?=E6=95=B4=E6=B5=81=E7=A8=8B=E5=AE=9E=E4=BE=8B=EF=BC=8C=E5=BE=85?= =?UTF-8?q?=E5=8A=9E=E6=9F=A5=E8=AF=A2=20*=20remove=20=E5=88=A0=E9=99=A4?= =?UTF-8?q?=E6=97=A0=E7=94=A8=E6=A0=A1=E9=AA=8C=20*=20add=20=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E5=BE=85=E5=8A=9E=E4=BA=BA=E6=9F=A5=E8=AF=A2=20*=20Me?= =?UTF-8?q?rge=20branch=20'dev'=20into=20warm-flow-future=20*=20update=20?= =?UTF-8?q?=E8=B0=83=E6=95=B4=E5=AD=97=E6=AE=B5=E9=94=99=E8=AF=AF=EF=BC=8C?= =?UTF-8?q?=E6=B5=81=E7=A8=8B=E5=AF=BC=E5=85=A5=20*=20add=20=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E6=B5=81=E7=A8=8B=E6=BF=80=E6=B4=BB/=E6=8C=82?= =?UTF-8?q?=E8=B5=B7=E6=8E=A5=E5=8F=A3=20=E5=8D=87=E7=BA=A7warm-flow?= =?UTF-8?q?=E5=88=B01.2.4=20*=20add=20=E6=B7=BB=E5=8A=A0=E5=8E=86=E5=8F=B2?= =?UTF-8?q?=E6=B5=81=E7=A8=8B=E5=AE=9A=E4=B9=89=E6=9F=A5=E8=AF=A2=20?= =?UTF-8?q?=E8=B0=83=E6=95=B4=E6=B5=81=E7=A8=8B=E5=8F=91=E5=B8=83=20*=20Me?= =?UTF-8?q?rge=20remote-tracking=20branch=20'origin/dev'=20into=20warm-flo?= =?UTF-8?q?w-future=20*=20Merge=20remote-tracking=20branch=20'origin/dev'?= =?UTF-8?q?=20into=20warm-flow-future=20*=20Merge=20remote-tracking=20bran?= =?UTF-8?q?ch=20'origin/dev'=20into=20warm-flow-future=20*=20Merge=20remot?= =?UTF-8?q?e-tracking=20branch=20'origin/dev'=20into=20warm-flow-future=20?= =?UTF-8?q?*=20update=20=E4=BC=98=E5=8C=96=20TenantSpringCacheManager=20?= =?UTF-8?q?=E5=A4=84=E7=90=86=E9=80=BB=E8=BE=91=20*=20fix=20=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=20=E4=B8=80=E7=BA=A7=E7=BC=93=E5=AD=98key=E6=9C=AA?= =?UTF-8?q?=E5=8C=BA=E5=88=86=E7=A7=9F=E6=88=B7=E9=97=AE=E9=A2=98=20*=20up?= =?UTF-8?q?date=20=E4=BC=98=E5=8C=96=20=E8=A7=92=E8=89=B2=E6=9D=83?= =?UTF-8?q?=E9=99=90=E5=88=A4=E6=96=AD=20*=20update=20=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=20readme=20*=20update=20=E4=BC=98=E5=8C=96=20=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E5=88=A0=E9=99=A4=E6=A0=87=E5=BF=97=E4=BD=8D=E5=B8=B8?= =?UTF-8?q?=E9=87=8F=E4=BC=98=E5=8C=96=E6=9F=A5=E8=AF=A2=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=20*=20fix=20=E4=BF=AE=E5=A4=8D=20=E7=99=BB=E5=87=BA=E6=97=A0?= =?UTF-8?q?=E6=B3=95=E6=AD=A3=E7=A1=AE=E5=88=A0=E9=99=A4=E5=AF=B9=E5=BA=94?= =?UTF-8?q?=E7=9A=84=E7=A7=9F=E6=88=B7=E6=95=B0=E6=8D=AE=E9=97=AE=E9=A2=98?= =?UTF-8?q?=20*=20update=20=E4=BC=98=E5=8C=96=20sse=20=E6=8B=A6=E6=88=AA?= =?UTF-8?q?=E7=BD=91=E7=BB=9C=E4=B8=AD=E6=96=ADio=E5=BC=82=E5=B8=B8=20*=20?= =?UTF-8?q?fix=20=E4=BF=AE=E5=A4=8D=20=E7=99=BB=E5=BD=95=E9=94=99=E8=AF=AF?= =?UTF-8?q?=E9=94=81=E5=AE=9A=E4=B8=8D=E5=8C=BA=E5=88=86=E7=A7=9F=E6=88=B7?= =?UTF-8?q?=E9=97=AE=E9=A2=98=20*=20update=20=E4=BC=98=E5=8C=96=20sse=20?= =?UTF-8?q?=E5=85=B3=E9=97=AD=E8=BF=9E=E6=8E=A5=E5=90=84=E7=A7=8D=E5=BC=82?= =?UTF-8?q?=E5=B8=B8=E9=97=AE=E9=A2=98=20*=20update=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=20=E7=9B=91=E6=8E=A7=E4=BD=BF=E7=94=A8=E7=8B=AC=E7=AB=8Bweb?= =?UTF-8?q?=E4=BE=9D=E8=B5=96=20*=20fix=20=E4=BF=AE=E5=A4=8D=20=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E7=94=9F=E6=88=90=20=E9=94=99=E8=AF=AF=E5=8C=B9?= =?UTF-8?q?=E9=85=8D=E8=A1=A8=E5=90=8D=E9=97=AE=E9=A2=98=20*=20update=20?= =?UTF-8?q?=E4=BC=98=E5=8C=96=20=E9=80=82=E9=85=8D=20anyline=20=E6=96=B0?= =?UTF-8?q?=E6=94=B9=E5=8A=A8=20*=20update=20anyline=208.7.2-20240728=20*?= =?UTF-8?q?=20update=20=E8=84=B1=E6=95=8F=E7=AD=96=E7=95=A5=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E5=A2=9E=E5=8A=A0=E5=AF=86=E7=A0=81=20*=20add=20?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=20=E6=9B=B4=E5=A4=9A=E8=84=B1=E6=95=8F?= =?UTF-8?q?=E7=AD=96=E7=95=A5=20*=20update=20=E4=BC=98=E5=8C=96oss?= =?UTF-8?q?=E6=9F=A5=E8=AF=A2=E4=BB=A3=E7=A0=81=20*=20update=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96=20sse=E5=8F=91=E9=80=81=E6=B6=88=E6=81=AF=20=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0token=E6=9C=89=E6=95=88=E6=9C=9F=E5=88=A4=E6=96=AD=20*?= =?UTF-8?q?=20fix=20=E4=BF=AE=E5=A4=8D=20=E7=99=BB=E5=87=BA=E5=90=8E?= =?UTF-8?q?=E9=87=8D=E6=96=B0=E7=99=BB=E5=BD=95=20sse=E6=8E=A8=E9=80=81?= =?UTF-8?q?=E6=8A=A5=E9=94=99=E9=97=AE=E9=A2=98=20*=20fix=20=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=20=E4=BB=A3=E7=A0=81=E7=94=9F=E6=88=90=20=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E6=BA=90=E5=88=87=E6=8D=A2=E9=97=AE=E9=A2=98=20*=20up?= =?UTF-8?q?date=20anyline=208.7.2-20240726=20*=20fix=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=20=E4=BB=A3=E7=A0=81=E7=94=9F=E6=88=90=20=E8=A1=A8=E7=BB=93?= =?UTF-8?q?=E6=9E=84=E7=BC=93=E5=AD=98=E9=97=AE=E9=A2=98=20*=20update=20sn?= =?UTF-8?q?ailjob=201.1.0=20=3D>=201.1.1=20*=20fix=20=E4=BF=AE=E5=A4=8D=20?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E7=94=9F=E6=88=90=20=E8=A1=A8=E7=BB=93?= =?UTF-8?q?=E6=9E=84=E7=BC=93=E5=AD=98=E9=97=AE=E9=A2=98=20*=20update=20?= =?UTF-8?q?=E4=BC=98=E5=8C=96=20sse=20=E8=87=AA=E5=8A=A8=E8=A3=85=E9=85=8D?= =?UTF-8?q?=20*=20=E5=88=9D=E5=A7=8B=E5=8C=96=E6=B7=BB=E5=8A=A0warm-flow?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 16 +- .../src/main/resources/application.yml | 31 +- .../core/domain/dto/CompleteTaskDTO.java | 71 + .../common/core/domain/dto/FlowCopyDTO.java | 30 + .../core/domain/dto/StartProcessDTO.java | 45 + .../core/domain/dto/TaskAssigneeDTO.java | 101 + .../core/domain/event/ProcessDeleteEvent.java | 34 + .../core/domain/event/ProcessEvent.java | 13 +- .../core/domain/event/ProcessTaskEvent.java | 18 +- .../core/domain/model/TaskAssigneeBody.java | 56 + .../common/core/enums/BusinessStatusEnum.java | 79 +- .../core/service/TaskAssigneeService.java | 45 + .../common/core/service/WorkflowService.java | 76 +- .../common/satoken/utils/LoginHelper.java | 1 + .../service/GenTableServiceImpl.java | 2 +- .../dromara/system/mapper/SysDeptMapper.java | 12 + .../service/impl/SysPostServiceImpl.java | 1 + .../service/impl/SysRoleServiceImpl.java | 1 + .../impl/SysTaskAssigneeServiceImpl.java | 168 ++ .../service/impl/SysTenantServiceImpl.java | 12 +- .../resources/mapper/system/SysDeptMapper.xml | 11 + ruoyi-modules/ruoyi-workflow/pom.xml | 57 +- .../common/constant/FlowConstant.java | 113 +- .../workflow/common/enums/FormTypeEnum.java | 54 - .../common/enums/MessageTypeEnum.java | 20 +- .../common/enums/TaskAssigneeEnum.java | 109 + .../common/enums/TaskAssigneeType.java | 49 + .../workflow/common/enums/TaskStatusEnum.java | 32 +- .../workflow/config/WarmFlowConfig.java | 15 + .../controller/ActModelController.java | 148 -- .../ActProcessDefinitionController.java | 147 -- .../ActProcessInstanceController.java | 160 -- .../controller/ActTaskController.java | 295 --- .../controller/FlwCategoryController.java | 130 ++ .../controller/FlwDefinitionController.java | 194 ++ .../controller/FlwInstanceController.java | 155 ++ .../controller/FlwTaskController.java | 199 ++ .../controller/WfCategoryController.java | 106 - .../WfDefinitionConfigController.java | 79 - .../controller/WfFormManageController.java | 114 -- .../workflow/domain/ActHiProcinst.java | 152 -- .../workflow/domain/ActHiTaskinst.java | 193 -- .../{WfCategory.java => FlowCategory.java} | 42 +- .../workflow/domain/WfDefinitionConfig.java | 56 - .../dromara/workflow/domain/WfFormManage.java | 51 - .../dromara/workflow/domain/WfNodeConfig.java | 61 - .../workflow/domain/WfTaskBackNode.java | 61 - .../workflow/domain/bo/AddMultiBo.java | 40 - .../workflow/domain/bo/BackProcessBo.java | 28 +- .../workflow/domain/bo/CompleteTaskBo.java | 20 +- .../workflow/domain/bo/DelegateBo.java | 38 - .../workflow/domain/bo/DeleteMultiBo.java | 52 - ...rocessInvalidBo.java => FlowCancelBo.java} | 14 +- .../workflow/domain/bo/FlowCategoryBo.java | 47 + .../{vo/WfCopy.java => bo/FlowCopyBo.java} | 5 +- .../workflow/domain/bo/FlowInstanceBo.java | 55 + .../workflow/domain/bo/FlowInvalidBo.java | 31 + .../workflow/domain/bo/FlowTaskBo.java | 55 + ...minationBo.java => FlowTerminationBo.java} | 8 +- .../dromara/workflow/domain/bo/ModelBo.java | 66 - .../domain/bo/ProcessDefinitionBo.java | 34 - .../workflow/domain/bo/ProcessInstanceBo.java | 43 - .../workflow/domain/bo/StartProcessBo.java | 8 +- .../workflow/domain/bo/SysUserMultiBo.java | 39 - .../dromara/workflow/domain/bo/TaskBo.java | 33 - .../workflow/domain/bo/TaskOperationBo.java | 48 + .../workflow/domain/bo/TaskUrgingBo.java | 34 - .../workflow/domain/bo/TestLeaveBo.java | 1 - .../workflow/domain/bo/TransmitBo.java | 37 - .../workflow/domain/bo/WfCategoryBo.java | 54 - .../domain/bo/WfDefinitionConfigBo.java | 59 - .../workflow/domain/bo/WfFormManageBo.java | 53 - .../workflow/domain/bo/WfNodeConfigBo.java | 63 - .../workflow/domain/vo/ActHistoryInfoVo.java | 93 - .../workflow/domain/vo/FlowCategoryVo.java | 69 + .../workflow/domain/vo/FlowDefinitionVo.java | 104 + .../workflow/domain/vo/FlowHisTaskVo.java | 244 +++ .../workflow/domain/vo/FlowInstanceVo.java | 137 ++ .../workflow/domain/vo/FlowTaskVo.java | 176 ++ .../{VariableVo.java => FlowVariableVo.java} | 2 +- .../workflow/domain/vo/GraphicInfoVo.java | 47 - .../dromara/workflow/domain/vo/ModelVo.java | 48 - .../workflow/domain/vo/MultiInstanceVo.java | 33 - .../workflow/domain/vo/ParticipantVo.java | 43 - .../domain/vo/ProcessDefinitionVo.java | 70 - .../workflow/domain/vo/ProcessInstanceVo.java | 100 - .../dromara/workflow/domain/vo/TaskVo.java | 173 -- .../workflow/domain/vo/WfCategoryVo.java | 58 - .../domain/vo/WfDefinitionConfigVo.java | 70 - .../workflow/domain/vo/WfFormManageVo.java | 63 - .../workflow/domain/vo/WfNodeConfigVo.java | 75 - .../CustomDefaultProcessDiagramCanvas.java | 108 - .../CustomDefaultProcessDiagramGenerator.java | 1120 ----------- .../cmd/AddSequenceMultiInstanceCmd.java | 61 - .../workflow/flowable/cmd/AttachmentCmd.java | 66 - .../flowable/cmd/DeleteExecutionCmd.java | 36 - .../cmd/DeleteSequenceMultiInstanceCmd.java | 83 - .../cmd/ExecutionChildByExecutionIdCmd.java | 39 - .../flowable/cmd/UpdateBusinessStatusCmd.java | 37 - .../flowable/cmd/UpdateHiTaskInstCmd.java | 51 - .../flowable/config/FlowableConfig.java | 32 - .../config/GlobalFlowableListener.java | 139 -- .../handler/FlowProcessEventHandler.java | 50 - .../handler/TaskTimeoutJobHandler.java | 37 - .../handler/FlowProcessEventHandler.java | 77 + .../handler/WorkflowPermissionHandler.java | 71 + .../listener/WorkflowGlobalListener.java | 115 ++ .../workflow/mapper/ActHiProcinstMapper.java | 16 - .../workflow/mapper/ActHiTaskinstMapper.java | 16 - .../workflow/mapper/ActTaskMapper.java | 47 - .../workflow/mapper/FlwCategoryMapper.java | 60 + .../workflow/mapper/FlwInstanceMapper.java | 27 + .../workflow/mapper/FlwTaskMapper.java | 57 + .../workflow/mapper/WfCategoryMapper.java | 15 - .../mapper/WfDefinitionConfigMapper.java | 15 - .../workflow/mapper/WfFormManageMapper.java | 15 - .../workflow/mapper/WfNodeConfigMapper.java | 15 - .../workflow/mapper/WfTaskBackNodeMapper.java | 13 - .../service/IActHiProcinstService.java | 31 - .../service/IActHiTaskinstService.java | 11 - .../workflow/service/IActModelService.java | 83 - .../service/IActProcessDefinitionService.java | 91 - .../service/IActProcessInstanceService.java | 110 - .../workflow/service/IActTaskService.java | 161 -- .../workflow/service/IFlwCategoryService.java | 102 + .../service/IFlwDefinitionService.java | 79 + .../workflow/service/IFlwInstanceService.java | 159 ++ .../service/IFlwTaskAssigneeService.java | 22 + .../workflow/service/IFlwTaskService.java | 190 ++ .../workflow/service/ITestLeaveService.java | 3 +- .../workflow/service/IWfCategoryService.java | 51 - .../service/IWfDefinitionConfigService.java | 83 - .../service/IWfFormManageService.java | 81 - .../service/IWfNodeConfigService.java | 56 - .../service/IWfTaskBackNodeService.java | 65 - .../impl/ActHiProcinstServiceImpl.java | 51 - .../impl/ActHiTaskinstServiceImpl.java | 18 - .../service/impl/ActModelServiceImpl.java | 431 ---- .../impl/ActProcessDefinitionServiceImpl.java | 444 ----- .../impl/ActProcessInstanceServiceImpl.java | 691 ------- .../service/impl/ActTaskServiceImpl.java | 861 -------- .../impl/CategoryNameTranslationImpl.java | 31 + .../service/impl/FlwCategoryServiceImpl.java | 267 +++ .../impl/FlwDefinitionServiceImpl.java | 275 +++ .../service/impl/FlwInstanceServiceImpl.java | 455 +++++ .../impl/FlwTaskAssigneeServiceImpl.java | 158 ++ .../service/impl/FlwTaskServiceImpl.java | 669 +++++++ .../service/impl/TestLeaveServiceImpl.java | 58 +- .../service/impl/WfCategoryServiceImpl.java | 130 -- .../impl/WfDefinitionConfigServiceImpl.java | 117 -- .../service/impl/WfFormManageServiceImpl.java | 111 -- .../service/impl/WfNodeConfigServiceImpl.java | 75 - .../impl/WfTaskBackNodeServiceImpl.java | 144 -- .../service/impl/WorkflowServiceImpl.java | 132 +- .../dromara/workflow/utils/ModelUtils.java | 289 --- .../dromara/workflow/utils/QueryUtils.java | 169 -- .../dromara/workflow/utils/WorkflowUtils.java | 363 ++-- .../mapper/workflow/ActHiProcinstMapper.xml | 7 - .../mapper/workflow/ActHiTaskinstMapper.xml | 7 - .../mapper/workflow/ActTaskMapper.xml | 77 - .../mapper/workflow/FlwCategoryMapper.xml | 11 + .../mapper/workflow/FlwInstanceMapper.xml | 36 + .../mapper/workflow/FlwTaskMapper.xml | 115 ++ .../mapper/workflow/WfCategoryMapper.xml | 7 - .../workflow/WfDefinitionConfigMapper.xml | 7 - .../mapper/workflow/WfFormManageMapper.xml | 7 - .../mapper/workflow/WfNodeConfigMapper.xml | 7 - .../mapper/workflow/WfTaskBackNodeMapper.xml | 7 - script/bpmn/leave1.xml | 17 + script/bpmn/leave2.xml | 24 + script/bpmn/leave3.xml | 27 + script/bpmn/leave4.xml | 20 + script/bpmn/leave5.xml | 27 + script/bpmn/模型.zip | Bin 8543 -> 0 bytes script/sql/oracle/oracle_ry_workflow.sql | 603 +++--- script/sql/postgres/postgres_ry_workflow.sql | 658 +++--- script/sql/ry_workflow.sql | 403 ++-- script/sql/sqlserver/sqlserver_ry_vue_5.X.sql | 6 +- .../sql/sqlserver/sqlserver_ry_workflow.sql | 1770 ++++++++++++----- 179 files changed, 8359 insertions(+), 11404 deletions(-) create mode 100644 ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/CompleteTaskDTO.java create mode 100644 ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/FlowCopyDTO.java create mode 100644 ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/StartProcessDTO.java create mode 100644 ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/TaskAssigneeDTO.java create mode 100644 ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/event/ProcessDeleteEvent.java create mode 100644 ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/model/TaskAssigneeBody.java create mode 100644 ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/TaskAssigneeService.java create mode 100644 ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTaskAssigneeServiceImpl.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/FormTypeEnum.java create mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/TaskAssigneeEnum.java create mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/TaskAssigneeType.java create mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/config/WarmFlowConfig.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/ActModelController.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/ActProcessDefinitionController.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/ActProcessInstanceController.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/ActTaskController.java create mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwCategoryController.java create mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwDefinitionController.java create mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwInstanceController.java create mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwTaskController.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/WfCategoryController.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/WfDefinitionConfigController.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/WfFormManageController.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/ActHiProcinst.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/ActHiTaskinst.java rename ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/{WfCategory.java => FlowCategory.java} (56%) delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/WfDefinitionConfig.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/WfFormManage.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/WfNodeConfig.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/WfTaskBackNode.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/AddMultiBo.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/DelegateBo.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/DeleteMultiBo.java rename ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/{ProcessInvalidBo.java => FlowCancelBo.java} (56%) create mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowCategoryBo.java rename ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/{vo/WfCopy.java => bo/FlowCopyBo.java} (77%) create mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowInstanceBo.java create mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowInvalidBo.java create mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowTaskBo.java rename ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/{TerminationBo.java => FlowTerminationBo.java} (66%) delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/ModelBo.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/ProcessDefinitionBo.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/ProcessInstanceBo.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/SysUserMultiBo.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/TaskBo.java create mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/TaskOperationBo.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/TaskUrgingBo.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/TransmitBo.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/WfCategoryBo.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/WfDefinitionConfigBo.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/WfFormManageBo.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/WfNodeConfigBo.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/ActHistoryInfoVo.java create mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowCategoryVo.java create mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowDefinitionVo.java create mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowHisTaskVo.java create mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowInstanceVo.java create mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowTaskVo.java rename ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/{VariableVo.java => FlowVariableVo.java} (86%) delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/GraphicInfoVo.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/ModelVo.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/MultiInstanceVo.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/ParticipantVo.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/ProcessDefinitionVo.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/ProcessInstanceVo.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/TaskVo.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/WfCategoryVo.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/WfDefinitionConfigVo.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/WfFormManageVo.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/WfNodeConfigVo.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/CustomDefaultProcessDiagramCanvas.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/CustomDefaultProcessDiagramGenerator.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/AddSequenceMultiInstanceCmd.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/AttachmentCmd.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/DeleteExecutionCmd.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/DeleteSequenceMultiInstanceCmd.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/ExecutionChildByExecutionIdCmd.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/UpdateBusinessStatusCmd.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/UpdateHiTaskInstCmd.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/config/FlowableConfig.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/config/GlobalFlowableListener.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/handler/FlowProcessEventHandler.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/handler/TaskTimeoutJobHandler.java create mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/handler/FlowProcessEventHandler.java create mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/handler/WorkflowPermissionHandler.java create mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/listener/WorkflowGlobalListener.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/ActHiProcinstMapper.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/ActHiTaskinstMapper.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/ActTaskMapper.java create mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/FlwCategoryMapper.java create mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/FlwInstanceMapper.java create mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/FlwTaskMapper.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/WfCategoryMapper.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/WfDefinitionConfigMapper.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/WfFormManageMapper.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/WfNodeConfigMapper.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/WfTaskBackNodeMapper.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActHiProcinstService.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActHiTaskinstService.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActModelService.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActProcessDefinitionService.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActProcessInstanceService.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActTaskService.java create mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwCategoryService.java create mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwDefinitionService.java create mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwInstanceService.java create mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwTaskAssigneeService.java create mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwTaskService.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IWfCategoryService.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IWfDefinitionConfigService.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IWfFormManageService.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IWfNodeConfigService.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IWfTaskBackNodeService.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActHiProcinstServiceImpl.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActHiTaskinstServiceImpl.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActModelServiceImpl.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActProcessDefinitionServiceImpl.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActProcessInstanceServiceImpl.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActTaskServiceImpl.java create mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/CategoryNameTranslationImpl.java create mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwCategoryServiceImpl.java create mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwDefinitionServiceImpl.java create mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwInstanceServiceImpl.java create mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskAssigneeServiceImpl.java create mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskServiceImpl.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WfCategoryServiceImpl.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WfDefinitionConfigServiceImpl.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WfFormManageServiceImpl.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WfNodeConfigServiceImpl.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WfTaskBackNodeServiceImpl.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/utils/ModelUtils.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/utils/QueryUtils.java delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/ActHiProcinstMapper.xml delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/ActHiTaskinstMapper.xml delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/ActTaskMapper.xml create mode 100644 ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/FlwCategoryMapper.xml create mode 100644 ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/FlwInstanceMapper.xml create mode 100644 ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/FlwTaskMapper.xml delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/WfCategoryMapper.xml delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/WfDefinitionConfigMapper.xml delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/WfFormManageMapper.xml delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/WfNodeConfigMapper.xml delete mode 100644 ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/WfTaskBackNodeMapper.xml create mode 100644 script/bpmn/leave1.xml create mode 100644 script/bpmn/leave2.xml create mode 100644 script/bpmn/leave3.xml create mode 100644 script/bpmn/leave4.xml create mode 100644 script/bpmn/leave5.xml delete mode 100644 script/bpmn/模型.zip diff --git a/pom.xml b/pom.xml index 63b9d0226..2993af438 100644 --- a/pom.xml +++ b/pom.xml @@ -50,7 +50,7 @@ 8.7.2-20241022 - 7.0.1 + 1.3.7 3.2.2 @@ -118,12 +118,16 @@ import + - org.flowable - flowable-bom - ${flowable.version} - pom - import + org.dromara.warm + warm-flow-mybatis-plus-sb3-starter + ${warm-flow.version} + + + org.dromara.warm + warm-flow-plugin-ui-sb-web + ${warm-flow.version} diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml index c42bb7f26..dbe16888d 100644 --- a/ruoyi-admin/src/main/resources/application.yml +++ b/ruoyi-admin/src/main/resources/application.yml @@ -119,6 +119,7 @@ security: - /error - /*/api-docs - /*/api-docs/** + - /warm-flow-ui/token-name # 多租户配置 tenant: @@ -227,8 +228,7 @@ xss: # 排除链接(多个用逗号分隔) excludeUrls: - /system/notice - - /workflow/model/save - - /workflow/model/editModelXml + - /warm-flow/save-xml # 全局线程池相关配置 # 如使用JDK21请直接使用虚拟线程 不要开启此配置 @@ -273,24 +273,11 @@ websocket: # 设置访问源地址 allowedOrigins: '*' ---- #flowable配置 -flowable: - # 开关 用于启动/停用工作流 +--- # warm-flow工作流配置 +warm-flow: + # 是否开启工作流,默认true enabled: true - process.enabled: ${flowable.enabled} - eventregistry.enabled: ${flowable.enabled} - async-executor-activate: false #关闭定时任务JOB - # 将databaseSchemaUpdate设置为true。当Flowable发现库与数据库表结构不一致时,会自动将数据库表结构升级至新版本。 - database-schema-update: true - activity-font-name: 宋体 - label-font-name: 宋体 - annotation-font-name: 宋体 - # 关闭各个模块生成表,目前只使用工作流基础表 - idm: - enabled: false - cmmn: - enabled: false - dmn: - enabled: false - app: - enabled: false + # 是否开启设计器ui + ui: true + # 默认Authorization,如果有多个token,用逗号分隔 + token-name: ${sa-token.token-name},clientid diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/CompleteTaskDTO.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/CompleteTaskDTO.java new file mode 100644 index 000000000..2e63f8aca --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/CompleteTaskDTO.java @@ -0,0 +1,71 @@ +package org.dromara.common.core.domain.dto; + +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * 办理任务请求对象 + * + * @author may + */ +@Data +public class CompleteTaskDTO implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 任务id + */ + private Long taskId; + + /** + * 附件id + */ + private String fileId; + + /** + * 抄送人员 + */ + private List flowCopyList; + + /** + * 消息类型 + */ + private List messageType; + + /** + * 办理意见 + */ + private String message; + + /** + * 消息通知 + */ + private String notice; + + /** + * 流程变量 + */ + private Map variables; + + /** + * 扩展变量(此处为逗号分隔的ossId) + */ + private String ext; + + public Map getVariables() { + if (variables == null) { + return new HashMap<>(16); + } + variables.entrySet().removeIf(entry -> Objects.isNull(entry.getValue())); + return variables; + } + +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/FlowCopyDTO.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/FlowCopyDTO.java new file mode 100644 index 000000000..2f20b21f7 --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/FlowCopyDTO.java @@ -0,0 +1,30 @@ +package org.dromara.common.core.domain.dto; + +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; + + +/** + * 抄送 + * + * @author may + */ +@Data +public class FlowCopyDTO implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 用户id + */ + private Long userId; + + /** + * 用户名称 + */ + private String userName; + +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/StartProcessDTO.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/StartProcessDTO.java new file mode 100644 index 000000000..3934ada55 --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/StartProcessDTO.java @@ -0,0 +1,45 @@ +package org.dromara.common.core.domain.dto; + + +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +/** + * 启动流程对象 + * + * @author may + */ +@Data +public class StartProcessDTO implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 业务唯一值id + */ + private String businessId; + + /** + * 流程定义编码 + */ + private String flowCode; + + /** + * 流程变量,前端会提交一个元素{'entity': {业务详情数据对象}} + */ + private Map variables; + + public Map getVariables() { + if (variables == null) { + return new HashMap<>(16); + } + variables.entrySet().removeIf(entry -> Objects.isNull(entry.getValue())); + return variables; + } +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/TaskAssigneeDTO.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/TaskAssigneeDTO.java new file mode 100644 index 000000000..85893e1dc --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/dto/TaskAssigneeDTO.java @@ -0,0 +1,101 @@ +package org.dromara.common.core.domain.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serial; +import java.io.Serializable; +import java.util.Date; +import java.util.List; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * 任务受让人 + * + * @author AprilWind + */ +@Data +@NoArgsConstructor +public class TaskAssigneeDTO implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 总大小 + */ + private Long total = 0L; + + /** + * + */ + private List list; + + public TaskAssigneeDTO(Long total, List list) { + this.total = total; + this.list = list; + } + + /** + * 将源列表转换为 TaskHandler 列表 + * + * @param 通用类型 + * @param sourceList 待转换的源列表 + * @param storageId 提取 storageId 的函数 + * @param handlerCode 提取 handlerCode 的函数 + * @param handlerName 提取 handlerName 的函数 + * @param groupName 提取 groupName 的函数 + * @param createTimeMapper 提取 createTime 的函数 + * @return 转换后的 TaskHandler 列表 + */ + public static List convertToHandlerList( + List sourceList, + Function storageId, + Function handlerCode, + Function handlerName, + Function groupName, + Function createTimeMapper) { + return sourceList.stream() + .map(item -> new TaskHandler( + String.valueOf(storageId.apply(item)), + handlerCode.apply(item), + handlerName.apply(item), + groupName != null ? String.valueOf(groupName.apply(item)) : null, + createTimeMapper.apply(item) + )).collect(Collectors.toList()); + } + + @Data + @NoArgsConstructor + @AllArgsConstructor + public static class TaskHandler { + + /** + * 主键 + */ + private String storageId; + + /** + * 权限编码 + */ + private String handlerCode; + + /** + * 权限名称 + */ + private String handlerName; + + /** + * 权限分组 + */ + private String groupName; + + /** + * 创建时间 + */ + private Date createTime; + } + +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/event/ProcessDeleteEvent.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/event/ProcessDeleteEvent.java new file mode 100644 index 000000000..d570c314e --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/event/ProcessDeleteEvent.java @@ -0,0 +1,34 @@ +package org.dromara.common.core.domain.event; + +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; + +/** + * 删除流程监听 + * + * @author AprilWind + */ +@Data +public class ProcessDeleteEvent implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 流程定义编码 + */ + private String flowCode; + + /** + * 业务id + */ + private String businessId; + +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/event/ProcessEvent.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/event/ProcessEvent.java index 61c7efc39..21bfbefa4 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/event/ProcessEvent.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/event/ProcessEvent.java @@ -10,7 +10,6 @@ import java.io.Serializable; * * @author may */ - @Data public class ProcessEvent implements Serializable { @@ -18,14 +17,19 @@ public class ProcessEvent implements Serializable { private static final long serialVersionUID = 1L; /** - * 流程定义key + * 租户ID */ - private String key; + private String tenantId; + + /** + * 流程定义编码 + */ + private String flowCode; /** * 业务id */ - private String businessKey; + private String businessId; /** * 状态 @@ -37,5 +41,4 @@ public class ProcessEvent implements Serializable { */ private boolean submit; - } diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/event/ProcessTaskEvent.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/event/ProcessTaskEvent.java index 019ca823b..33bc6e5a6 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/event/ProcessTaskEvent.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/event/ProcessTaskEvent.java @@ -10,7 +10,6 @@ import java.io.Serializable; * * @author may */ - @Data public class ProcessTaskEvent implements Serializable { @@ -18,23 +17,28 @@ public class ProcessTaskEvent implements Serializable { private static final long serialVersionUID = 1L; /** - * 流程定义key + * 租户ID */ - private String key; + private String tenantId; /** - * 审批节点key + * 流程定义编码 */ - private String taskDefinitionKey; + private String flowCode; + + /** + * 审批节点编码 + */ + private String nodeCode; /** * 任务id */ - private String taskId; + private Long taskId; /** * 业务id */ - private String businessKey; + private String businessId; } diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/model/TaskAssigneeBody.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/model/TaskAssigneeBody.java new file mode 100644 index 000000000..0cbed2f18 --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/model/TaskAssigneeBody.java @@ -0,0 +1,56 @@ +package org.dromara.common.core.domain.model; + +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serial; +import java.io.Serializable; + +/** + * 任务受让人 + * + * @author AprilWind + */ +@Data +@NoArgsConstructor +public class TaskAssigneeBody implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 权限编码 + */ + private String handlerCode; + + /** + * 权限名称 + */ + private String handlerName; + + /** + * 权限分组 + */ + private String groupId; + + /** + * 开始时间 + */ + private String beginTime; + + /** + * 结束时间 + */ + private String endTime; + + /** + * 当前页 + */ + private Integer pageNum = 1; + + /** + * 每页显示条数 + */ + private Integer pageSize = 10; + +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/enums/BusinessStatusEnum.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/enums/BusinessStatusEnum.java index 0af943a78..c1660ee93 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/enums/BusinessStatusEnum.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/enums/BusinessStatusEnum.java @@ -7,6 +7,10 @@ import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.utils.StringUtils; import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; /** * 业务状态枚举 @@ -16,30 +20,37 @@ import java.util.Arrays; @Getter @AllArgsConstructor public enum BusinessStatusEnum { + /** * 已撤销 */ CANCEL("cancel", "已撤销"), + /** * 草稿 */ DRAFT("draft", "草稿"), + /** * 待审核 */ WAITING("waiting", "待审核"), + /** * 已完成 */ FINISH("finish", "已完成"), + /** * 已作废 */ INVALID("invalid", "已作废"), + /** * 已退回 */ BACK("back", "已退回"), + /** * 已终止 */ @@ -55,20 +66,72 @@ public enum BusinessStatusEnum { */ private final String desc; + private static final Map STATUS_MAP = Arrays.stream(BusinessStatusEnum.values()) + .collect(Collectors.toConcurrentMap(BusinessStatusEnum::getStatus, Function.identity())); + /** - * 获取业务状态 + * 根据状态获取对应的 BusinessStatusEnum 枚举 * - * @param status 状态 + * @param status 业务状态码 + * @return 对应的 BusinessStatusEnum 枚举,如果找不到则返回 null + */ + public static BusinessStatusEnum getByStatus(String status) { + // 使用 STATUS_MAP 获取对应的枚举,若找不到则返回 null + return STATUS_MAP.get(status); + } + + /** + * 根据状态获取对应的业务状态描述信息 + * + * @param status 业务状态码 + * @return 返回业务状态描述,若状态码为空或未找到对应的枚举,返回空字符串 */ public static String findByStatus(String status) { if (StringUtils.isBlank(status)) { return StrUtil.EMPTY; } - return Arrays.stream(BusinessStatusEnum.values()) - .filter(statusEnum -> statusEnum.getStatus().equals(status)) - .findFirst() - .map(BusinessStatusEnum::getDesc) - .orElse(StrUtil.EMPTY); + BusinessStatusEnum statusEnum = STATUS_MAP.get(status); + return (statusEnum != null) ? statusEnum.getDesc() : StrUtil.EMPTY; + } + + /** + * 判断是否为指定的状态之一:草稿、已撤销或已退回 + * + * @param status 要检查的状态 + * @return 如果状态为草稿、已撤销或已退回之一,则返回 true;否则返回 false + */ + public static boolean isDraftOrCancelOrBack(String status) { + return DRAFT.status.equals(status) || CANCEL.status.equals(status) || BACK.status.equals(status); + } + + /** + * 判断是否为撤销,退回,作废,终止 + * + * @param status status + * @return 结果 + */ + public static boolean initialState(String status) { + return CANCEL.status.equals(status) || BACK.status.equals(status) || INVALID.status.equals(status) || TERMINATION.status.equals(status); + } + + /** + * 获取运行中的实例状态列表 + * + * @return 包含运行中实例状态的不可变列表 + * (包含 DRAFT、WAITING、BACK 和 CANCEL 状态) + */ + public static List runningStatus() { + return Arrays.asList(DRAFT.status, WAITING.status, BACK.status, CANCEL.status); + } + + /** + * 获取结束实例的状态列表 + * + * @return 包含结束实例状态的不可变列表 + * (包含 FINISH、INVALID 和 TERMINATION 状态) + */ + public static List finishStatus() { + return Arrays.asList(FINISH.status, INVALID.status, TERMINATION.status); } /** @@ -148,5 +211,5 @@ public enum BusinessStatusEnum { throw new ServiceException("流程状态为空!"); } } -} +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/TaskAssigneeService.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/TaskAssigneeService.java new file mode 100644 index 000000000..9af669111 --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/TaskAssigneeService.java @@ -0,0 +1,45 @@ +package org.dromara.common.core.service; + +import org.dromara.common.core.domain.dto.TaskAssigneeDTO; +import org.dromara.common.core.domain.model.TaskAssigneeBody; + +/** + * 工作流设计器获取任务执行人 + * + * @author Lion Li + */ +public interface TaskAssigneeService { + + /** + * 查询角色并返回任务指派的列表,支持分页 + * + * @param taskQuery 查询条件 + * @return 办理人 + */ + TaskAssigneeDTO selectRolesByTaskAssigneeList(TaskAssigneeBody taskQuery); + + /** + * 查询岗位并返回任务指派的列表,支持分页 + * + * @param taskQuery 查询条件 + * @return 办理人 + */ + TaskAssigneeDTO selectPostsByTaskAssigneeList(TaskAssigneeBody taskQuery); + + /** + * 查询部门并返回任务指派的列表,支持分页 + * + * @param taskQuery 查询条件 + * @return 办理人 + */ + TaskAssigneeDTO selectDeptsByTaskAssigneeList(TaskAssigneeBody taskQuery); + + /** + * 查询用户并返回任务指派的列表,支持分页 + * + * @param taskQuery 查询条件 + * @return 办理人 + */ + TaskAssigneeDTO selectUsersByTaskAssigneeList(TaskAssigneeBody taskQuery); + +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/WorkflowService.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/WorkflowService.java index 4e556c9cb..565362e56 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/WorkflowService.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/WorkflowService.java @@ -1,5 +1,8 @@ package org.dromara.common.core.service; +import org.dromara.common.core.domain.dto.CompleteTaskDTO; +import org.dromara.common.core.domain.dto.StartProcessDTO; + import java.util.List; import java.util.Map; @@ -13,64 +16,63 @@ public interface WorkflowService { /** * 运行中的实例 删除程实例,删除历史记录,删除业务与流程关联信息 * - * @param businessKeys 业务id + * @param businessIds 业务id * @return 结果 */ - boolean deleteRunAndHisInstance(List businessKeys); + boolean deleteInstance(List businessIds); /** * 获取当前流程状态 * * @param taskId 任务id + * @return 状态 */ - String getBusinessStatusByTaskId(String taskId); + String getBusinessStatusByTaskId(Long taskId); /** * 获取当前流程状态 * - * @param businessKey 业务id + * @param businessId 业务id + * @return 状态 */ - String getBusinessStatus(String businessKey); + String getBusinessStatus(String businessId); /** - * 设置流程变量(全局变量) + * 设置流程变量 * - * @param taskId 任务id - * @param variableName 变量名称 - * @param value 变量值 + * @param instanceId 流程实例id + * @param variable 流程变量 */ - void setVariable(String taskId, String variableName, Object value); - - /** - * 设置流程变量(全局变量) - * - * @param taskId 任务id - * @param variables 流程变量 - */ - void setVariables(String taskId, Map variables); - - /** - * 设置流程变量(本地变量,非全局变量) - * - * @param taskId 任务id - * @param variableName 变量名称 - * @param value 变量值 - */ - void setVariableLocal(String taskId, String variableName, Object value); - - /** - * 设置流程变量(本地变量,非全局变量) - * - * @param taskId 任务id - * @param variables 流程变量 - */ - void setVariablesLocal(String taskId, Map variables); + void setVariable(Long instanceId, Map variable); /** * 按照业务id查询流程实例id * - * @param businessKey 业务id + * @param businessId 业务id * @return 结果 */ - String getInstanceIdByBusinessKey(String businessKey); + Long getInstanceIdByBusinessId(String businessId); + + /** + * 新增租户流程定义 + * + * @param tenantId 租户id + */ + void syncDef(String tenantId); + + /** + * 启动流程 + * + * @param startProcess 参数 + * @return 结果 + */ + Map startWorkFlow(StartProcessDTO startProcess); + + /** + * 办理任务 + * + * @param completeTask 参数 + * @return 结果 + */ + boolean completeTask(CompleteTaskDTO completeTask); } diff --git a/ruoyi-common/ruoyi-common-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 19557e131..e2c92366f 100644 --- a/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/utils/LoginHelper.java +++ b/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/utils/LoginHelper.java @@ -15,6 +15,7 @@ import org.dromara.common.core.enums.UserType; import java.util.Set; + /** * 登录鉴权助手 *

diff --git a/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java b/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java index 37299804a..6b9e60617 100644 --- a/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java +++ b/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java @@ -63,7 +63,7 @@ public class GenTableServiceImpl implements IGenTableService { private final GenTableColumnMapper genTableColumnMapper; private final IdentifierGenerator identifierGenerator; - private static final String[] TABLE_IGNORE = new String[]{"sj_", "act_", "flw_", "gen_"}; + private static final String[] TABLE_IGNORE = new String[]{"sj_", "flow_", "gen_"}; /** * 查询业务字段列表 diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysDeptMapper.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysDeptMapper.java index 0f2c90667..b69624cf0 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysDeptMapper.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysDeptMapper.java @@ -3,6 +3,7 @@ package org.dromara.system.mapper; import com.baomidou.mybatisplus.core.conditions.Wrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Constants; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import org.apache.ibatis.annotations.Param; import org.dromara.common.mybatis.annotation.DataColumn; import org.dromara.common.mybatis.annotation.DataPermission; @@ -31,6 +32,17 @@ public interface SysDeptMapper extends BaseMapperPlus { }) List selectDeptList(@Param(Constants.WRAPPER) Wrapper queryWrapper); + /** + * 分页查询部门管理数据 + * + * @param queryWrapper 查询条件 + * @return 部门信息集合 + */ + @DataPermission({ + @DataColumn(key = "deptName", value = "dept_id"), + }) + Page selectPageDeptList(@Param("page") Page page, @Param(Constants.WRAPPER) Wrapper queryWrapper); + /** * 统计指定部门ID的部门数量 * 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 72f1a5e31..5888985a7 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysPostServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysPostServiceImpl.java @@ -245,4 +245,5 @@ public class SysPostServiceImpl implements ISysPostService, PostService { SysPost post = MapstructUtils.convert(bo, SysPost.class); return baseMapper.updateById(post); } + } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysRoleServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysRoleServiceImpl.java index 4c007358e..0a2e485f6 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysRoleServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysRoleServiceImpl.java @@ -548,4 +548,5 @@ public class SysRoleServiceImpl implements ISysRoleService, RoleService { } }); } + } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTaskAssigneeServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTaskAssigneeServiceImpl.java new file mode 100644 index 000000000..23dd0520c --- /dev/null +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTaskAssigneeServiceImpl.java @@ -0,0 +1,168 @@ +package org.dromara.system.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import lombok.RequiredArgsConstructor; +import org.dromara.common.core.constant.SystemConstants; +import org.dromara.common.core.domain.dto.TaskAssigneeDTO; +import org.dromara.common.core.domain.model.TaskAssigneeBody; +import org.dromara.common.core.service.TaskAssigneeService; +import org.dromara.common.core.utils.StreamUtils; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.mybatis.core.page.PageQuery; +import org.dromara.system.domain.SysDept; +import org.dromara.system.domain.SysPost; +import org.dromara.system.domain.SysRole; +import org.dromara.system.domain.SysUser; +import org.dromara.system.domain.vo.SysDeptVo; +import org.dromara.system.domain.vo.SysPostVo; +import org.dromara.system.domain.vo.SysRoleVo; +import org.dromara.system.domain.vo.SysUserVo; +import org.dromara.system.mapper.SysDeptMapper; +import org.dromara.system.mapper.SysPostMapper; +import org.dromara.system.mapper.SysRoleMapper; +import org.dromara.system.mapper.SysUserMapper; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 工作流设计器获取任务执行人 + * + * @author Lion Li + */ +@RequiredArgsConstructor +@Service +public class SysTaskAssigneeServiceImpl implements TaskAssigneeService { + + private final SysPostMapper postMapper; + private final SysDeptMapper deptMapper; + private final SysUserMapper userMapper; + private final SysRoleMapper roleMapper; + + /** + * 查询角色并返回任务指派的列表,支持分页 + * + * @param taskQuery 查询条件 + * @return 办理人 + */ + @Override + public TaskAssigneeDTO selectRolesByTaskAssigneeList(TaskAssigneeBody taskQuery) { + PageQuery pageQuery = new PageQuery(taskQuery.getPageSize(), taskQuery.getPageNum()); + QueryWrapper wrapper = Wrappers.query(); + wrapper.eq("r.del_flag", SystemConstants.NORMAL) + .like(StringUtils.isNotBlank(taskQuery.getHandlerCode()), "r.role_name", taskQuery.getHandlerCode()) + .like(StringUtils.isNotBlank(taskQuery.getHandlerName()), "r.role_key", taskQuery.getHandlerName()) + .between(StringUtils.isNotBlank(taskQuery.getBeginTime()) && StringUtils.isNotBlank(taskQuery.getEndTime()), + "r.create_time", taskQuery.getBeginTime(), taskQuery.getEndTime()) + .orderByAsc("r.role_sort").orderByAsc("r.create_time"); + Page page = roleMapper.selectPageRoleList(pageQuery.build(), wrapper); + // 使用封装的字段映射方法进行转换 + List handlers = TaskAssigneeDTO.convertToHandlerList(page.getRecords(), + SysRoleVo::getRoleId, SysRoleVo::getRoleKey, SysRoleVo::getRoleName, null, SysRoleVo::getCreateTime); + return new TaskAssigneeDTO(page.getTotal(), handlers); + } + + /** + * 查询岗位并返回任务指派的列表,支持分页 + * + * @param taskQuery 查询条件 + * @return 办理人 + */ + @Override + public TaskAssigneeDTO selectPostsByTaskAssigneeList(TaskAssigneeBody taskQuery) { + PageQuery pageQuery = new PageQuery(taskQuery.getPageSize(), taskQuery.getPageNum()); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery() + .like(StringUtils.isNotBlank(taskQuery.getHandlerCode()), SysPost::getPostCategory, taskQuery.getHandlerCode()) + .like(StringUtils.isNotBlank(taskQuery.getHandlerName()), SysPost::getPostName, taskQuery.getHandlerName()) + .between(StringUtils.isNotBlank(taskQuery.getBeginTime()) && StringUtils.isNotBlank(taskQuery.getEndTime()), + SysPost::getCreateTime, taskQuery.getBeginTime(), taskQuery.getEndTime()); + if (StringUtils.isNotBlank(taskQuery.getGroupId())) { + Long belongDeptId = Long.valueOf(taskQuery.getGroupId()); + wrapper.and(x -> { + List deptList = deptMapper.selectListByParentId(belongDeptId); + List deptIds = StreamUtils.toList(deptList, SysDept::getDeptId); + deptIds.add(belongDeptId); + x.in(SysPost::getDeptId, deptIds); + }); + } + Page page = postMapper.selectPagePostList(pageQuery.build(), wrapper); + // 使用封装的字段映射方法进行转换 + List handlers = TaskAssigneeDTO.convertToHandlerList(page.getRecords(), + SysPostVo::getPostId, SysPostVo::getPostCategory, SysPostVo::getPostName, SysPostVo::getDeptId, SysPostVo::getCreateTime); + return new TaskAssigneeDTO(page.getTotal(), handlers); + } + + /** + * 查询部门并返回任务指派的列表,支持分页 + * + * @param taskQuery 查询条件 + * @return 办理人 + */ + @Override + public TaskAssigneeDTO selectDeptsByTaskAssigneeList(TaskAssigneeBody taskQuery) { + PageQuery pageQuery = new PageQuery(taskQuery.getPageSize(), taskQuery.getPageNum()); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery() + .eq(SysDept::getDelFlag, SystemConstants.NORMAL) + .like(StringUtils.isNotBlank(taskQuery.getHandlerCode()), SysDept::getDeptCategory, taskQuery.getHandlerCode()) + .like(StringUtils.isNotBlank(taskQuery.getHandlerName()), SysDept::getDeptName, taskQuery.getHandlerName()) + .between(StringUtils.isNotBlank(taskQuery.getBeginTime()) && StringUtils.isNotBlank(taskQuery.getEndTime()), + SysDept::getCreateTime, taskQuery.getBeginTime(), taskQuery.getEndTime()) + .orderByAsc(SysDept::getAncestors) + .orderByAsc(SysDept::getParentId) + .orderByAsc(SysDept::getOrderNum) + .orderByAsc(SysDept::getDeptId); + if (StringUtils.isNotBlank(taskQuery.getGroupId())) { + //部门树搜索 + wrapper.and(x -> { + Long parentId = Long.valueOf(taskQuery.getGroupId()); + List deptList = deptMapper.selectListByParentId(parentId); + List deptIds = StreamUtils.toList(deptList, SysDept::getDeptId); + deptIds.add(parentId); + x.in(SysDept::getDeptId, deptIds); + }); + } + Page page = deptMapper.selectPageDeptList(pageQuery.build(), wrapper); + // 使用封装的字段映射方法进行转换 + List handlers = TaskAssigneeDTO.convertToHandlerList(page.getRecords(), + SysDeptVo::getDeptId, SysDeptVo::getDeptCategory, SysDeptVo::getDeptName, SysDeptVo::getParentId, SysDeptVo::getCreateTime); + return new TaskAssigneeDTO(page.getTotal(), handlers); + } + + + /** + * 查询用户并返回任务指派的列表,支持分页 + * + * @param taskQuery 查询条件 + * @return 办理人 + */ + @Override + public TaskAssigneeDTO selectUsersByTaskAssigneeList(TaskAssigneeBody taskQuery) { + PageQuery pageQuery = new PageQuery(taskQuery.getPageSize(), taskQuery.getPageNum()); + QueryWrapper wrapper = Wrappers.query(); + wrapper.eq("u.del_flag", SystemConstants.NORMAL) + .like(StringUtils.isNotBlank(taskQuery.getHandlerCode()), "u.user_name", taskQuery.getHandlerCode()) + .like(StringUtils.isNotBlank(taskQuery.getHandlerName()), "u.nick_name", taskQuery.getHandlerName()) + .between(taskQuery.getBeginTime() != null && taskQuery.getEndTime() != null, + "u.create_time", taskQuery.getBeginTime(), taskQuery.getEndTime()) + .orderByAsc("u.user_id"); + if (StringUtils.isNotBlank(taskQuery.getGroupId())) { + //部门树搜索 + wrapper.and(x -> { + Long parentId = Long.valueOf(taskQuery.getGroupId()); + List deptList = deptMapper.selectListByParentId(parentId); + List deptIds = StreamUtils.toList(deptList, SysDept::getDeptId); + deptIds.add(parentId); + x.in("u.dept_id", deptIds); + }); + } + Page page = userMapper.selectPageUserList(pageQuery.build(), wrapper); + // 使用封装的字段映射方法进行转换 + List handlers = TaskAssigneeDTO.convertToHandlerList(page.getRecords(), + SysUserVo::getUserId, SysUserVo::getUserName, SysUserVo::getNickName, SysUserVo::getDeptId, SysUserVo::getCreateTime); + return new TaskAssigneeDTO(page.getTotal(), handlers); + } + +} diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTenantServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTenantServiceImpl.java index 7bfe989b9..856dabba5 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 @@ -15,6 +15,7 @@ import org.dromara.common.core.constant.Constants; import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.core.constant.TenantConstants; import org.dromara.common.core.exception.ServiceException; +import org.dromara.common.core.service.WorkflowService; import org.dromara.common.core.utils.MapstructUtils; import org.dromara.common.core.utils.SpringUtils; import org.dromara.common.core.utils.StreamUtils; @@ -56,6 +57,7 @@ public class SysTenantServiceImpl implements ISysTenantService { private final SysDictTypeMapper dictTypeMapper; private final SysDictDataMapper dictDataMapper; private final SysConfigMapper configMapper; + private final WorkflowService workflowService; /** * 查询租户 @@ -121,7 +123,9 @@ public class SysTenantServiceImpl implements ISysTenantService { // 获取所有租户编号 List tenantIds = baseMapper.selectObjs( - new LambdaQueryWrapper().select(SysTenant::getTenantId), x -> {return Convert.toStr(x);}); + new LambdaQueryWrapper().select(SysTenant::getTenantId), x -> { + return Convert.toStr(x); + }); String tenantId = generateTenantId(tenantIds); add.setTenantId(tenantId); boolean flag = baseMapper.insert(add) > 0; @@ -191,6 +195,8 @@ public class SysTenantServiceImpl implements ISysTenantService { config.setTenantId(tenantId); } configMapper.insertBatch(sysConfigList); + //新增租户流程定义 + workflowService.syncDef(tenantId); return true; } @@ -399,7 +405,9 @@ public class SysTenantServiceImpl implements ISysTenantService { // 获取所有租户编号 List tenantIds = baseMapper.selectObjs( new LambdaQueryWrapper().select(SysTenant::getTenantId) - .eq(SysTenant::getStatus, SystemConstants.NORMAL), x -> {return Convert.toStr(x);}); + .eq(SysTenant::getStatus, SystemConstants.NORMAL), x -> { + return Convert.toStr(x); + }); List saveTypeList = new ArrayList<>(); List saveDataList = new ArrayList<>(); Set set = new HashSet<>(); diff --git a/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml b/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml index 6ad866f29..9057a0e22 100644 --- a/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml +++ b/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml @@ -18,6 +18,17 @@ from sys_dept ${ew.getCustomSqlSegment} + + diff --git a/ruoyi-modules/ruoyi-workflow/pom.xml b/ruoyi-modules/ruoyi-workflow/pom.xml index e55839ef7..d195fafa3 100644 --- a/ruoyi-modules/ruoyi-workflow/pom.xml +++ b/ruoyi-modules/ruoyi-workflow/pom.xml @@ -18,57 +18,14 @@ - - org.flowable - flowable-spring-boot-autoconfigure - - - org.flowable - flowable-spring-security - - - - - - org.flowable - flowable-spring-configurator - - - - org.flowable - flowable-spring-boot-starter-actuator - - - - - org.flowable - flowable-image-generator - - - - - org.flowable - flowable-json-converter - 6.8.0 - - - - - org.apache.xmlgraphics - batik-all - 1.17 - - - xalan - xalan - - + org.dromara + ruoyi-common-sse org.dromara - ruoyi-common-websocket + ruoyi-common-doc @@ -113,6 +70,14 @@ org.dromara ruoyi-common-security + + org.dromara.warm + warm-flow-mybatis-plus-sb3-starter + + + org.dromara.warm + warm-flow-plugin-ui-sb-web + diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/constant/FlowConstant.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/constant/FlowConstant.java index c3fcafa87..1b10eb8ea 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/constant/FlowConstant.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/constant/FlowConstant.java @@ -8,83 +8,6 @@ package org.dromara.workflow.common.constant; */ public interface FlowConstant { - String MESSAGE_CURRENT_TASK_IS_NULL = "当前任务不存在或你不是任务办理人!"; - - String MESSAGE_SUSPENDED = "当前任务已挂起不可审批!"; - - /** - * 连线 - */ - String SEQUENCE_FLOW = "sequenceFlow"; - - /** - * 并行网关 - */ - String PARALLEL_GATEWAY = "parallelGateway"; - - /** - * 排它网关 - */ - String EXCLUSIVE_GATEWAY = "exclusiveGateway"; - - /** - * 包含网关 - */ - String INCLUSIVE_GATEWAY = "inclusiveGateway"; - - /** - * 结束节点 - */ - String END_EVENT = "endEvent"; - - - /** - * 流程委派标识 - */ - String PENDING = "PENDING"; - - /** - * 候选人标识 - */ - String CANDIDATE = "candidate"; - - /** - * 会签任务总数 - */ - String NUMBER_OF_INSTANCES = "nrOfInstances"; - - /** - * 正在执行的会签总数 - */ - String NUMBER_OF_ACTIVE_INSTANCES = "nrOfActiveInstances"; - - /** - * 已完成的会签任务总数 - */ - String NUMBER_OF_COMPLETED_INSTANCES = "nrOfCompletedInstances"; - - /** - * 循环的索引值,可以使用elementIndexVariable属性修改loopCounter的变量名 - */ - String LOOP_COUNTER = "loopCounter"; - - String ZIP = "ZIP"; - - /** - * 业务与流程实例关联对象 - */ - String BUSINESS_INSTANCE_DTO = "businessInstanceDTO"; - - /** - * 流程定义配置 - */ - String WF_DEFINITION_CONFIG_VO = "wfDefinitionConfigVo"; - - /** - * 节点配置 - */ - String WF_NODE_CONFIG_VO = "wfNodeConfigVo"; - /** * 流程发起人 */ @@ -98,40 +21,46 @@ public interface FlowConstant { /** * 业务id */ - String BUSINESS_KEY = "businessKey"; + String BUSINESS_ID = "businessId"; /** - * 流程定义id + * 任务id */ - String PROCESS_DEFINITION_ID = "processDefinitionId"; + String TASK_ID = "taskId"; /** - * 开启跳过表达式变量 + * 委托 */ - String FLOWABLE_SKIP_EXPRESSION_ENABLED = "_FLOWABLE_SKIP_EXPRESSION_ENABLED"; + String DELEGATE_TASK = "delegateTask"; /** - * 模型标识key命名规范正则表达式 + * 转办 */ - String MODEL_KEY_PATTERN = "^[a-zA-Z][a-zA-Z0-9_]{0,254}$"; + String TRANSFER_TASK = "transferTask"; /** - * 用户任务 + * 加签 */ - String USER_TASK = "userTask"; + String ADD_SIGNATURE = "addSignature"; /** - * 会签 + * 减签 */ - String MULTI_INSTANCE = "multiInstance"; + String REDUCTION_SIGNATURE = "reductionSignature"; /** - * 是 + * 流程分类Id转名称 */ - String TRUE = "0"; + String CATEGORY_ID_TO_NAME = "category_id_to_name"; /** - * 否 + * 流程分类名称 */ - String FALSE = "1"; + String FLOW_CATEGORY_NAME = "flow_category_name#30d"; + + /** + * 默认租户OA申请分类id + */ + Long FLOW_CATEGORY_ID = 100L; + } diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/FormTypeEnum.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/FormTypeEnum.java deleted file mode 100644 index 083ab7b85..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/FormTypeEnum.java +++ /dev/null @@ -1,54 +0,0 @@ -package org.dromara.workflow.common.enums; - -import cn.hutool.core.util.StrUtil; -import lombok.AllArgsConstructor; -import lombok.Getter; -import org.apache.commons.lang3.StringUtils; - -import java.util.Arrays; - -/** - * 任务状态枚举 - * - * @author may - */ -@Getter -@AllArgsConstructor -public enum FormTypeEnum { - /** - * 自定义表单 - */ - STATIC("static", "自定义表单"), - /** - * 动态表单 - */ - DYNAMIC("dynamic", "动态表单"); - - /** - * 类型 - */ - private final String type; - - /** - * 描述 - */ - private final String desc; - - /** - * 表单类型 - * - * @param formType 表单类型 - */ - public static String findByType(String formType) { - if (StringUtils.isBlank(formType)) { - return StrUtil.EMPTY; - } - - return Arrays.stream(FormTypeEnum.values()) - .filter(statusEnum -> statusEnum.getType().equals(formType)) - .findFirst() - .map(FormTypeEnum::getDesc) - .orElse(StrUtil.EMPTY); - } -} - diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/MessageTypeEnum.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/MessageTypeEnum.java index a28295822..0fe5cfe90 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/MessageTypeEnum.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/MessageTypeEnum.java @@ -3,8 +3,10 @@ package org.dromara.workflow.common.enums; import lombok.AllArgsConstructor; import lombok.Getter; +import java.util.Arrays; import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Function; +import java.util.stream.Collectors; /** * 消息类型枚举 @@ -14,14 +16,17 @@ import java.util.concurrent.ConcurrentHashMap; @Getter @AllArgsConstructor public enum MessageTypeEnum { + /** * 站内信 */ SYSTEM_MESSAGE("1", "站内信"), + /** * 邮箱 */ EMAIL_MESSAGE("2", "邮箱"), + /** * 短信 */ @@ -31,21 +36,18 @@ public enum MessageTypeEnum { private final String desc; - private final static Map MESSAGE_TYPE_ENUM_MAP = new ConcurrentHashMap<>(MessageTypeEnum.values().length); - - static { - for (MessageTypeEnum messageType : MessageTypeEnum.values()) { - MESSAGE_TYPE_ENUM_MAP.put(messageType.code, messageType); - } - } + private static final Map MESSAGE_TYPE_ENUM_MAP = Arrays.stream(values()) + .collect(Collectors.toConcurrentMap(MessageTypeEnum::getCode, Function.identity())); /** * 根据消息类型 code 获取 MessageTypeEnum + * * @param code 消息类型code * @return MessageTypeEnum */ public static MessageTypeEnum getByCode(String code) { - return MESSAGE_TYPE_ENUM_MAP.get(code); + return MESSAGE_TYPE_ENUM_MAP.getOrDefault(code, null); } + } diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/TaskAssigneeEnum.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/TaskAssigneeEnum.java new file mode 100644 index 000000000..60be92fe9 --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/TaskAssigneeEnum.java @@ -0,0 +1,109 @@ +package org.dromara.workflow.common.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.dromara.common.core.exception.ServiceException; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 任务分配人枚举 + * + * @author AprilWind + */ +@Getter +@AllArgsConstructor +public enum TaskAssigneeEnum { + + /** + * 用户 + */ + USER("用户", ""), + + /** + * 角色 + */ + ROLE("角色", "role:"), + + /** + * 部门 + */ + DEPT("部门", "dept:"), + + /** + * 岗位 + */ + POST("岗位", "post:"); + + private final String desc; + private final String code; + + /** + * 根据描述获取对应的枚举类型 + *

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

+ */ + COPY("4", "待办任务的抄送人权限"); + + /** + * 类型 + */ + private final String code; + + /** + * 描述 + */ + private final String description; + +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/TaskStatusEnum.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/TaskStatusEnum.java index 7b2f55c20..d18ebb01d 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/TaskStatusEnum.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/TaskStatusEnum.java @@ -3,9 +3,10 @@ package org.dromara.workflow.common.enums; import cn.hutool.core.util.StrUtil; import lombok.AllArgsConstructor; import lombok.Getter; -import org.apache.commons.lang3.StringUtils; import java.util.Arrays; +import java.util.Map; +import java.util.stream.Collectors; /** * 任务状态枚举 @@ -15,50 +16,62 @@ import java.util.Arrays; @Getter @AllArgsConstructor public enum TaskStatusEnum { + /** * 撤销 */ CANCEL("cancel", "撤销"), + /** * 通过 */ PASS("pass", "通过"), + /** * 待审核 */ WAITING("waiting", "待审核"), + /** * 作废 */ INVALID("invalid", "作废"), + /** * 退回 */ BACK("back", "退回"), + /** * 终止 */ TERMINATION("termination", "终止"), + /** * 转办 */ TRANSFER("transfer", "转办"), + /** * 委托 */ - PENDING("pending", "委托"), + DEPUTE("depute", "委托"), + /** * 抄送 */ COPY("copy", "抄送"), + /** * 加签 */ SIGN("sign", "加签"), + /** * 减签 */ SIGN_OFF("sign_off", "减签"), + /** * 超时 */ @@ -74,21 +87,18 @@ public enum TaskStatusEnum { */ private final String desc; + private static final Map STATUS_DESC_MAP = Arrays.stream(values()) + .collect(Collectors.toConcurrentMap(TaskStatusEnum::getStatus, TaskStatusEnum::getDesc)); + /** * 任务业务状态 * * @param status 状态 */ public static String findByStatus(String status) { - if (StringUtils.isBlank(status)) { - return StrUtil.EMPTY; - } - - return Arrays.stream(TaskStatusEnum.values()) - .filter(statusEnum -> statusEnum.getStatus().equals(status)) - .findFirst() - .map(TaskStatusEnum::getDesc) - .orElse(StrUtil.EMPTY); + // 从缓存中直接获取描述 + return STATUS_DESC_MAP.getOrDefault(status, StrUtil.EMPTY); } + } diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/config/WarmFlowConfig.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/config/WarmFlowConfig.java new file mode 100644 index 000000000..a38c83e27 --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/config/WarmFlowConfig.java @@ -0,0 +1,15 @@ +package org.dromara.workflow.config; + + +import org.springframework.context.annotation.Configuration; + +/** + * warmFlow配置 + * + * @author may + */ +@Configuration +public class WarmFlowConfig { + +} + diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/ActModelController.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/ActModelController.java deleted file mode 100644 index 842d3d667..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/ActModelController.java +++ /dev/null @@ -1,148 +0,0 @@ -package org.dromara.workflow.controller; - -import jakarta.servlet.http.HttpServletResponse; -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotEmpty; -import lombok.RequiredArgsConstructor; -import org.dromara.common.core.domain.R; -import org.dromara.common.core.validate.AddGroup; -import org.dromara.common.core.validate.EditGroup; -import org.dromara.common.idempotent.annotation.RepeatSubmit; -import org.dromara.common.log.annotation.Log; -import org.dromara.common.log.enums.BusinessType; -import org.dromara.common.mybatis.core.page.PageQuery; -import org.dromara.common.mybatis.core.page.TableDataInfo; -import org.dromara.common.web.core.BaseController; -import org.dromara.workflow.domain.bo.ModelBo; -import org.dromara.workflow.domain.vo.ModelVo; -import org.dromara.workflow.service.IActModelService; -import org.flowable.engine.RepositoryService; -import org.flowable.engine.repository.Model; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import java.util.Arrays; -import java.util.List; - -/** - * 模型管理 控制层 - * - * @author may - */ -@Validated -@RequiredArgsConstructor -@RestController -@RequestMapping("/workflow/model") -public class ActModelController extends BaseController { - - @Autowired(required = false) - private RepositoryService repositoryService; - private final IActModelService actModelService; - - - /** - * 分页查询模型 - * - * @param modelBo 模型参数 - */ - @GetMapping("/list") - public TableDataInfo page(ModelBo modelBo, PageQuery pageQuery) { - return actModelService.page(modelBo, pageQuery); - } - - /** - * 新增模型 - * - * @param modelBo 模型请求对象 - */ - @Log(title = "模型管理", businessType = BusinessType.INSERT) - @RepeatSubmit() - @PostMapping("/save") - public R saveNewModel(@Validated(AddGroup.class) @RequestBody ModelBo modelBo) { - return toAjax(actModelService.saveNewModel(modelBo)); - } - - /** - * 查询模型 - * - * @param id 模型id - */ - @GetMapping("/getInfo/{id}") - public R getInfo(@NotBlank(message = "模型id不能为空") @PathVariable String id) { - return R.ok(actModelService.getInfo(id)); - } - - /** - * 修改模型信息 - * - * @param modelBo 模型数据 - */ - @Log(title = "模型管理", businessType = BusinessType.UPDATE) - @RepeatSubmit() - @PutMapping(value = "/update") - public R update(@RequestBody ModelBo modelBo) { - return toAjax(actModelService.update(modelBo)); - } - - /** - * 编辑XMl模型 - * - * @param modelBo 模型数据 - */ - @Log(title = "模型管理", businessType = BusinessType.UPDATE) - @RepeatSubmit() - @PutMapping(value = "/editModelXml") - public R editModel(@Validated(EditGroup.class) @RequestBody ModelBo modelBo) { - return toAjax(actModelService.editModelXml(modelBo)); - } - - /** - * 删除流程模型 - * - * @param ids 模型id - */ - @Log(title = "模型管理", businessType = BusinessType.DELETE) - @RepeatSubmit() - @DeleteMapping("/{ids}") - @Transactional(rollbackFor = Exception.class) - public R delete(@NotEmpty(message = "主键不能为空") @PathVariable String[] ids) { - Arrays.stream(ids).parallel().forEachOrdered(repositoryService::deleteModel); - return R.ok(); - } - - /** - * 模型部署 - * - * @param id 模型id - */ - @Log(title = "模型管理", businessType = BusinessType.INSERT) - @RepeatSubmit() - @PostMapping("/modelDeploy/{id}") - public R deploy(@NotBlank(message = "模型id不能为空") @PathVariable("id") String id) { - return toAjax(actModelService.modelDeploy(id)); - } - - /** - * 导出模型zip压缩包 - * - * @param modelIds 模型id - * @param response 相应 - */ - @GetMapping("/export/zip/{modelIds}") - public void exportZip(@NotEmpty(message = "模型id不能为空") @PathVariable List modelIds, - HttpServletResponse response) { - actModelService.exportZip(modelIds, response); - } - - /** - * 复制模型 - * - * @param modelBo 模型数据 - */ - @PostMapping("/copyModel") - public R copyModel(@RequestBody ModelBo modelBo) { - return toAjax(actModelService.copyModel(modelBo)); - } -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/ActProcessDefinitionController.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/ActProcessDefinitionController.java deleted file mode 100644 index 5198bd164..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/ActProcessDefinitionController.java +++ /dev/null @@ -1,147 +0,0 @@ -package org.dromara.workflow.controller; - -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; -import lombok.RequiredArgsConstructor; -import org.dromara.common.core.domain.R; -import org.dromara.common.idempotent.annotation.RepeatSubmit; -import org.dromara.common.log.annotation.Log; -import org.dromara.common.log.enums.BusinessType; -import org.dromara.common.mybatis.core.page.PageQuery; -import org.dromara.common.mybatis.core.page.TableDataInfo; -import org.dromara.common.web.core.BaseController; -import org.dromara.workflow.domain.bo.ProcessDefinitionBo; -import org.dromara.workflow.domain.vo.ProcessDefinitionVo; -import org.dromara.workflow.service.IActProcessDefinitionService; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; -import org.springframework.web.multipart.MultipartFile; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - - -/** - * 流程定义管理 控制层 - * - * @author may - */ -@Validated -@RequiredArgsConstructor -@RestController -@RequestMapping("/workflow/processDefinition") -public class ActProcessDefinitionController extends BaseController { - - private final IActProcessDefinitionService actProcessDefinitionService; - - /** - * 分页查询 - * - * @param bo 参数 - */ - @GetMapping("/list") - public TableDataInfo page(ProcessDefinitionBo bo, PageQuery pageQuery) { - return actProcessDefinitionService.page(bo, pageQuery); - } - - /** - * 查询历史流程定义列表 - * - * @param key 流程定义key - */ - @GetMapping("/getListByKey/{key}") - public R> getListByKey(@NotEmpty(message = "流程定义key不能为空") @PathVariable String key) { - return R.ok("操作成功", actProcessDefinitionService.getListByKey(key)); - } - - /** - * 查看流程定义图片 - * - * @param processDefinitionId 流程定义id - */ - @GetMapping("/definitionImage/{processDefinitionId}") - public R definitionImage(@PathVariable String processDefinitionId) { - return R.ok("操作成功", actProcessDefinitionService.definitionImage(processDefinitionId)); - } - - /** - * 查看流程定义xml文件 - * - * @param processDefinitionId 流程定义id - */ - @GetMapping("/definitionXml/{processDefinitionId}") - public R> definitionXml(@NotBlank(message = "流程定义id不能为空") @PathVariable String processDefinitionId) { - Map map = new HashMap<>(); - String xmlStr = actProcessDefinitionService.definitionXml(processDefinitionId); - map.put("xml", Arrays.asList(xmlStr.split("\n"))); - map.put("xmlStr", xmlStr); - return R.ok(map); - } - - /** - * 删除流程定义 - * - * @param deploymentIds 部署id - * @param processDefinitionIds 流程定义id - */ - @Log(title = "流程定义管理", businessType = BusinessType.DELETE) - @DeleteMapping("/{deploymentIds}/{processDefinitionIds}") - public R deleteDeployment(@NotNull(message = "流程部署id不能为空") @PathVariable List deploymentIds, - @NotNull(message = "流程定义id不能为空") @PathVariable List processDefinitionIds) { - return toAjax(actProcessDefinitionService.deleteDeployment(deploymentIds, processDefinitionIds)); - } - - /** - * 激活或者挂起流程定义 - * - * @param processDefinitionId 流程定义id - */ - @Log(title = "流程定义管理", businessType = BusinessType.UPDATE) - @RepeatSubmit() - @PutMapping("/updateDefinitionState/{processDefinitionId}") - public R updateDefinitionState(@NotBlank(message = "流程定义id不能为空") @PathVariable String processDefinitionId) { - return toAjax(actProcessDefinitionService.updateDefinitionState(processDefinitionId)); - } - - /** - * 迁移流程定义 - * - * @param currentProcessDefinitionId 当前流程定义id - * @param fromProcessDefinitionId 需要迁移到的流程定义id - */ - @Log(title = "流程定义管理", businessType = BusinessType.UPDATE) - @RepeatSubmit() - @PutMapping("/migrationDefinition/{currentProcessDefinitionId}/{fromProcessDefinitionId}") - public R migrationDefinition(@NotBlank(message = "当前流程定义id") @PathVariable String currentProcessDefinitionId, - @NotBlank(message = "需要迁移到的流程定义id") @PathVariable String fromProcessDefinitionId) { - return toAjax(actProcessDefinitionService.migrationDefinition(currentProcessDefinitionId, fromProcessDefinitionId)); - } - - /** - * 流程定义转换为模型 - * - * @param processDefinitionId 流程定义id - */ - @Log(title = "流程定义管理", businessType = BusinessType.UPDATE) - @RepeatSubmit() - @PutMapping("/convertToModel/{processDefinitionId}") - public R convertToModel(@NotEmpty(message = "流程定义id不能为空") @PathVariable String processDefinitionId) { - return toAjax(actProcessDefinitionService.convertToModel(processDefinitionId)); - } - - /** - * 通过zip或xml部署流程定义 - * - * @param file 文件 - * @param categoryCode 分类 - */ - @Log(title = "流程定义管理", businessType = BusinessType.INSERT) - @PostMapping("/deployByFile") - public void deployByFile(@RequestParam("file") MultipartFile file, @RequestParam("categoryCode") String categoryCode) { - actProcessDefinitionService.deployByFile(file, categoryCode); - } - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/ActProcessInstanceController.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/ActProcessInstanceController.java deleted file mode 100644 index 931b9f568..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/ActProcessInstanceController.java +++ /dev/null @@ -1,160 +0,0 @@ -package org.dromara.workflow.controller; - -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import lombok.RequiredArgsConstructor; -import org.dromara.common.core.domain.R; -import org.dromara.common.core.validate.AddGroup; -import org.dromara.common.idempotent.annotation.RepeatSubmit; -import org.dromara.common.log.annotation.Log; -import org.dromara.common.log.enums.BusinessType; -import org.dromara.common.mybatis.core.page.PageQuery; -import org.dromara.common.mybatis.core.page.TableDataInfo; -import org.dromara.common.web.core.BaseController; -import org.dromara.workflow.domain.bo.ProcessInstanceBo; -import org.dromara.workflow.domain.bo.ProcessInvalidBo; -import org.dromara.workflow.domain.bo.TaskUrgingBo; -import org.dromara.workflow.domain.vo.ActHistoryInfoVo; -import org.dromara.workflow.domain.vo.ProcessInstanceVo; -import org.dromara.workflow.service.IActProcessInstanceService; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import java.util.Arrays; -import java.util.List; -import java.util.Map; - -/** - * 流程实例管理 控制层 - * - * @author may - */ -@Validated -@RequiredArgsConstructor -@RestController -@RequestMapping("/workflow/processInstance") -public class ActProcessInstanceController extends BaseController { - - private final IActProcessInstanceService actProcessInstanceService; - - /** - * 分页查询正在运行的流程实例 - * - * @param bo 参数 - */ - @GetMapping("/getPageByRunning") - public TableDataInfo getPageByRunning(ProcessInstanceBo bo, PageQuery pageQuery) { - return actProcessInstanceService.getPageByRunning(bo, pageQuery); - } - - /** - * 分页查询已结束的流程实例 - * - * @param bo 参数 - */ - @GetMapping("/getPageByFinish") - public TableDataInfo getPageByFinish(ProcessInstanceBo bo, PageQuery pageQuery) { - return actProcessInstanceService.getPageByFinish(bo, pageQuery); - } - - /** - * 通过业务id获取历史流程图 - * - * @param businessKey 业务id - */ - @GetMapping("/getHistoryImage/{businessKey}") - public R getHistoryImage(@NotBlank(message = "业务id不能为空") @PathVariable String businessKey) { - return R.ok("操作成功", actProcessInstanceService.getHistoryImage(businessKey)); - } - - /** - * 通过业务id获取历史流程图运行中,历史等节点 - * - * @param businessKey 业务id - */ - @GetMapping("/getHistoryList/{businessKey}") - public R> getHistoryList(@NotBlank(message = "业务id不能为空") @PathVariable String businessKey) { - return R.ok("操作成功", actProcessInstanceService.getHistoryList(businessKey)); - } - - /** - * 获取审批记录 - * - * @param businessKey 业务id - */ - @GetMapping("/getHistoryRecord/{businessKey}") - public R> getHistoryRecord(@NotBlank(message = "业务id不能为空") @PathVariable String businessKey) { - return R.ok(actProcessInstanceService.getHistoryRecord(businessKey)); - } - - /** - * 作废流程实例,不会删除历史记录(删除运行中的实例) - * - * @param processInvalidBo 参数 - */ - @Log(title = "流程实例管理", businessType = BusinessType.DELETE) - @RepeatSubmit() - @PostMapping("/deleteRunInstance") - public R deleteRunInstance(@Validated(AddGroup.class) @RequestBody ProcessInvalidBo processInvalidBo) { - return toAjax(actProcessInstanceService.deleteRunInstance(processInvalidBo)); - } - - /** - * 运行中的实例 删除程实例,删除历史记录,删除业务与流程关联信息 - * - * @param businessKeys 业务id - */ - @Log(title = "流程实例管理", businessType = BusinessType.DELETE) - @RepeatSubmit() - @DeleteMapping("/deleteRunAndHisInstance/{businessKeys}") - public R deleteRunAndHisInstance(@NotNull(message = "业务id不能为空") @PathVariable String[] businessKeys) { - return toAjax(actProcessInstanceService.deleteRunAndHisInstance(Arrays.asList(businessKeys))); - } - - /** - * 已完成的实例 删除程实例,删除历史记录,删除业务与流程关联信息 - * - * @param businessKeys 业务id - */ - @Log(title = "流程实例管理", businessType = BusinessType.DELETE) - @RepeatSubmit() - @DeleteMapping("/deleteFinishAndHisInstance/{businessKeys}") - public R deleteFinishAndHisInstance(@NotNull(message = "业务id不能为空") @PathVariable String[] businessKeys) { - return toAjax(actProcessInstanceService.deleteFinishAndHisInstance(Arrays.asList(businessKeys))); - } - - /** - * 撤销流程申请 - * - * @param businessKey 业务id - */ - @Log(title = "流程实例管理", businessType = BusinessType.INSERT) - @RepeatSubmit() - @PostMapping("/cancelProcessApply/{businessKey}") - public R cancelProcessApply(@NotBlank(message = "业务id不能为空") @PathVariable String businessKey) { - return toAjax(actProcessInstanceService.cancelProcessApply(businessKey)); - } - - /** - * 分页查询当前登录人单据 - * - * @param bo 参数 - */ - @GetMapping("/getPageByCurrent") - public TableDataInfo getPageByCurrent(ProcessInstanceBo bo, PageQuery pageQuery) { - return actProcessInstanceService.getPageByCurrent(bo, pageQuery); - } - - /** - * 任务催办(给当前任务办理人发送站内信,邮件,短信等) - * - * @param taskUrgingBo 任务催办 - */ - @Log(title = "流程实例管理", businessType = BusinessType.INSERT) - @RepeatSubmit() - @PostMapping("/taskUrging") - public R taskUrging(@RequestBody TaskUrgingBo taskUrgingBo) { - return toAjax(actProcessInstanceService.taskUrging(taskUrgingBo)); - } - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/ActTaskController.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/ActTaskController.java deleted file mode 100644 index 25724b6d9..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/ActTaskController.java +++ /dev/null @@ -1,295 +0,0 @@ -package org.dromara.workflow.controller; - -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.convert.Convert; -import jakarta.validation.constraints.NotBlank; -import lombok.RequiredArgsConstructor; -import org.dromara.common.core.domain.R; -import org.dromara.common.core.validate.AddGroup; -import org.dromara.common.idempotent.annotation.RepeatSubmit; -import org.dromara.common.log.annotation.Log; -import org.dromara.common.log.enums.BusinessType; -import org.dromara.common.mybatis.core.page.PageQuery; -import org.dromara.common.mybatis.core.page.TableDataInfo; -import org.dromara.common.satoken.utils.LoginHelper; -import org.dromara.common.web.core.BaseController; -import org.dromara.workflow.domain.WfTaskBackNode; -import org.dromara.workflow.domain.bo.*; -import org.dromara.workflow.domain.vo.TaskVo; -import org.dromara.workflow.domain.vo.VariableVo; -import org.dromara.workflow.service.IActTaskService; -import org.dromara.workflow.service.IWfTaskBackNodeService; -import org.dromara.workflow.utils.QueryUtils; -import org.flowable.engine.TaskService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import java.util.List; -import java.util.Map; - -/** - * 任务管理 控制层 - * - * @author may - */ -@Validated -@RequiredArgsConstructor -@RestController -@RequestMapping("/workflow/task") -public class ActTaskController extends BaseController { - - @Autowired(required = false) - private TaskService taskService; - private final IActTaskService actTaskService; - private final IWfTaskBackNodeService wfTaskBackNodeService; - - - /** - * 启动任务 - * - * @param startProcessBo 启动流程参数 - */ - @Log(title = "任务管理", businessType = BusinessType.INSERT) - @RepeatSubmit() - @PostMapping("/startWorkFlow") - public R> startWorkFlow(@Validated(AddGroup.class) @RequestBody StartProcessBo startProcessBo) { - Map map = actTaskService.startWorkFlow(startProcessBo); - return R.ok("提交成功", map); - } - - /** - * 办理任务 - * - * @param completeTaskBo 办理任务参数 - */ - @Log(title = "任务管理", businessType = BusinessType.INSERT) - @RepeatSubmit() - @PostMapping("/completeTask") - public R completeTask(@Validated(AddGroup.class) @RequestBody CompleteTaskBo completeTaskBo) { - return toAjax(actTaskService.completeTask(completeTaskBo)); - } - - /** - * 查询当前用户的待办任务 - * - * @param taskBo 参数 - */ - @GetMapping("/getPageByTaskWait") - public TableDataInfo getPageByTaskWait(TaskBo taskBo, PageQuery pageQuery) { - return actTaskService.getPageByTaskWait(taskBo, pageQuery); - } - - /** - * 查询当前租户所有待办任务 - * - * @param taskBo 参数 - */ - @GetMapping("/getPageByAllTaskWait") - public TableDataInfo getPageByAllTaskWait(TaskBo taskBo, PageQuery pageQuery) { - return actTaskService.getPageByAllTaskWait(taskBo, pageQuery); - } - - /** - * 查询当前用户的已办任务 - * - * @param taskBo 参数 - */ - @GetMapping("/getPageByTaskFinish") - public TableDataInfo getPageByTaskFinish(TaskBo taskBo, PageQuery pageQuery) { - return actTaskService.getPageByTaskFinish(taskBo, pageQuery); - } - - /** - * 查询当前用户的抄送 - * - * @param taskBo 参数 - */ - @GetMapping("/getPageByTaskCopy") - public TableDataInfo getPageByTaskCopy(TaskBo taskBo, PageQuery pageQuery) { - return actTaskService.getPageByTaskCopy(taskBo, pageQuery); - } - - /** - * 查询当前租户所有已办任务 - * - * @param taskBo 参数 - */ - @GetMapping("/getPageByAllTaskFinish") - public TableDataInfo getPageByAllTaskFinish(TaskBo taskBo, PageQuery pageQuery) { - return actTaskService.getPageByAllTaskFinish(taskBo, pageQuery); - } - - /** - * 签收(拾取)任务 - * - * @param taskId 任务id - */ - @Log(title = "任务管理", businessType = BusinessType.INSERT) - @RepeatSubmit() - @PostMapping("/claim/{taskId}") - public R claimTask(@NotBlank(message = "任务id不能为空") @PathVariable String taskId) { - try { - taskService.claim(taskId, Convert.toStr(LoginHelper.getUserId())); - return R.ok(); - } catch (Exception e) { - e.printStackTrace(); - return R.fail("签收任务失败:" + e.getMessage()); - } - } - - /** - * 归还(拾取的)任务 - * - * @param taskId 任务id - */ - @Log(title = "任务管理", businessType = BusinessType.INSERT) - @RepeatSubmit() - @PostMapping("/returnTask/{taskId}") - public R returnTask(@NotBlank(message = "任务id不能为空") @PathVariable String taskId) { - try { - taskService.setAssignee(taskId, null); - return R.ok(); - } catch (Exception e) { - e.printStackTrace(); - return R.fail("归还任务失败:" + e.getMessage()); - } - } - - /** - * 委派任务 - * - * @param delegateBo 参数 - */ - @Log(title = "任务管理", businessType = BusinessType.INSERT) - @RepeatSubmit() - @PostMapping("/delegateTask") - public R delegateTask(@Validated({AddGroup.class}) @RequestBody DelegateBo delegateBo) { - return toAjax(actTaskService.delegateTask(delegateBo)); - } - - /** - * 终止任务 - * - * @param terminationBo 参数 - */ - @Log(title = "任务管理", businessType = BusinessType.DELETE) - @RepeatSubmit() - @PostMapping("/terminationTask") - public R terminationTask(@RequestBody TerminationBo terminationBo) { - return toAjax(actTaskService.terminationTask(terminationBo)); - } - - /** - * 转办任务 - * - * @param transmitBo 参数 - */ - @Log(title = "任务管理", businessType = BusinessType.INSERT) - @RepeatSubmit() - @PostMapping("/transferTask") - public R transferTask(@Validated({AddGroup.class}) @RequestBody TransmitBo transmitBo) { - return toAjax(actTaskService.transferTask(transmitBo)); - } - - /** - * 会签任务加签 - * - * @param addMultiBo 参数 - */ - @Log(title = "任务管理", businessType = BusinessType.INSERT) - @RepeatSubmit() - @PostMapping("/addMultiInstanceExecution") - public R addMultiInstanceExecution(@Validated({AddGroup.class}) @RequestBody AddMultiBo addMultiBo) { - return toAjax(actTaskService.addMultiInstanceExecution(addMultiBo)); - } - - /** - * 会签任务减签 - * - * @param deleteMultiBo 参数 - */ - @Log(title = "任务管理", businessType = BusinessType.INSERT) - @RepeatSubmit() - @PostMapping("/deleteMultiInstanceExecution") - public R deleteMultiInstanceExecution(@Validated({AddGroup.class}) @RequestBody DeleteMultiBo deleteMultiBo) { - return toAjax(actTaskService.deleteMultiInstanceExecution(deleteMultiBo)); - } - - /** - * 驳回审批 - * - * @param backProcessBo 参数 - */ - @Log(title = "任务管理", businessType = BusinessType.INSERT) - @RepeatSubmit() - @PostMapping("/backProcess") - public R backProcess(@Validated({AddGroup.class}) @RequestBody BackProcessBo backProcessBo) { - return R.ok("操作成功", actTaskService.backProcess(backProcessBo)); - } - - /** - * 获取当前任务 - * - * @param taskId 任务id - */ - @GetMapping("/getTaskById/{taskId}") - public R getTaskById(@PathVariable String taskId) { - return R.ok(QueryUtils.getTask(taskId)); - } - - - /** - * 修改任务办理人 - * - * @param taskIds 任务id - * @param userId 办理人id - */ - @Log(title = "任务管理", businessType = BusinessType.UPDATE) - @RepeatSubmit() - @PutMapping("/updateAssignee/{taskIds}/{userId}") - public R updateAssignee(@PathVariable String[] taskIds, @PathVariable String userId) { - return toAjax(actTaskService.updateAssignee(taskIds, userId)); - } - - /** - * 查询流程变量 - * - * @param taskId 任务id - */ - @GetMapping("/getInstanceVariable/{taskId}") - public R> getProcessInstVariable(@PathVariable String taskId) { - return R.ok(actTaskService.getInstanceVariable(taskId)); - } - - /** - * 获取可驳回得任务节点 - * - * @param processInstanceId 流程实例id - */ - @GetMapping("/getTaskNodeList/{processInstanceId}") - public R> getNodeList(@PathVariable String processInstanceId) { - return R.ok(CollUtil.reverse(wfTaskBackNodeService.getListByInstanceId(processInstanceId))); - } - - /** - * 查询工作流任务用户选择加签人员 - * - * @param taskId 任务id - */ - @GetMapping("/getTaskUserIdsByAddMultiInstance/{taskId}") - public R getTaskUserIdsByAddMultiInstance(@PathVariable String taskId) { - return R.ok("操作成功", actTaskService.getTaskUserIdsByAddMultiInstance(taskId)); - } - - /** - * 查询工作流选择减签人员 - * - * @param taskId 任务id - */ - @GetMapping("/getListByDeleteMultiInstance/{taskId}") - public R> getListByDeleteMultiInstance(@PathVariable String taskId) { - return R.ok(actTaskService.getListByDeleteMultiInstance(taskId)); - } - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwCategoryController.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwCategoryController.java new file mode 100644 index 000000000..99fa064df --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwCategoryController.java @@ -0,0 +1,130 @@ +package org.dromara.workflow.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.lang.tree.Tree; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.constraints.NotNull; +import lombok.RequiredArgsConstructor; +import org.dromara.common.core.domain.R; +import org.dromara.common.core.validate.AddGroup; +import org.dromara.common.core.validate.EditGroup; +import org.dromara.common.excel.utils.ExcelUtil; +import org.dromara.common.idempotent.annotation.RepeatSubmit; +import org.dromara.common.log.annotation.Log; +import org.dromara.common.log.enums.BusinessType; +import org.dromara.common.web.core.BaseController; +import org.dromara.workflow.domain.bo.FlowCategoryBo; +import org.dromara.workflow.domain.vo.FlowCategoryVo; +import org.dromara.workflow.service.IFlwCategoryService; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 流程分类 + * + * @author may + */ +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("/workflow/category") +public class FlwCategoryController extends BaseController { + + private final IFlwCategoryService flwCategoryService; + + /** + * 查询流程分类列表 + */ + @SaCheckPermission("workflow:category:list") + @GetMapping("/list") + public R> list(FlowCategoryBo bo) { + List list = flwCategoryService.queryList(bo); + return R.ok(list); + } + + /** + * 导出流程分类列表 + */ + @SaCheckPermission("workflow:category:export") + @Log(title = "流程分类", businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(FlowCategoryBo bo, HttpServletResponse response) { + List list = flwCategoryService.queryList(bo); + ExcelUtil.exportExcel(list, "流程分类", FlowCategoryVo.class, response); + } + + /** + * 获取流程分类详细信息 + * + * @param categoryId 主键 + */ + @SaCheckPermission("workflow:category:query") + @GetMapping("/{categoryId}") + public R getInfo(@NotNull(message = "主键不能为空") @PathVariable Long categoryId) { + flwCategoryService.checkCategoryDataScope(categoryId); + return R.ok(flwCategoryService.queryById(categoryId)); + } + + /** + * 新增流程分类 + */ + @SaCheckPermission("workflow:category:add") + @Log(title = "流程分类", businessType = BusinessType.INSERT) + @RepeatSubmit() + @PostMapping() + public R add(@Validated(AddGroup.class) @RequestBody FlowCategoryBo category) { + if (!flwCategoryService.checkCategoryNameUnique(category)) { + return R.fail("新增流程分类'" + category.getCategoryName() + "'失败,流程分类名称已存在"); + } + return toAjax(flwCategoryService.insertByBo(category)); + } + + /** + * 修改流程分类 + */ + @SaCheckPermission("workflow:category:edit") + @Log(title = "流程分类", businessType = BusinessType.UPDATE) + @RepeatSubmit() + @PutMapping() + public R edit(@Validated(EditGroup.class) @RequestBody FlowCategoryBo category) { + Long categoryId = category.getCategoryId(); + flwCategoryService.checkCategoryDataScope(categoryId); + if (!flwCategoryService.checkCategoryNameUnique(category)) { + return R.fail("修改流程分类'" + category.getCategoryName() + "'失败,流程分类名称已存在"); + } else if (category.getParentId().equals(categoryId)) { + return R.fail("修改流程分类'" + category.getCategoryName() + "'失败,上级流程分类不能是自己"); + } + return toAjax(flwCategoryService.updateByBo(category)); + } + + /** + * 删除流程分类 + * + * @param categoryId 主键 + */ + @SaCheckPermission("workflow:category:remove") + @Log(title = "流程分类", businessType = BusinessType.DELETE) + @DeleteMapping("/{categoryId}") + public R remove(@PathVariable Long categoryId) { + if (flwCategoryService.hasChildByCategoryId(categoryId)) { + return R.warn("存在下级流程分类,不允许删除"); + } + if (flwCategoryService.checkCategoryExistDefinition(categoryId)) { + return R.warn("流程分类存在流程定义,不允许删除"); + } + return toAjax(flwCategoryService.deleteWithValidById(categoryId)); + } + + /** + * 获取流程分类树列表 + * + * @param categoryBo 流程分类 + */ + @GetMapping("/categoryTree") + public R>> categoryTree(FlowCategoryBo categoryBo) { + return R.ok(flwCategoryService.selectCategoryTreeList(categoryBo)); + } + +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwDefinitionController.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwDefinitionController.java new file mode 100644 index 000000000..b125f0f28 --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwDefinitionController.java @@ -0,0 +1,194 @@ +package org.dromara.workflow.controller; + +import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; +import org.dromara.common.core.domain.R; +import org.dromara.common.idempotent.annotation.RepeatSubmit; +import org.dromara.common.log.annotation.Log; +import org.dromara.common.log.enums.BusinessType; +import org.dromara.common.mybatis.core.page.PageQuery; +import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.common.web.core.BaseController; +import org.dromara.warm.flow.core.entity.Definition; +import org.dromara.warm.flow.core.service.DefService; +import org.dromara.warm.flow.orm.entity.FlowDefinition; +import org.dromara.workflow.domain.vo.FlowDefinitionVo; +import org.dromara.workflow.service.IFlwDefinitionService; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.util.List; + +/** + * 流程定义管理 控制层 + * + * @author may + */ +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("/workflow/definition") +public class FlwDefinitionController extends BaseController { + + private final IFlwDefinitionService flwDefinitionService; + private final DefService defService; + + /** + * 查询流程定义列表 + * + * @param flowDefinition 参数 + * @param pageQuery 分页 + */ + @GetMapping("/list") + public TableDataInfo list(FlowDefinition flowDefinition, PageQuery pageQuery) { + return flwDefinitionService.queryList(flowDefinition, pageQuery); + } + + /** + * 查询未发布的流程定义列表 + * + * @param flowDefinition 参数 + * @param pageQuery 分页 + */ + @GetMapping("/unPublishList") + public TableDataInfo unPublishList(FlowDefinition flowDefinition, PageQuery pageQuery) { + return flwDefinitionService.unPublishList(flowDefinition, pageQuery); + } + + /** + * 获取流程定义详细信息 + * + * @param id 流程定义id + */ + @GetMapping(value = "/{id}") + public R getInfo(@PathVariable Long id) { + return R.ok(defService.getById(id)); + } + + /** + * 新增流程定义 + * + * @param flowDefinition 参数 + */ + @Log(title = "流程定义", businessType = BusinessType.INSERT) + @PostMapping + @RepeatSubmit() + @Transactional(rollbackFor = Exception.class) + public R add(@RequestBody FlowDefinition flowDefinition) { + return R.ok(defService.checkAndSave(flowDefinition)); + } + + /** + * 修改流程定义 + * + * @param flowDefinition 参数 + */ + @Log(title = "流程定义", businessType = BusinessType.UPDATE) + @PutMapping + @RepeatSubmit() + @Transactional(rollbackFor = Exception.class) + public R edit(@RequestBody FlowDefinition flowDefinition) { + return R.ok(defService.updateById(flowDefinition)); + } + + /** + * 发布流程定义 + * + * @param id 流程定义id + */ + @Log(title = "流程定义", businessType = BusinessType.INSERT) + @PutMapping("/publish/{id}") + @RepeatSubmit() + @Transactional(rollbackFor = Exception.class) + public R publish(@PathVariable Long id) { + return R.ok(flwDefinitionService.publish(id)); + } + + /** + * 取消发布流程定义 + * + * @param id 流程定义id + */ + @Log(title = "流程定义", businessType = BusinessType.INSERT) + @PutMapping("/unPublish/{id}") + @RepeatSubmit() + @Transactional(rollbackFor = Exception.class) + public R unPublish(@PathVariable Long id) { + return R.ok(defService.unPublish(id)); + } + + /** + * 删除流程定义 + */ + @Log(title = "流程定义", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + @Transactional(rollbackFor = Exception.class) + public R remove(@PathVariable List ids) { + return toAjax(flwDefinitionService.removeDef(ids)); + } + + /** + * 复制流程定义 + * + * @param id 流程定义id + */ + @Log(title = "流程定义", businessType = BusinessType.INSERT) + @PostMapping("/copy/{id}") + @RepeatSubmit() + @Transactional(rollbackFor = Exception.class) + public R copy(@PathVariable Long id) { + return R.ok(defService.copyDef(id)); + } + + /** + * 导入流程定义 + * + * @param file 文件 + * @param category 分类 + */ + @Log(title = "流程定义", businessType = BusinessType.IMPORT) + @PostMapping("/importDef") + @Transactional(rollbackFor = Exception.class) + public R importDef(MultipartFile file, String category) { + return R.ok(flwDefinitionService.importXml(file, category)); + } + + /** + * 导出流程定义 + * + * @param id 流程定义id + * @param response 响应 + * @throws IOException 异常 + */ + @Log(title = "流程定义", businessType = BusinessType.EXPORT) + @PostMapping("/exportDef/{id}") + public void exportDef(@PathVariable Long id, HttpServletResponse response) throws IOException { + flwDefinitionService.exportDef(id, response); + } + + /** + * 获取流程定义xml字符串 + * + * @param id 流程定义id + */ + @GetMapping("/xmlString/{id}") + public R xmlString(@PathVariable Long id) { + return R.ok("操作成功", defService.xmlString(id)); + } + + /** + * 激活/挂起流程定义 + * + * @param id 流程定义id + * @param active 激活/挂起 + */ + @RepeatSubmit() + @PutMapping("/active/{id}") + public R active(@PathVariable Long id, @RequestParam boolean active) { + return R.ok(active ? defService.active(id) : defService.unActive(id)); + } + +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwInstanceController.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwInstanceController.java new file mode 100644 index 000000000..cb65f2158 --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwInstanceController.java @@ -0,0 +1,155 @@ +package org.dromara.workflow.controller; + +import lombok.RequiredArgsConstructor; +import org.dromara.common.core.domain.R; +import org.dromara.common.idempotent.annotation.RepeatSubmit; +import org.dromara.common.log.annotation.Log; +import org.dromara.common.log.enums.BusinessType; +import org.dromara.common.mybatis.core.page.PageQuery; +import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.common.web.core.BaseController; +import org.dromara.warm.flow.core.service.InsService; +import org.dromara.workflow.domain.bo.FlowCancelBo; +import org.dromara.workflow.domain.bo.FlowInstanceBo; +import org.dromara.workflow.domain.bo.FlowInvalidBo; +import org.dromara.workflow.domain.vo.FlowInstanceVo; +import org.dromara.workflow.service.IFlwInstanceService; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.Map; + +/** + * 流程实例管理 控制层 + * + * @author may + */ +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("/workflow/instance") +public class FlwInstanceController extends BaseController { + + private final IFlwInstanceService flwInstanceService; + private final InsService insService; + + /** + * 查询正在运行的流程实例列表 + * + * @param flowInstanceBo 流程实例 + * @param pageQuery 分页 + */ + @GetMapping("/pageByRunning") + public TableDataInfo selectRunningInstanceList(FlowInstanceBo flowInstanceBo, PageQuery pageQuery) { + return flwInstanceService.selectRunningInstanceList(flowInstanceBo, pageQuery); + } + + /** + * 查询已结束的流程实例列表 + * + * @param flowInstanceBo 流程实例 + * @param pageQuery 分页 + */ + @GetMapping("/pageByFinish") + public TableDataInfo selectFinishInstanceList(FlowInstanceBo flowInstanceBo, PageQuery pageQuery) { + return flwInstanceService.selectFinishInstanceList(flowInstanceBo, pageQuery); + } + + /** + * 根据业务id查询流程实例详细信息 + * + * @param businessId 业务id + */ + @GetMapping("/getInfo/{businessId}") + public R getInfo(@PathVariable Long businessId) { + return R.ok(flwInstanceService.queryByBusinessId(businessId)); + } + + /** + * 按照业务id删除流程实例 + * + * @param businessIds 业务id + */ + @DeleteMapping("/deleteByBusinessIds/{businessIds}") + public R deleteByBusinessIds(@PathVariable List businessIds) { + return toAjax(flwInstanceService.deleteByBusinessIds(businessIds)); + } + + /** + * 按照实例id删除流程实例 + * + * @param instanceIds 实例id + */ + @DeleteMapping("/deleteByInstanceIds/{instanceIds}") + public R deleteByInstanceIds(@PathVariable List instanceIds) { + return toAjax(flwInstanceService.deleteByInstanceIds(instanceIds)); + } + + /** + * 撤销流程 + * + * @param bo 参数 + */ + @RepeatSubmit() + @PutMapping("/cancelProcessApply") + public R cancelProcessApply(@RequestBody FlowCancelBo bo) { + return toAjax(flwInstanceService.cancelProcessApply(bo)); + } + + /** + * 激活/挂起流程实例 + * + * @param id 流程实例id + * @param active 激活/挂起 + */ + @RepeatSubmit() + @PutMapping("/active/{id}") + public R active(@PathVariable Long id, @RequestParam boolean active) { + return R.ok(active ? insService.active(id) : insService.unActive(id)); + } + + /** + * 获取当前登陆人发起的流程实例 + * + * @param flowInstanceBo 参数 + * @param pageQuery 分页 + */ + @GetMapping("/pageByCurrent") + public TableDataInfo selectCurrentInstanceList(FlowInstanceBo flowInstanceBo, PageQuery pageQuery) { + return flwInstanceService.selectCurrentInstanceList(flowInstanceBo, pageQuery); + } + + /** + * 获取流程图,流程记录 + * + * @param businessId 业务id + */ + @GetMapping("/flowImage/{businessId}") + public R> flowImage(@PathVariable String businessId) { + return R.ok(flwInstanceService.flowImage(businessId)); + } + + /** + * 获取流程变量 + * + * @param instanceId 流程实例id + */ + @GetMapping("/instanceVariable/{instanceId}") + public R> instanceVariable(@PathVariable String instanceId) { + return R.ok(flwInstanceService.instanceVariable(instanceId)); + } + + /** + * 作废流程 + * + * @param bo 参数 + */ + @Log(title = "流程实例管理", businessType = BusinessType.INSERT) + @RepeatSubmit() + @PostMapping("/invalid") + public R invalid(@Validated @RequestBody FlowInvalidBo bo) { + return R.ok(flwInstanceService.processInvalid(bo)); + } + +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwTaskController.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwTaskController.java new file mode 100644 index 000000000..7736b7bf8 --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwTaskController.java @@ -0,0 +1,199 @@ +package org.dromara.workflow.controller; + +import lombok.RequiredArgsConstructor; +import org.dromara.common.core.domain.R; +import org.dromara.common.core.domain.dto.UserDTO; +import org.dromara.common.core.validate.AddGroup; +import org.dromara.common.idempotent.annotation.RepeatSubmit; +import org.dromara.common.log.annotation.Log; +import org.dromara.common.log.enums.BusinessType; +import org.dromara.common.mybatis.core.page.PageQuery; +import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.common.web.core.BaseController; +import org.dromara.warm.flow.core.entity.Node; +import org.dromara.workflow.domain.bo.*; +import org.dromara.workflow.domain.vo.FlowHisTaskVo; +import org.dromara.workflow.domain.vo.FlowTaskVo; +import org.dromara.workflow.service.IFlwTaskService; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.Map; + +/** + * 任务管理 控制层 + * + * @author may + */ +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("/workflow/task") +public class FlwTaskController extends BaseController { + + private final IFlwTaskService flwTaskService; + + /** + * 启动任务 + * + * @param startProcessBo 启动流程参数 + */ + @Log(title = "任务管理", businessType = BusinessType.INSERT) + @RepeatSubmit() + @PostMapping("/startWorkFlow") + public R> startWorkFlow(@Validated(AddGroup.class) @RequestBody StartProcessBo startProcessBo) { + Map map = flwTaskService.startWorkFlow(startProcessBo); + return R.ok("提交成功", map); + } + + /** + * 办理任务 + * + * @param completeTaskBo 办理任务参数 + */ + @Log(title = "任务管理", businessType = BusinessType.INSERT) + @RepeatSubmit() + @PostMapping("/completeTask") + public R completeTask(@Validated(AddGroup.class) @RequestBody CompleteTaskBo completeTaskBo) { + return toAjax(flwTaskService.completeTask(completeTaskBo)); + } + + /** + * 查询当前用户的待办任务 + * + * @param flowTaskBo 参数 + * @param pageQuery 分页 + */ + @GetMapping("/pageByTaskWait") + public TableDataInfo pageByTaskWait(FlowTaskBo flowTaskBo, PageQuery pageQuery) { + return flwTaskService.pageByTaskWait(flowTaskBo, pageQuery); + } + + /** + * 查询当前用户的已办任务 + * + * @param flowTaskBo 参数 + * @param pageQuery 分页 + */ + + @GetMapping("/pageByTaskFinish") + public TableDataInfo pageByTaskFinish(FlowTaskBo flowTaskBo, PageQuery pageQuery) { + return flwTaskService.pageByTaskFinish(flowTaskBo, pageQuery); + } + + /** + * 查询待办任务 + * + * @param flowTaskBo 参数 + * @param pageQuery 分页 + */ + @GetMapping("/pageByAllTaskWait") + public TableDataInfo pageByAllTaskWait(FlowTaskBo flowTaskBo, PageQuery pageQuery) { + return flwTaskService.pageByAllTaskWait(flowTaskBo, pageQuery); + } + + /** + * 查询已办任务 + * + * @param flowTaskBo 参数 + * @param pageQuery 分页 + */ + @GetMapping("/pageByAllTaskFinish") + public TableDataInfo pageByAllTaskFinish(FlowTaskBo flowTaskBo, PageQuery pageQuery) { + return flwTaskService.pageByAllTaskFinish(flowTaskBo, pageQuery); + } + + /** + * 查询当前用户的抄送 + * + * @param flowTaskBo 参数 + * @param pageQuery 分页 + */ + @GetMapping("/pageByTaskCopy") + public TableDataInfo pageByTaskCopy(FlowTaskBo flowTaskBo, PageQuery pageQuery) { + return flwTaskService.pageByTaskCopy(flowTaskBo, pageQuery); + } + + /** + * 根据taskId查询代表任务 + * + * @param taskId 任务id + */ + @GetMapping("/getTask/{taskId}") + public R getTask(@PathVariable Long taskId) { + return R.ok(flwTaskService.selectById(taskId)); + } + + /** + * 终止任务 + * + * @param bo 参数 + */ + @Log(title = "任务管理", businessType = BusinessType.INSERT) + @RepeatSubmit() + @PostMapping("/terminationTask") + public R terminationTask(@RequestBody FlowTerminationBo bo) { + return R.ok(flwTaskService.terminationTask(bo)); + } + + /** + * 任务操作 + * + * @param bo 参数 + * @param taskOperation 操作类型,委派 delegateTask、转办 transferTask、加签 addSignature、减签 reductionSignature + */ + @Log(title = "任务管理", businessType = BusinessType.UPDATE) + @RepeatSubmit + @PostMapping("/taskOperation/{taskOperation}") + public R taskOperation(@Validated @RequestBody TaskOperationBo bo, @PathVariable String taskOperation) { + return toAjax(flwTaskService.taskOperation(bo, taskOperation)); + } + + /** + * 修改任务办理人 + * + * @param taskIdList 任务id + * @param userId 办理人id + */ + @Log(title = "任务管理", businessType = BusinessType.UPDATE) + @RepeatSubmit() + @PutMapping("/updateAssignee/{userId}") + public R updateAssignee(@RequestBody List taskIdList, @PathVariable String userId) { + return toAjax(flwTaskService.updateAssignee(taskIdList, userId)); + } + + /** + * 驳回审批 + * + * @param bo 参数 + */ + @Log(title = "任务管理", businessType = BusinessType.INSERT) + @RepeatSubmit() + @PostMapping("/backProcess") + public R backProcess(@Validated({AddGroup.class}) @RequestBody BackProcessBo bo) { + return toAjax(flwTaskService.backProcess(bo)); + } + + /** + * 获取可驳回的前置节点 + * + * @param definitionId 流程定义id + * @param nowNodeCode 当前节点 + */ + @GetMapping("/getBackTaskNode/{definitionId}/{nowNodeCode}") + public R> getBackTaskNode(@PathVariable Long definitionId, @PathVariable String nowNodeCode) { + return R.ok(flwTaskService.getBackTaskNode(definitionId, nowNodeCode)); + } + + /** + * 获取当前任务的所有办理人 + * + * @param taskId 任务id + */ + @GetMapping("/currentTaskAllUser/{taskId}") + public R> currentTaskAllUser(@PathVariable Long taskId) { + return R.ok(flwTaskService.currentTaskAllUser(taskId)); + } + +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/WfCategoryController.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/WfCategoryController.java deleted file mode 100644 index 8dced8929..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/WfCategoryController.java +++ /dev/null @@ -1,106 +0,0 @@ -package org.dromara.workflow.controller; - -import cn.dev33.satoken.annotation.SaCheckPermission; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; -import lombok.RequiredArgsConstructor; -import org.dromara.common.core.domain.R; -import org.dromara.common.core.validate.AddGroup; -import org.dromara.common.core.validate.EditGroup; -import org.dromara.common.excel.utils.ExcelUtil; -import org.dromara.common.idempotent.annotation.RepeatSubmit; -import org.dromara.common.log.annotation.Log; -import org.dromara.common.log.enums.BusinessType; -import org.dromara.common.web.core.BaseController; -import org.dromara.workflow.domain.bo.WfCategoryBo; -import org.dromara.workflow.domain.vo.WfCategoryVo; -import org.dromara.workflow.service.IWfCategoryService; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -/** - * 流程分类 - * - * @author may - * @date 2023-06-28 - */ -@Validated -@RequiredArgsConstructor -@RestController -@RequestMapping("/workflow/category") -public class WfCategoryController extends BaseController { - - private final IWfCategoryService wfCategoryService; - - /** - * 查询流程分类列表 - */ - @SaCheckPermission("workflow:category:list") - @GetMapping("/list") - public R> list(WfCategoryBo bo) { - List list = wfCategoryService.queryList(bo); - return R.ok(list); - - } - - /** - * 导出流程分类列表 - */ - @SaCheckPermission("workflow:category:export") - @Log(title = "流程分类", businessType = BusinessType.EXPORT) - @PostMapping("/export") - public void export(WfCategoryBo bo, HttpServletResponse response) { - List list = wfCategoryService.queryList(bo); - ExcelUtil.exportExcel(list, "流程分类", WfCategoryVo.class, response); - } - - /** - * 获取流程分类详细信息 - * - * @param id 主键 - */ - @SaCheckPermission("workflow:category:query") - @GetMapping("/{id}") - public R getInfo(@NotNull(message = "主键不能为空") - @PathVariable Long id) { - return R.ok(wfCategoryService.queryById(id)); - } - - /** - * 新增流程分类 - */ - @SaCheckPermission("workflow:category:add") - @Log(title = "流程分类", businessType = BusinessType.INSERT) - @RepeatSubmit() - @PostMapping() - public R add(@Validated(AddGroup.class) @RequestBody WfCategoryBo bo) { - return toAjax(wfCategoryService.insertByBo(bo)); - } - - /** - * 修改流程分类 - */ - @SaCheckPermission("workflow:category:edit") - @Log(title = "流程分类", businessType = BusinessType.UPDATE) - @RepeatSubmit() - @PutMapping() - public R edit(@Validated(EditGroup.class) @RequestBody WfCategoryBo bo) { - return toAjax(wfCategoryService.updateByBo(bo)); - } - - /** - * 删除流程分类 - * - * @param ids 主键串 - */ - @SaCheckPermission("workflow:category:remove") - @Log(title = "流程分类", businessType = BusinessType.DELETE) - @DeleteMapping("/{ids}") - public R remove(@NotEmpty(message = "主键不能为空") - @PathVariable Long[] ids) { - return toAjax(wfCategoryService.deleteWithValidByIds(List.of(ids), true)); - } -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/WfDefinitionConfigController.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/WfDefinitionConfigController.java deleted file mode 100644 index 176aba2e4..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/WfDefinitionConfigController.java +++ /dev/null @@ -1,79 +0,0 @@ -package org.dromara.workflow.controller; - -import java.util.List; - -import lombok.RequiredArgsConstructor; -import jakarta.validation.constraints.*; -import org.dromara.workflow.domain.bo.WfDefinitionConfigBo; -import org.springframework.web.bind.annotation.*; -import org.springframework.validation.annotation.Validated; -import org.dromara.common.idempotent.annotation.RepeatSubmit; -import org.dromara.common.log.annotation.Log; -import org.dromara.common.web.core.BaseController; -import org.dromara.common.core.domain.R; -import org.dromara.common.core.validate.AddGroup; -import org.dromara.common.log.enums.BusinessType; -import org.dromara.workflow.domain.vo.WfDefinitionConfigVo; -import org.dromara.workflow.service.IWfDefinitionConfigService; - -/** - * 流程定义配置 - * - * @author may - * @date 2024-03-18 - */ -@Validated -@RequiredArgsConstructor -@RestController -@RequestMapping("/workflow/definitionConfig") -public class WfDefinitionConfigController extends BaseController { - - private final IWfDefinitionConfigService wfDefinitionConfigService; - - - /** - * 获取流程定义配置详细信息 - * - * @param definitionId 主键 - */ - @GetMapping("/getByDefId/{definitionId}") - public R getByDefId(@NotBlank(message = "流程定义ID不能为空") - @PathVariable String definitionId) { - return R.ok(wfDefinitionConfigService.getByDefId(definitionId)); - } - - /** - * 新增流程定义配置 - */ - @Log(title = "流程定义配置", businessType = BusinessType.INSERT) - @RepeatSubmit() - @PostMapping("/saveOrUpdate") - public R saveOrUpdate(@Validated(AddGroup.class) @RequestBody WfDefinitionConfigBo bo) { - return toAjax(wfDefinitionConfigService.saveOrUpdate(bo)); - } - - /** - * 删除流程定义配置 - * - * @param ids 主键串 - */ - @Log(title = "流程定义配置", businessType = BusinessType.DELETE) - @DeleteMapping("/{ids}") - public R remove(@NotEmpty(message = "主键不能为空") - @PathVariable Long[] ids) { - return toAjax(wfDefinitionConfigService.deleteByIds(List.of(ids))); - } - - /** - * 查询流程定义配置排除当前查询的流程定义 - * - * @param tableName 表名 - * @param definitionId 流程定义id - */ - @GetMapping("/getByTableNameNotDefId/{tableName}/{definitionId}") - public R> getByTableNameNotDefId(@NotBlank(message = "表名不能为空") @PathVariable String tableName, - @NotBlank(message = "流程定义ID不能为空") @PathVariable String definitionId) { - return R.ok(wfDefinitionConfigService.getByTableNameNotDefId(tableName, definitionId)); - } - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/WfFormManageController.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/WfFormManageController.java deleted file mode 100644 index 198e233b4..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/WfFormManageController.java +++ /dev/null @@ -1,114 +0,0 @@ -package org.dromara.workflow.controller; - -import java.util.List; - -import lombok.RequiredArgsConstructor; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.validation.constraints.*; -import cn.dev33.satoken.annotation.SaCheckPermission; -import org.springframework.web.bind.annotation.*; -import org.springframework.validation.annotation.Validated; -import org.dromara.common.idempotent.annotation.RepeatSubmit; -import org.dromara.common.log.annotation.Log; -import org.dromara.common.web.core.BaseController; -import org.dromara.common.mybatis.core.page.PageQuery; -import org.dromara.common.core.domain.R; -import org.dromara.common.core.validate.AddGroup; -import org.dromara.common.core.validate.EditGroup; -import org.dromara.common.log.enums.BusinessType; -import org.dromara.common.excel.utils.ExcelUtil; -import org.dromara.workflow.domain.vo.WfFormManageVo; -import org.dromara.workflow.domain.bo.WfFormManageBo; -import org.dromara.workflow.service.IWfFormManageService; -import org.dromara.common.mybatis.core.page.TableDataInfo; - -/** - * 表单管理 - * - * @author may - * @date 2024-03-29 - */ -@Validated -@RequiredArgsConstructor -@RestController -@RequestMapping("/workflow/formManage") -public class WfFormManageController extends BaseController { - - private final IWfFormManageService wfFormManageService; - - /** - * 查询表单管理列表 - */ - @SaCheckPermission("workflow:formManage:list") - @GetMapping("/list") - public TableDataInfo list(WfFormManageBo bo, PageQuery pageQuery) { - return wfFormManageService.queryPageList(bo, pageQuery); - } - - /** - * 查询表单管理列表 - */ - @SaCheckPermission("workflow:formManage:list") - @GetMapping("/list/selectList") - public R> selectList() { - return R.ok(wfFormManageService.selectList()); - } - - /** - * 导出表单管理列表 - */ - @SaCheckPermission("workflow:formManage:export") - @Log(title = "表单管理", businessType = BusinessType.EXPORT) - @PostMapping("/export") - public void export(WfFormManageBo bo, HttpServletResponse response) { - List list = wfFormManageService.queryList(bo); - ExcelUtil.exportExcel(list, "表单管理", WfFormManageVo.class, response); - } - - /** - * 获取表单管理详细信息 - * - * @param id 主键 - */ - @SaCheckPermission("workflow:formManage:query") - @GetMapping("/{id}") - public R getInfo(@NotNull(message = "主键不能为空") - @PathVariable Long id) { - return R.ok(wfFormManageService.queryById(id)); - } - - /** - * 新增表单管理 - */ - @SaCheckPermission("workflow:formManage:add") - @Log(title = "表单管理", businessType = BusinessType.INSERT) - @RepeatSubmit() - @PostMapping() - public R add(@Validated(AddGroup.class) @RequestBody WfFormManageBo bo) { - return toAjax(wfFormManageService.insertByBo(bo)); - } - - /** - * 修改表单管理 - */ - @SaCheckPermission("workflow:formManage:edit") - @Log(title = "表单管理", businessType = BusinessType.UPDATE) - @RepeatSubmit() - @PutMapping() - public R edit(@Validated(EditGroup.class) @RequestBody WfFormManageBo bo) { - return toAjax(wfFormManageService.updateByBo(bo)); - } - - /** - * 删除表单管理 - * - * @param ids 主键串 - */ - @SaCheckPermission("workflow:formManage:remove") - @Log(title = "表单管理", businessType = BusinessType.DELETE) - @DeleteMapping("/{ids}") - public R remove(@NotEmpty(message = "主键不能为空") - @PathVariable Long[] ids) { - return toAjax(wfFormManageService.deleteByIds(List.of(ids))); - } -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/ActHiProcinst.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/ActHiProcinst.java deleted file mode 100644 index e87fb9253..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/ActHiProcinst.java +++ /dev/null @@ -1,152 +0,0 @@ -package org.dromara.workflow.domain; - -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.Data; - -import java.io.Serial; -import java.io.Serializable; -import java.util.Date; - -/** - * 流程实例对象 act_hi_procinst - * - * @author may - * @date 2023-07-22 - */ -@Data -@TableName("act_hi_procinst") -public class ActHiProcinst implements Serializable { - - @Serial - private static final long serialVersionUID = 1L; - - /** - * - */ - @TableId(value = "ID_") - private String id; - - /** - * - */ - @TableField(value = "REV_") - private Long rev; - - /** - * - */ - @TableField(value = "PROC_INST_ID_") - private String procInstId; - - /** - * - */ - @TableField(value = "BUSINESS_KEY_") - private String businessKey; - - /** - * - */ - @TableField(value = "PROC_DEF_ID_") - private String procDefId; - - /** - * - */ - @TableField(value = "START_TIME_") - private Date startTime; - - /** - * - */ - @TableField(value = "END_TIME_") - private Date endTime; - - /** - * - */ - @TableField(value = "DURATION_") - private Long duration; - - /** - * - */ - @TableField(value = "START_USER_ID_") - private String startUserId; - - /** - * - */ - @TableField(value = "START_ACT_ID_") - private String startActId; - - /** - * - */ - @TableField(value = "END_ACT_ID_") - private String endActId; - - /** - * - */ - @TableField(value = "SUPER_PROCESS_INSTANCE_ID_") - private String superProcessInstanceId; - - /** - * - */ - @TableField(value = "DELETE_REASON_") - private String deleteReason; - - /** - * - */ - @TableField(value = "TENANT_ID_") - private String tenantId; - - /** - * - */ - @TableField(value = "NAME_") - private String name; - - /** - * - */ - @TableField(value = "CALLBACK_ID_") - private String callbackId; - - /** - * - */ - @TableField(value = "CALLBACK_TYPE_") - private String callbackType; - - /** - * - */ - @TableField(value = "REFERENCE_ID_") - private String referenceId; - - /** - * - */ - @TableField(value = "REFERENCE_TYPE_") - private String referenceType; - - /** - * - */ - @TableField(value = "PROPAGATED_STAGE_INST_ID_") - private String propagatedStageInstId; - - /** - * - */ - @TableField(value = "BUSINESS_STATUS_") - private String businessStatus; - - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/ActHiTaskinst.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/ActHiTaskinst.java deleted file mode 100644 index abc17b54c..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/ActHiTaskinst.java +++ /dev/null @@ -1,193 +0,0 @@ -package org.dromara.workflow.domain; - -import com.baomidou.mybatisplus.annotation.*; -import lombok.Data; - -import java.io.Serializable; -import java.util.Date; - -import java.io.Serial; - -/** - * 流程历史任务对象 act_hi_taskinst - * - * @author may - * @date 2024-03-02 - */ -@Data -@TableName("act_hi_taskinst") -public class ActHiTaskinst implements Serializable { - - @Serial - private static final long serialVersionUID = 1L; - - /** - * - */ - @TableId(value = "ID_") - private String id; - - /** - * 版本 - */ - @TableField(value = "REV_") - private Long rev; - - /** - * 流程定义id - */ - @TableField(value = "PROC_DEF_ID_") - private String procDefId; - - /** - * - */ - @TableField(value = "TASK_DEF_ID_") - private String taskDefId; - - /** - * 任务节点id - */ - @TableField(value = "TASK_DEF_KEY_") - private String taskDefKey; - - /** - * 流程实例id - */ - @TableField(value = "PROC_INST_ID_") - private String procInstId; - - /** - * 流程执行id - */ - @TableField(value = "EXECUTION_ID") - private String executionId; - - /** - * - */ - @TableField(value = "SCOPE_ID_") - private String scopeId; - - /** - * - */ - @TableField(value = "SUB_SCOPE_ID_") - private String subScopeId; - - /** - * 先用当前字段标识抄送类型 - */ - @TableField(value = "SCOPE_TYPE_") - private String scopeType; - - /** - * - */ - @TableField(value = "SCOPE_DEFINITION_ID_") - private String scopeDefinitionId; - - /** - * - */ - @TableField(value = "PROPAGATED_STAGE_INST_ID_") - private String propagatedStageInstId; - - /** - * 任务名称 - */ - @TableField(value = "NAME_") - private String name; - - /** - * 父级id - */ - @TableField(value = "PARENT_TASK_ID_") - private String parentTaskId; - - /** - * 描述 - */ - @TableField(value = "DESCRIPTION_") - private String description; - - /** - * 办理人 - */ - @TableField(value = "OWNER_") - private String owner; - - /** - * 办理人 - */ - @TableField(value = "ASSIGNEE_") - private String assignee; - - /** - * 开始事件 - */ - @TableField(value = "START_TIME_") - private Date startTime; - - /** - * 认领时间 - */ - @TableField(value = "CLAIM_TIME_") - private Date claimTime; - - /** - * 结束时间 - */ - @TableField(value = "END_TIME_") - private Date endTime; - - /** - * 持续时间 - */ - @TableField(value = "DURATION_") - private Long duration; - - /** - * 删除原因 - */ - @TableField(value = "DELETE_REASON_") - private String deleteReason; - - /** - * 优先级 - */ - @TableField(value = "PRIORITY_") - private Long priority; - - /** - * 到期时间 - */ - @TableField(value = "DUE_DATE_") - private Date dueDate; - - /** - * - */ - @TableField(value = "FORM_KEY_") - private String formKey; - - /** - * 分类 - */ - @TableField(value = "CATEGORY_") - private String category; - - /** - * 最后修改时间 - */ - @TableField(value = "LAST_UPDATED_TIME_") - private Date lastUpdatedTime; - - /** - * 租户id - */ - @TableField(value = "TENANT_ID_") - private String tenantId; - - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/WfCategory.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/FlowCategory.java similarity index 56% rename from ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/WfCategory.java rename to ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/FlowCategory.java index 94a7cf500..2ec297c5a 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/WfCategory.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/FlowCategory.java @@ -1,6 +1,7 @@ package org.dromara.workflow.domain; import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableLogic; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; import lombok.EqualsAndHashCode; @@ -16,37 +17,42 @@ import java.io.Serial; */ @Data @EqualsAndHashCode(callSuper = true) -@TableName("wf_category") -public class WfCategory extends TenantEntity { +@TableName("flow_category") +public class FlowCategory extends TenantEntity { @Serial private static final long serialVersionUID = 1L; /** - * 主键 + * 流程分类ID */ - @TableId(value = "id") - private Long id; + @TableId(value = "category_id") + private Long categoryId; /** - * 分类名称 - */ - private String categoryName; - - /** - * 分类编码 - */ - private String categoryCode; - - /** - * 父级id + * 父流程分类id */ private Long parentId; /** - * 排序 + * 祖级列表 */ - private Long sortNum; + private String ancestors; + /** + * 流程分类名称 + */ + private String categoryName; + + /** + * 显示顺序 + */ + private Long orderNum; + + /** + * 删除标志(0代表存在 2代表删除) + */ + @TableLogic + private String delFlag; } diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/WfDefinitionConfig.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/WfDefinitionConfig.java deleted file mode 100644 index 11dcaa081..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/WfDefinitionConfig.java +++ /dev/null @@ -1,56 +0,0 @@ -package org.dromara.workflow.domain; - -import org.dromara.common.mybatis.core.domain.BaseEntity; -import com.baomidou.mybatisplus.annotation.*; -import lombok.Data; -import lombok.EqualsAndHashCode; - -import java.io.Serial; - -/** - * 流程定义配置对象 wf_definition_config - * - * @author may - * @date 2024-03-18 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@TableName("wf_definition_config") -public class WfDefinitionConfig extends BaseEntity { - - @Serial - private static final long serialVersionUID = 1L; - - /** - * 主键 - */ - @TableId(value = "id") - private Long id; - - /** - * 表名 - */ - private String tableName; - - /** - * 流程定义ID - */ - private String definitionId; - - /** - * 流程KEY - */ - private String processKey; - - /** - * 流程版本 - */ - private Integer version; - - /** - * 备注 - */ - private String remark; - - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/WfFormManage.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/WfFormManage.java deleted file mode 100644 index 47f0d7a58..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/WfFormManage.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.dromara.workflow.domain; - -import org.dromara.common.tenant.core.TenantEntity; -import com.baomidou.mybatisplus.annotation.*; -import lombok.Data; -import lombok.EqualsAndHashCode; - -import java.io.Serial; - -/** - * 表单管理对象 wf_form_manage - * - * @author may - * @date 2024-03-29 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@TableName("wf_form_manage") -public class WfFormManage extends TenantEntity { - - @Serial - private static final long serialVersionUID = 1L; - - /** - * 主键 - */ - @TableId(value = "id") - private Long id; - - /** - * 表单名称 - */ - private String formName; - - /** - * 表单类型 - */ - private String formType; - - /** - * 路由地址/表单ID - */ - private String router; - - /** - * 备注 - */ - private String remark; - - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/WfNodeConfig.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/WfNodeConfig.java deleted file mode 100644 index 999425f53..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/WfNodeConfig.java +++ /dev/null @@ -1,61 +0,0 @@ -package org.dromara.workflow.domain; - -import org.dromara.common.tenant.core.TenantEntity; -import com.baomidou.mybatisplus.annotation.*; -import lombok.Data; -import lombok.EqualsAndHashCode; - -import java.io.Serial; - -/** - * 节点配置对象 wf_node_config - * - * @author may - * @date 2024-03-30 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@TableName("wf_node_config") -public class WfNodeConfig extends TenantEntity { - - @Serial - private static final long serialVersionUID = 1L; - - /** - * 主键 - */ - @TableId(value = "id") - private Long id; - - /** - * 表单id - */ - private Long formId; - - /** - * 表单类型 - */ - private String formType; - - /** - * 节点名称 - */ - private String nodeName; - - /** - * 节点id - */ - private String nodeId; - - /** - * 流程定义id - */ - private String definitionId; - - /** - * 是否为申请人节点 (0是 1否) - */ - private String applyUserTask; - - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/WfTaskBackNode.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/WfTaskBackNode.java deleted file mode 100644 index 6f5972794..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/WfTaskBackNode.java +++ /dev/null @@ -1,61 +0,0 @@ -package org.dromara.workflow.domain; - -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.Data; -import lombok.EqualsAndHashCode; -import org.dromara.common.tenant.core.TenantEntity; - -import java.io.Serial; - -/** - * 节点驳回记录 wf_task_back_node - * - * @author may - * @date 2024-03-13 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@TableName("wf_task_back_node") -public class WfTaskBackNode extends TenantEntity { - - @Serial - private static final long serialVersionUID = 1L; - - /** - * 主键 - */ - @TableId(value = "id") - private Long id; - - /** - * 实例id - */ - private String instanceId; - - /** - * 节点id - */ - private String nodeId; - - /** - * 节点名称 - */ - private String nodeName; - - /** - * 排序 - */ - private Integer orderNo; - - /** - * 节点类型 - */ - private String taskType; - - /** - * 办理人 - */ - private String assignee; - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/AddMultiBo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/AddMultiBo.java deleted file mode 100644 index 320ec64ca..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/AddMultiBo.java +++ /dev/null @@ -1,40 +0,0 @@ -package org.dromara.workflow.domain.bo; - -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotEmpty; -import lombok.Data; -import org.dromara.common.core.validate.AddGroup; - -import java.io.Serial; -import java.io.Serializable; -import java.util.List; - -/** - * 加签参数请求 - * - * @author may - */ -@Data -public class AddMultiBo implements Serializable { - - @Serial - private static final long serialVersionUID = 1L; - - /** - * 任务ID - */ - @NotBlank(message = "任务ID不能为空", groups = AddGroup.class) - private String taskId; - - /** - * 加签人员id - */ - @NotEmpty(message = "加签人员不能为空", groups = AddGroup.class) - private List assignees; - - /** - * 加签人员名称 - */ - @NotEmpty(message = "加签人员不能为空", groups = AddGroup.class) - private List assigneeNames; -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/BackProcessBo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/BackProcessBo.java index d0f436925..80b9691d9 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/BackProcessBo.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/BackProcessBo.java @@ -1,12 +1,16 @@ package org.dromara.workflow.domain.bo; import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; import lombok.Data; import org.dromara.common.core.validate.AddGroup; import java.io.Serial; import java.io.Serializable; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.Objects; /** @@ -23,8 +27,8 @@ public class BackProcessBo implements Serializable { /** * 任务ID */ - @NotBlank(message = "任务ID不能为空", groups = AddGroup.class) - private String taskId; + @NotNull(message = "任务ID不能为空", groups = AddGroup.class) + private Long taskId; /** * 消息类型 @@ -35,10 +39,28 @@ public class BackProcessBo implements Serializable { * 驳回的节点id(目前未使用,直接驳回到申请人) */ @NotBlank(message = "驳回的节点不能为空", groups = AddGroup.class) - private String targetActivityId; + private String nodeCode; /** * 办理意见 */ private String message; + + /** + * 通知 + */ + private String notice; + + /** + * 流程变量 + */ + private Map variables; + + public Map getVariables() { + if (variables == null) { + return new HashMap<>(16); + } + variables.entrySet().removeIf(entry -> Objects.isNull(entry.getValue())); + return variables; + } } diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/CompleteTaskBo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/CompleteTaskBo.java index 062390551..9fdf48478 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/CompleteTaskBo.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/CompleteTaskBo.java @@ -1,9 +1,8 @@ package org.dromara.workflow.domain.bo; -import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; import lombok.Data; import org.dromara.common.core.validate.AddGroup; -import org.dromara.workflow.domain.vo.WfCopy; import java.io.Serial; import java.io.Serializable; @@ -26,8 +25,8 @@ public class CompleteTaskBo implements Serializable { /** * 任务id */ - @NotBlank(message = "任务id不能为空", groups = {AddGroup.class}) - private String taskId; + @NotNull(message = "任务id不能为空", groups = {AddGroup.class}) + private Long taskId; /** * 附件id @@ -37,7 +36,7 @@ public class CompleteTaskBo implements Serializable { /** * 抄送人员 */ - private List wfCopyList; + private List flowCopyList; /** * 消息类型 @@ -49,11 +48,22 @@ public class CompleteTaskBo implements Serializable { */ private String message; + /** + * 消息通知 + */ + private String notice; + /** * 流程变量 */ private Map variables; + /** + * 扩展变量(此处为逗号分隔的ossId) + * @return + */ + private String ext; + public Map getVariables() { if (variables == null) { return new HashMap<>(16); diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/DelegateBo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/DelegateBo.java deleted file mode 100644 index a6846a6d6..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/DelegateBo.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.dromara.workflow.domain.bo; - -import jakarta.validation.constraints.NotBlank; -import lombok.Data; -import org.dromara.common.core.validate.AddGroup; - -import java.io.Serial; -import java.io.Serializable; - -/** - * 委派任务请求对象 - * - * @author may - */ -@Data -public class DelegateBo implements Serializable { - - @Serial - private static final long serialVersionUID = 1L; - - /** - * 委派人id - */ - @NotBlank(message = "委派人id不能为空", groups = {AddGroup.class}) - private String userId; - - /** - * 委派人名称 - */ - @NotBlank(message = "委派人名称不能为空", groups = {AddGroup.class}) - private String nickName; - - /** - * 任务id - */ - @NotBlank(message = "任务id不能为空", groups = {AddGroup.class}) - private String taskId; -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/DeleteMultiBo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/DeleteMultiBo.java deleted file mode 100644 index e533167d9..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/DeleteMultiBo.java +++ /dev/null @@ -1,52 +0,0 @@ -package org.dromara.workflow.domain.bo; - -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotEmpty; -import lombok.Data; -import org.dromara.common.core.validate.AddGroup; - -import java.io.Serial; -import java.io.Serializable; -import java.util.List; - -/** - * 减签参数请求 - * - * @author may - */ -@Data -public class DeleteMultiBo implements Serializable { - - @Serial - private static final long serialVersionUID = 1L; - - /** - * 任务ID - */ - @NotBlank(message = "任务ID不能为空", groups = AddGroup.class) - private String taskId; - - /** - * 减签人员 - */ - @NotEmpty(message = "减签人员不能为空", groups = AddGroup.class) - private List taskIds; - - /** - * 执行id - */ - @NotEmpty(message = "执行id不能为空", groups = AddGroup.class) - private List executionIds; - - /** - * 人员id - */ - @NotEmpty(message = "减签人员id不能为空", groups = AddGroup.class) - private List assigneeIds; - - /** - * 人员名称 - */ - @NotEmpty(message = "减签人员不能为空", groups = AddGroup.class) - private List assigneeNames; -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/ProcessInvalidBo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowCancelBo.java similarity index 56% rename from ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/ProcessInvalidBo.java rename to ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowCancelBo.java index 41e51c2a6..31742ea79 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/ProcessInvalidBo.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowCancelBo.java @@ -8,24 +8,24 @@ import java.io.Serial; import java.io.Serializable; /** - * 流程实例作废请求对象 + * 撤销任务请求对象 * * @author may */ @Data -public class ProcessInvalidBo implements Serializable { +public class FlowCancelBo implements Serializable { @Serial private static final long serialVersionUID = 1L; /** - * 业务id + * 任务ID */ - @NotBlank(message = "业务id不能为空", groups = {AddGroup.class}) - private String businessKey; + @NotBlank(message = "业务ID不能为空", groups = AddGroup.class) + private String businessId; /** - * 作废原因 + * 办理意见 */ - private String deleteReason; + private String message; } diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowCategoryBo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowCategoryBo.java new file mode 100644 index 000000000..fd626eb0d --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowCategoryBo.java @@ -0,0 +1,47 @@ +package org.dromara.workflow.domain.bo; + +import io.github.linpeilie.annotations.AutoMapper; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.dromara.common.core.validate.AddGroup; +import org.dromara.common.core.validate.EditGroup; +import org.dromara.common.mybatis.core.domain.BaseEntity; +import org.dromara.workflow.domain.FlowCategory; + +/** + * 流程分类业务对象 wf_category + * + * @author may + * @date 2023-06-27 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@AutoMapper(target = FlowCategory.class, reverseConvertGenerate = false) +public class FlowCategoryBo extends BaseEntity { + + /** + * 流程分类ID + */ + @NotNull(message = "流程分类ID不能为空", groups = { EditGroup.class }) + private Long categoryId; + + /** + * 父流程分类id + */ + @NotNull(message = "父流程分类id不能为空", groups = {AddGroup.class, EditGroup.class}) + private Long parentId; + + /** + * 流程分类名称 + */ + @NotBlank(message = "流程分类名称不能为空", groups = {AddGroup.class, EditGroup.class}) + private String categoryName; + + /** + * 显示顺序 + */ + private Long orderNum; + +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/WfCopy.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowCopyBo.java similarity index 77% rename from ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/WfCopy.java rename to ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowCopyBo.java index 88a5a2184..a45e52109 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/WfCopy.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowCopyBo.java @@ -1,17 +1,18 @@ -package org.dromara.workflow.domain.vo; +package org.dromara.workflow.domain.bo; import lombok.Data; import java.io.Serial; import java.io.Serializable; + /** * 抄送 * * @author may */ @Data -public class WfCopy implements Serializable { +public class FlowCopyBo implements Serializable { @Serial private static final long serialVersionUID = 1L; diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowInstanceBo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowInstanceBo.java new file mode 100644 index 000000000..fb1fe611b --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowInstanceBo.java @@ -0,0 +1,55 @@ +package org.dromara.workflow.domain.bo; + +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; +import java.util.List; + +/** + * 流程实例请求对象 + * + * @author may + */ +@Data +public class FlowInstanceBo implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 流程定义名称 + */ + private String flowName; + + /** + * 流程定义编码 + */ + private String flowCode; + + /** + * 任务发起人 + */ + private String startUserId; + + /** + * 业务id + */ + private String businessId; + + /** + * 流程分类id + */ + private String category; + + /** + * 任务名称 + */ + private String nodeName; + + /** + * 申请人Ids + */ + private List createByIds; + +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowInvalidBo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowInvalidBo.java new file mode 100644 index 000000000..297bd00d9 --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowInvalidBo.java @@ -0,0 +1,31 @@ +package org.dromara.workflow.domain.bo; + +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import org.dromara.common.core.validate.AddGroup; + +import java.io.Serial; +import java.io.Serializable; + +/** + * 作废请求对象 + * + * @author may + */ +@Data +public class FlowInvalidBo implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 流程实例id + */ + @NotNull(message = "流程实例id为空", groups = AddGroup.class) + private Long id; + + /** + * 审批意见 + */ + private String comment; +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowTaskBo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowTaskBo.java new file mode 100644 index 000000000..64dd08255 --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowTaskBo.java @@ -0,0 +1,55 @@ +package org.dromara.workflow.domain.bo; + +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; +import java.util.List; + +/** + * 任务请求对象 + * + * @author may + */ +@Data +public class FlowTaskBo implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 任务名称 + */ + private String nodeName; + + /** + * 流程定义名称 + */ + private String flowName; + + /** + * 流程定义编码 + */ + private String flowCode; + + /** + * 流程分类id + */ + private String category; + + /** + * 流程实例id + */ + private Long instanceId; + + /** + * 权限列表 + */ + private List permissionList; + + /** + * 申请人Ids + */ + private List createByIds; + +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/TerminationBo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowTerminationBo.java similarity index 66% rename from ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/TerminationBo.java rename to ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowTerminationBo.java index 8f2206e82..897fc21ee 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/TerminationBo.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowTerminationBo.java @@ -1,6 +1,6 @@ package org.dromara.workflow.domain.bo; -import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; import lombok.Data; import org.dromara.common.core.validate.AddGroup; @@ -13,7 +13,7 @@ import java.io.Serializable; * @author may */ @Data -public class TerminationBo implements Serializable { +public class FlowTerminationBo implements Serializable { @Serial private static final long serialVersionUID = 1L; @@ -21,8 +21,8 @@ public class TerminationBo implements Serializable { /** * 任务id */ - @NotBlank(message = "任务id为空", groups = AddGroup.class) - private String taskId; + @NotNull(message = "任务id为空", groups = AddGroup.class) + private Long taskId; /** * 审批意见 diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/ModelBo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/ModelBo.java deleted file mode 100644 index efe9acddb..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/ModelBo.java +++ /dev/null @@ -1,66 +0,0 @@ -package org.dromara.workflow.domain.bo; - -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.Pattern; -import lombok.Data; -import org.dromara.common.core.validate.AddGroup; -import org.dromara.common.core.validate.EditGroup; -import org.dromara.workflow.common.constant.FlowConstant; - -import java.io.Serial; -import java.io.Serializable; - -/** - * 模型请求对象 - * - * @author may - */ -@Data -public class ModelBo implements Serializable { - - @Serial - private static final long serialVersionUID = 1L; - - /** - * 模型id - */ - @NotBlank(message = "模型ID不能为空", groups = {EditGroup.class}) - private String id; - - /** - * 模型名称 - */ - @NotBlank(message = "模型名称不能为空", groups = {AddGroup.class}) - private String name; - - /** - * 模型标识key - */ - @NotBlank(message = "模型标识key不能为空", groups = {AddGroup.class}) - @Pattern(regexp = FlowConstant.MODEL_KEY_PATTERN, message = "模型标识key只能字符或者下划线开头", groups = {AddGroup.class}) - private String key; - - /** - * 模型分类 - */ - @NotBlank(message = "模型分类不能为空", groups = {AddGroup.class}) - private String categoryCode; - - /** - * 模型XML - */ - @NotBlank(message = "模型XML不能为空", groups = {AddGroup.class}) - private String xml; - - /** - * 模型SVG图片 - */ - @NotBlank(message = "模型SVG不能为空", groups = {EditGroup.class}) - private String svg; - - /** - * 备注 - */ - private String description; - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/ProcessDefinitionBo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/ProcessDefinitionBo.java deleted file mode 100644 index 2025932ba..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/ProcessDefinitionBo.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.dromara.workflow.domain.bo; - -import lombok.Data; - -import java.io.Serial; -import java.io.Serializable; - -/** - * 流程定义请求对象 - * - * @author may - */ -@Data -public class ProcessDefinitionBo implements Serializable { - - @Serial - private static final long serialVersionUID = 1L; - - /** - * 流程定义名称key - */ - private String key; - - /** - * 流程定义名称 - */ - private String name; - - /** - * 模型分类 - */ - private String categoryCode; - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/ProcessInstanceBo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/ProcessInstanceBo.java deleted file mode 100644 index 2833b3ecb..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/ProcessInstanceBo.java +++ /dev/null @@ -1,43 +0,0 @@ -package org.dromara.workflow.domain.bo; - -import lombok.Data; - -import java.io.Serial; -import java.io.Serializable; - -/** - * 流程实例请求对象 - * - * @author may - */ -@Data -public class ProcessInstanceBo implements Serializable { - - @Serial - private static final long serialVersionUID = 1L; - - /** - * 流程名称 - */ - private String name; - - /** - * 流程key - */ - private String key; - - /** - * 任务发起人 - */ - private String startUserId; - - /** - * 业务id - */ - private String businessKey; - - /** - * 模型分类 - */ - private String categoryCode; -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/StartProcessBo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/StartProcessBo.java index 7af7935e6..ea21a81e7 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/StartProcessBo.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/StartProcessBo.java @@ -26,13 +26,13 @@ public class StartProcessBo implements Serializable { * 业务唯一值id */ @NotBlank(message = "业务ID不能为空", groups = {AddGroup.class}) - private String businessKey; + private String businessId; /** - * 表名 + * 流程定义编码 */ - @NotBlank(message = "表名不能为空", groups = {AddGroup.class}) - private String tableName; + @NotBlank(message = "流程定义编码不能为空", groups = {AddGroup.class}) + private String flowCode; /** * 流程变量,前端会提交一个元素{'entity': {业务详情数据对象}} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/SysUserMultiBo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/SysUserMultiBo.java deleted file mode 100644 index e4d99e47a..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/SysUserMultiBo.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.dromara.workflow.domain.bo; - -import lombok.Data; - -import java.io.Serial; -import java.io.Serializable; - - -/** - * 用户加签查询 - * - * @author may - */ -@Data -public class SysUserMultiBo implements Serializable { - - @Serial - private static final long serialVersionUID = 1L; - - /** - * 人员名称 - */ - private String userName; - - /** - * 人员名称 - */ - private String nickName; - - /** - * 部门id - */ - private String deptId; - - /** - * 任务id - */ - private String taskId; -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/TaskBo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/TaskBo.java deleted file mode 100644 index 303747939..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/TaskBo.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.dromara.workflow.domain.bo; - -import lombok.Data; - -import java.io.Serial; -import java.io.Serializable; - -/** - * 任务请求对象 - * - * @author may - */ -@Data -public class TaskBo implements Serializable { - - @Serial - private static final long serialVersionUID = 1L; - - /** - * 任务名称 - */ - private String name; - - /** - * 流程定义名称 - */ - private String processDefinitionName; - - /** - * 流程定义key - */ - private String processDefinitionKey; -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/TaskOperationBo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/TaskOperationBo.java new file mode 100644 index 000000000..4348e310c --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/TaskOperationBo.java @@ -0,0 +1,48 @@ +package org.dromara.workflow.domain.bo; + +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import org.dromara.common.core.validate.AddGroup; +import org.dromara.common.core.validate.EditGroup; + +import java.io.Serial; +import java.io.Serializable; +import java.util.List; + + +/** + * 任务操作业务对象,用于描述任务委派、转办、加签等操作的必要参数 + * 包含了用户ID、任务ID、任务相关的消息、以及加签/减签的用户ID + * + * @author AprilWind + */ +@Data +public class TaskOperationBo implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 委派/转办人的用户ID(必填,准对委派/转办人操作) + */ + @NotNull(message = "委派/转办人id不能为空", groups = {AddGroup.class}) + private String userId; + + /** + * 加签/减签人的用户ID列表(必填,针对加签/减签操作) + */ + @NotNull(message = "加签/减签id不能为空", groups = {EditGroup.class}) + private List userIds; + + /** + * 任务ID(必填) + */ + @NotNull(message = "任务id不能为空") + private Long taskId; + + /** + * 意见或备注信息(可选) + */ + private String message; + +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/TaskUrgingBo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/TaskUrgingBo.java deleted file mode 100644 index 20856efa9..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/TaskUrgingBo.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.dromara.workflow.domain.bo; - -import lombok.Data; - -import java.io.Serial; -import java.io.Serializable; -import java.util.List; - -/** - * 任务催办 - * - * @author may - */ -@Data -public class TaskUrgingBo implements Serializable { - - @Serial - private static final long serialVersionUID = 1L; - - /** - * 流程实例id - */ - private String processInstanceId; - - /** - * 消息类型 - */ - private List messageType; - - /** - * 催办内容(为空默认系统内置信息) - */ - private String message; -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/TestLeaveBo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/TestLeaveBo.java index 877e98160..a1a4b5968 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/TestLeaveBo.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/TestLeaveBo.java @@ -53,7 +53,6 @@ public class TestLeaveBo extends BaseEntity { /** * 请假天数 */ - @NotNull(message = "请假天数不能为空", groups = {AddGroup.class, EditGroup.class}) private Integer leaveDays; /** diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/TransmitBo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/TransmitBo.java deleted file mode 100644 index 3eb6609fd..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/TransmitBo.java +++ /dev/null @@ -1,37 +0,0 @@ -package org.dromara.workflow.domain.bo; - -import jakarta.validation.constraints.NotBlank; -import lombok.Data; -import org.dromara.common.core.validate.AddGroup; - -import java.io.Serial; -import java.io.Serializable; - -/** - * 终转办务请求对象 - * - * @author may - */ -@Data -public class TransmitBo implements Serializable { - - @Serial - private static final long serialVersionUID = 1L; - - /** - * 任务id - */ - @NotBlank(message = "任务id为空", groups = AddGroup.class) - private String taskId; - - /** - * 转办人id - */ - @NotBlank(message = "转办人不能为空", groups = AddGroup.class) - private String userId; - - /** - * 审批意见 - */ - private String comment; -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/WfCategoryBo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/WfCategoryBo.java deleted file mode 100644 index 69608fda3..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/WfCategoryBo.java +++ /dev/null @@ -1,54 +0,0 @@ -package org.dromara.workflow.domain.bo; - -import io.github.linpeilie.annotations.AutoMapper; -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import lombok.Data; -import lombok.EqualsAndHashCode; -import org.dromara.common.core.validate.AddGroup; -import org.dromara.common.core.validate.EditGroup; -import org.dromara.common.mybatis.core.domain.BaseEntity; -import org.dromara.workflow.domain.WfCategory; - -/** - * 流程分类业务对象 wf_category - * - * @author may - * @date 2023-06-27 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@AutoMapper(target = WfCategory.class, reverseConvertGenerate = false) -public class WfCategoryBo extends BaseEntity { - - /** - * 主键 - */ - @NotNull(message = "主键不能为空", groups = {EditGroup.class}) - private Long id; - - /** - * 分类名称 - */ - @NotBlank(message = "分类名称不能为空", groups = {AddGroup.class, EditGroup.class}) - private String categoryName; - - /** - * 分类编码 - */ - @NotBlank(message = "分类编码不能为空", groups = {AddGroup.class, EditGroup.class}) - private String categoryCode; - - /** - * 父级id - */ - @NotNull(message = "父级id不能为空", groups = {AddGroup.class, EditGroup.class}) - private Long parentId; - - /** - * 排序 - */ - private Long sortNum; - - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/WfDefinitionConfigBo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/WfDefinitionConfigBo.java deleted file mode 100644 index fac17709a..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/WfDefinitionConfigBo.java +++ /dev/null @@ -1,59 +0,0 @@ -package org.dromara.workflow.domain.bo; - -import org.dromara.workflow.domain.WfDefinitionConfig; -import org.dromara.common.mybatis.core.domain.BaseEntity; -import org.dromara.common.core.validate.AddGroup; -import org.dromara.common.core.validate.EditGroup; -import io.github.linpeilie.annotations.AutoMapper; -import lombok.Data; -import lombok.EqualsAndHashCode; -import jakarta.validation.constraints.*; - -/** - * 流程定义配置业务对象 wf_form_definition - * - * @author may - * @date 2024-03-18 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@AutoMapper(target = WfDefinitionConfig.class, reverseConvertGenerate = false) -public class WfDefinitionConfigBo extends BaseEntity { - - /** - * 主键 - */ - @NotNull(message = "主键不能为空", groups = {EditGroup.class}) - private Long id; - - /** - * 表名 - */ - @NotBlank(message = "表名不能为空", groups = {AddGroup.class}) - private String tableName; - - /** - * 流程定义ID - */ - @NotBlank(message = "流程定义ID不能为空", groups = {AddGroup.class}) - private String definitionId; - - /** - * 流程KEY - */ - @NotBlank(message = "流程KEY不能为空", groups = {AddGroup.class}) - private String processKey; - - /** - * 流程版本 - */ - @NotNull(message = "流程版本不能为空", groups = {AddGroup.class}) - private Integer version; - - /** - * 备注 - */ - private String remark; - - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/WfFormManageBo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/WfFormManageBo.java deleted file mode 100644 index 8afc286db..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/WfFormManageBo.java +++ /dev/null @@ -1,53 +0,0 @@ -package org.dromara.workflow.domain.bo; - -import org.dromara.workflow.domain.WfFormManage; -import org.dromara.common.mybatis.core.domain.BaseEntity; -import org.dromara.common.core.validate.AddGroup; -import org.dromara.common.core.validate.EditGroup; -import io.github.linpeilie.annotations.AutoMapper; -import lombok.Data; -import lombok.EqualsAndHashCode; -import jakarta.validation.constraints.*; - -/** - * 表单管理业务对象 wf_form_manage - * - * @author may - * @date 2024-03-29 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@AutoMapper(target = WfFormManage.class, reverseConvertGenerate = false) -public class WfFormManageBo extends BaseEntity { - - /** - * 主键 - */ - @NotNull(message = "主键不能为空", groups = { EditGroup.class }) - private Long id; - - /** - * 表单名称 - */ - @NotBlank(message = "表单名称不能为空", groups = { AddGroup.class, EditGroup.class }) - private String formName; - - /** - * 表单类型 - */ - @NotBlank(message = "表单类型不能为空", groups = { AddGroup.class, EditGroup.class }) - private String formType; - /** - * 路由地址/表单ID - */ - @NotBlank(message = "路由地址/表单ID不能为空", groups = { AddGroup.class, EditGroup.class }) - private String router; - - - /** - * 备注 - */ - private String remark; - - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/WfNodeConfigBo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/WfNodeConfigBo.java deleted file mode 100644 index de518d3dd..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/WfNodeConfigBo.java +++ /dev/null @@ -1,63 +0,0 @@ -package org.dromara.workflow.domain.bo; - -import org.dromara.workflow.domain.WfNodeConfig; -import org.dromara.common.mybatis.core.domain.BaseEntity; -import org.dromara.common.core.validate.AddGroup; -import org.dromara.common.core.validate.EditGroup; -import io.github.linpeilie.annotations.AutoMapper; -import lombok.Data; -import lombok.EqualsAndHashCode; -import jakarta.validation.constraints.*; - -/** - * 节点配置业务对象 wf_node_config - * - * @author may - * @date 2024-03-30 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@AutoMapper(target = WfNodeConfig.class, reverseConvertGenerate = false) -public class WfNodeConfigBo extends BaseEntity { - - /** - * 主键 - */ - @NotNull(message = "主键不能为空", groups = {EditGroup.class}) - private Long id; - - /** - * 表单id - */ - private Long formId; - - /** - * 表单类型 - */ - private String formType; - - /** - * 节点名称 - */ - @NotBlank(message = "节点名称不能为空", groups = {AddGroup.class, EditGroup.class}) - private String nodeName; - - /** - * 节点id - */ - @NotBlank(message = "节点id不能为空", groups = {AddGroup.class, EditGroup.class}) - private String nodeId; - - /** - * 流程定义id - */ - @NotBlank(message = "流程定义id不能为空", groups = {AddGroup.class, EditGroup.class}) - private String definitionId; - - /** - * 是否为申请人节点 (0是 1否) - */ - @NotBlank(message = "是否为申请人节点不能为空", groups = {AddGroup.class, EditGroup.class}) - private String applyUserTask; - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/ActHistoryInfoVo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/ActHistoryInfoVo.java deleted file mode 100644 index e4c1142ac..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/ActHistoryInfoVo.java +++ /dev/null @@ -1,93 +0,0 @@ -package org.dromara.workflow.domain.vo; - -import lombok.Data; -import org.dromara.common.translation.annotation.Translation; -import org.dromara.common.translation.constant.TransConstant; -import org.flowable.engine.task.Attachment; - -import java.io.Serial; -import java.io.Serializable; -import java.util.Date; -import java.util.List; - -/** - * 流程审批记录视图 - * - * @author may - */ -@Data -public class ActHistoryInfoVo implements Serializable { - - @Serial - private static final long serialVersionUID = 1L; - /** - * 任务id - */ - private String id; - /** - * 节点id - */ - private String taskDefinitionKey; - /** - * 任务名称 - */ - private String name; - /** - * 流程实例id - */ - private String processInstanceId; - /** - * 版本 - */ - private Integer version; - /** - * 开始时间 - */ - private Date startTime; - /** - * 结束时间 - */ - private Date endTime; - /** - * 运行时长 - */ - private String runDuration; - /** - * 状态 - */ - private String status; - /** - * 状态 - */ - private String statusName; - /** - * 办理人id - */ - private String assignee; - - /** - * 办理人名称 - */ - @Translation(type = TransConstant.USER_ID_TO_NICKNAME, mapper = "assignee") - private String nickName; - - /** - * 办理人id - */ - private String owner; - - /** - * 审批信息id - */ - private String commentId; - - /** - * 审批信息 - */ - private String comment; - - /** - * 审批附件 - */ - private List attachmentList; -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowCategoryVo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowCategoryVo.java new file mode 100644 index 000000000..2c72143cb --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowCategoryVo.java @@ -0,0 +1,69 @@ +package org.dromara.workflow.domain.vo; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import io.github.linpeilie.annotations.AutoMapper; +import lombok.Data; +import org.dromara.common.excel.annotation.ExcelDictFormat; +import org.dromara.common.excel.convert.ExcelDictConvert; +import org.dromara.workflow.domain.FlowCategory; + +import java.io.Serial; +import java.io.Serializable; +import java.util.Date; + + +/** + * 流程分类视图对象 wf_category + * + * @author may + * @date 2023-06-27 + */ +@Data +@ExcelIgnoreUnannotated +@AutoMapper(target = FlowCategory.class) +public class FlowCategoryVo implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 流程分类ID + */ + @ExcelProperty(value = "流程分类ID") + private Long categoryId; + + /** + * 父级id + */ + private Long parentId; + + /** + * 父类别名称 + */ + private String parentName; + + /** + * 祖级列表 + */ + private String ancestors; + + /** + * 流程分类名称 + */ + @ExcelProperty(value = "流程分类名称") + private String categoryName; + + /** + * 显示顺序 + */ + @ExcelProperty(value = "显示顺序") + private Long orderNum; + + /** + * 创建时间 + */ + @ExcelProperty(value = "创建时间") + private Date createTime; + +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowDefinitionVo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowDefinitionVo.java new file mode 100644 index 000000000..aef75739a --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowDefinitionVo.java @@ -0,0 +1,104 @@ +package org.dromara.workflow.domain.vo; + +import lombok.Data; +import org.dromara.common.translation.annotation.Translation; +import org.dromara.workflow.common.constant.FlowConstant; + +import java.io.Serial; +import java.io.Serializable; +import java.util.Date; + +/** + * 流程定义视图 + * + * @author may + */ +@Data +public class FlowDefinitionVo implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + private Long id; + + /** + * 创建时间 + */ + private Date createTime; + + /** + * 更新时间 + */ + private Date updateTime; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 删除标记 + */ + private String delFlag; + + /** + * 流程定义编码 + */ + private String flowCode; + + /** + * 流程定义名称 + */ + private String flowName; + + /** + * 流程分类id + */ + private String category; + + /** + * 流程分类名称 + */ + @Translation(type = FlowConstant.CATEGORY_ID_TO_NAME, mapper = "category") + private String categoryName; + + /** + * 流程版本 + */ + private String version; + + /** + * 是否发布(0未发布 1已发布 9失效) + */ + private Integer isPublish; + + /** + * 审批表单是否自定义(Y是 N否) + */ + private String formCustom; + + /** + * 审批表单路径 + */ + private String formPath; + + /** + * 流程激活状态(0挂起 1激活) + */ + private Integer activityStatus; + + /** + * 监听器类型 + */ + private String listenerType; + + /** + * 监听器路径 + */ + private String listenerPath; + + /** + * 扩展字段,预留给业务系统使用 + */ + private String ext; +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowHisTaskVo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowHisTaskVo.java new file mode 100644 index 000000000..8776a76b8 --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowHisTaskVo.java @@ -0,0 +1,244 @@ +package org.dromara.workflow.domain.vo; + +import lombok.Data; +import org.dromara.common.core.utils.DateUtils; +import org.dromara.common.translation.annotation.Translation; +import org.dromara.common.translation.constant.TransConstant; +import org.dromara.warm.flow.core.enums.CooperateType; +import org.dromara.workflow.common.constant.FlowConstant; + +import java.io.Serial; +import java.io.Serializable; +import java.util.Date; +import java.util.List; + +/** + * 历史任务视图 + * + * @author may + */ +@Data +public class FlowHisTaskVo implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + private Long id; + + /** + * 创建时间 + */ + private Date createTime; + + /** + * 更新时间 + */ + private Date updateTime; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 删除标记 + */ + private String delFlag; + + /** + * 对应flow_definition表的id + */ + private Long definitionId; + + /** + * 流程定义名称 + */ + private String flowName; + + /** + * 流程实例表id + */ + private Long instanceId; + + /** + * 任务表id + */ + private Long taskId; + + /** + * 协作方式(1审批 2转办 3委派 4会签 5票签 6加签 7减签) + */ + private Integer cooperateType; + + /** + * 协作方式(1审批 2转办 3委派 4会签 5票签 6加签 7减签) + */ + private String cooperateTypeName; + + /** + * 业务id + */ + private String businessId; + + /** + * 开始节点编码 + */ + private String nodeCode; + + /** + * 开始节点名称 + */ + private String nodeName; + + /** + * 开始节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关) + */ + private Integer nodeType; + + /** + * 目标节点编码 + */ + private String targetNodeCode; + + /** + * 结束节点名称 + */ + private String targetNodeName; + + /** + * 审批者 + */ + private String approver; + + /** + * 审批者 + */ + @Translation(type = TransConstant.USER_ID_TO_NICKNAME, mapper = "approver") + private String approveName; + + /** + * 协作人(只有转办、会签、票签、委派) + */ + private String collaborator; + + /** + * 权限标识 permissionFlag的list形式 + */ + private List permissionList; + + /** + * 跳转类型(PASS通过 REJECT退回 NONE无动作) + */ + private String skipType; + + /** + * 流程状态 + */ + private String flowStatus; + + /** + * 任务状态 + */ + private String flowTaskStatus; + + /** + * 流程状态 + */ + private String flowStatusName; + + /** + * 审批意见 + */ + private String message; + + /** + * 业务详情 存业务类的json + */ + private String ext; + + /** + * 创建者 + */ + private String createBy; + + /** + * 申请人 + */ + @Translation(type = TransConstant.USER_ID_TO_NICKNAME, mapper = "createBy") + private String createByName; + + /** + * 流程分类id + */ + private String category; + + /** + * 流程分类名称 + */ + @Translation(type = FlowConstant.CATEGORY_ID_TO_NAME, mapper = "category") + private String categoryName; + + /** + * 审批表单是否自定义(Y是 N否) + */ + private String formCustom; + + /** + * 审批表单路径 + */ + private String formPath; + + /** + * 流程定义编码 + */ + private String flowCode; + + /** + * 流程版本号 + */ + private String version; + + /** + * 运行时长 + */ + private String runDuration; + + /** + * 设置创建时间并计算任务运行时长 + * + * @param createTime 创建时间 + */ + public void setCreateTime(Date createTime) { + this.createTime = createTime; + updateRunDuration(); + } + + /** + * 设置更新时间并计算任务运行时长 + * + * @param updateTime 更新时间 + */ + public void setUpdateTime(Date updateTime) { + this.updateTime = updateTime; + updateRunDuration(); + } + + /** + * 更新运行时长 + */ + private void updateRunDuration() { + // 如果创建时间和更新时间均不为空,计算它们之间的时长 + if (this.updateTime != null && this.createTime != null) { + this.runDuration = DateUtils.getTimeDifference(this.updateTime, this.createTime); + } + } + + /** + * 设置协作方式,并通过协作方式获取名称 + */ + public void setCooperateType(Integer cooperateType) { + this.cooperateType = cooperateType; + this.cooperateTypeName = CooperateType.getValueByKey(cooperateType); + } + +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowInstanceVo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowInstanceVo.java new file mode 100644 index 000000000..75543f419 --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowInstanceVo.java @@ -0,0 +1,137 @@ +package org.dromara.workflow.domain.vo; + +import lombok.Data; +import org.dromara.common.translation.annotation.Translation; +import org.dromara.common.translation.constant.TransConstant; +import org.dromara.workflow.common.constant.FlowConstant; + +import java.util.Date; + +/** + * 流程实例视图 + * + * @author may + */ +@Data +public class FlowInstanceVo { + + private Long id; + + /** + * 创建时间 + */ + private Date createTime; + + /** + * 更新时间 + */ + private Date updateTime; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 删除标记 + */ + private String delFlag; + + /** + * 对应flow_definition表的id + */ + private Long definitionId; + + /** + * 流程定义名称 + */ + private String flowName; + + /** + * 流程定义编码 + */ + private String flowCode; + + /** + * 业务id + */ + private String businessId; + + /** + * 节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关) + */ + private Integer nodeType; + + /** + * 流程节点编码 每个流程的nodeCode是唯一的,即definitionId+nodeCode唯一,在数据库层面做了控制 + */ + private String nodeCode; + + /** + * 流程节点名称 + */ + private String nodeName; + + /** + * 流程变量 + */ + private String variable; + + /** + * 流程状态(0待提交 1审批中 2 审批通过 3自动通过 8已完成 9已退回 10失效) + */ + private String flowStatus; + + /** + * 流程状态 + */ + private String flowStatusName; + + /** + * 流程激活状态(0挂起 1激活) + */ + private Integer activityStatus; + + /** + * 审批表单是否自定义(Y是 N否) + */ + private String formCustom; + + /** + * 审批表单路径 + */ + private String formPath; + + /** + * 扩展字段,预留给业务系统使用 + */ + private String ext; + + /** + * 流程定义版本 + */ + private String version; + + /** + * 创建者 + */ + private String createBy; + + /** + * 申请人 + */ + @Translation(type = TransConstant.USER_ID_TO_NICKNAME, mapper = "createBy") + private String createByName; + + /** + * 流程分类id + */ + private String category; + + /** + * 流程分类名称 + */ + @Translation(type = FlowConstant.CATEGORY_ID_TO_NAME, mapper = "category") + private String categoryName; + +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowTaskVo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowTaskVo.java new file mode 100644 index 000000000..3fb08d954 --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowTaskVo.java @@ -0,0 +1,176 @@ +package org.dromara.workflow.domain.vo; + +import lombok.Data; +import org.dromara.common.translation.annotation.Translation; +import org.dromara.common.translation.constant.TransConstant; +import org.dromara.warm.flow.core.entity.User; +import org.dromara.workflow.common.constant.FlowConstant; + +import java.io.Serial; +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; + +/** + * 任务视图 + * + * @author may + */ +@Data +public class FlowTaskVo implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + private Long id; + + /** + * 创建时间 + */ + private Date createTime; + + /** + * 更新时间 + */ + private Date updateTime; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 删除标记 + */ + private String delFlag; + + /** + * 对应flow_definition表的id + */ + private Long definitionId; + + /** + * 流程实例表id + */ + private Long instanceId; + + /** + * 流程定义名称 + */ + private String flowName; + + /** + * 业务id + */ + private String businessId; + + /** + * 节点编码 + */ + private String nodeCode; + + /** + * 节点名称 + */ + private String nodeName; + + /** + * 节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关) + */ + private Integer nodeType; + + /** + * 权限标识 permissionFlag的list形式 + */ + private List permissionList; + + /** + * 流程用户列表 + */ + private List userList; + + /** + * 审批表单是否自定义(Y是 N否) + */ + private String formCustom; + + /** + * 审批表单 + */ + private String formPath; + + /** + * 流程定义编码 + */ + private String flowCode; + + /** + * 流程版本号 + */ + private String version; + + /** + * 流程状态 + */ + private String flowStatus; + + /** + * 流程分类id + */ + private String category; + + /** + * 流程分类名称 + */ + @Translation(type = FlowConstant.CATEGORY_ID_TO_NAME, mapper = "category") + private String categoryName; + + /** + * 流程状态 + */ + @Translation(type = TransConstant.DICT_TYPE_TO_LABEL, mapper = "flowStatus", other = "wf_business_status") + private String flowStatusName; + + /** + * 办理人类型 + */ + private String type; + + /** + * 办理人ids + */ + private String assigneeIds; + + /** + * 办理人名称 + */ + private String assigneeNames; + + /** + * 抄送人id + */ + private String processedBy; + + /** + * 抄送人名称 + */ + @Translation(type = TransConstant.USER_ID_TO_NICKNAME, mapper = "processedBy") + private String processedByName; + + /** + * 流程签署比例值 大于0为票签,会签 + */ + private BigDecimal nodeRatio; + + /** + * 申请人id + */ + private String createBy; + + /** + * 申请人名称 + */ + @Translation(type = TransConstant.USER_ID_TO_NICKNAME, mapper = "createBy") + private String createByName; +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/VariableVo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowVariableVo.java similarity index 86% rename from ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/VariableVo.java rename to ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowVariableVo.java index 6a26c8287..b4de76e93 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/VariableVo.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowVariableVo.java @@ -11,7 +11,7 @@ import java.io.Serializable; * @author may */ @Data -public class VariableVo implements Serializable { +public class FlowVariableVo implements Serializable { @Serial private static final long serialVersionUID = 1L; diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/GraphicInfoVo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/GraphicInfoVo.java deleted file mode 100644 index 763613165..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/GraphicInfoVo.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.dromara.workflow.domain.vo; - -import lombok.Data; - -import java.io.Serial; -import java.io.Serializable; - -/** - * 节点图形信息 - * - * @author may - */ -@Data -public class GraphicInfoVo implements Serializable { - - @Serial - private static final long serialVersionUID = 1L; - /** - * x坐标 - */ - private double x; - - /** - * y坐标 - */ - private double y; - - /** - * 节点高度 - */ - private double height; - - /** - * 节点宽度 - */ - private double width; - - /** - * 节点id - */ - private String nodeId; - - /** - * 节点名称 - */ - private String nodeName; -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/ModelVo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/ModelVo.java deleted file mode 100644 index b2ce81108..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/ModelVo.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.dromara.workflow.domain.vo; - -import lombok.Data; - -import java.io.Serial; -import java.io.Serializable; - -/** - * 模型视图对象 - * - * @author may - */ -@Data -public class ModelVo implements Serializable { - - @Serial - private static final long serialVersionUID = 1L; - - /** - * 模型id - */ - private String id; - - /** - * 模型名称 - */ - private String name; - - /** - * 模型标识key - */ - private String key; - - /** - * 模型分类 - */ - private String categoryCode; - - /** - * 模型XML - */ - private String xml; - - /** - * 备注 - */ - private String description; -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/MultiInstanceVo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/MultiInstanceVo.java deleted file mode 100644 index b99839603..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/MultiInstanceVo.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.dromara.workflow.domain.vo; - -import lombok.Data; - -import java.io.Serial; -import java.io.Serializable; - -/** - * 多实例信息 - * - * @author may - */ -@Data -public class MultiInstanceVo implements Serializable { - - @Serial - private static final long serialVersionUID = 1L; - - /** - * 会签类型(串行,并行) - */ - private Object type; - - /** - * 会签人员KEY - */ - private String assignee; - - /** - * 会签人员集合KEY - */ - private String assigneeList; -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/ParticipantVo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/ParticipantVo.java deleted file mode 100644 index c5876f689..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/ParticipantVo.java +++ /dev/null @@ -1,43 +0,0 @@ -package org.dromara.workflow.domain.vo; - -import lombok.Data; - -import java.io.Serial; -import java.io.Serializable; -import java.util.List; - -/** - * 参与者 - * - * @author may - */ -@Data -public class ParticipantVo implements Serializable { - - @Serial - private static final long serialVersionUID = 1L; - - /** - * 组id(角色id) - */ - private List groupIds; - - /** - * 候选人id(用户id) 当组id不为空时,将组内人员查出放入candidate - */ - private List candidate; - - /** - * 候选人名称(用户名称) 当组id不为空时,将组内人员查出放入candidateName - */ - private List candidateName; - - /** - * 是否认领标识 - * 当为空时默认当前任务不需要认领 - * 当为true时当前任务说明为候选模式并且有人已经认领了任务可以归还, - * 当为false时当前任务说明为候选模式该任务未认领, - */ - private Boolean claim; - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/ProcessDefinitionVo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/ProcessDefinitionVo.java deleted file mode 100644 index 034adbb26..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/ProcessDefinitionVo.java +++ /dev/null @@ -1,70 +0,0 @@ -package org.dromara.workflow.domain.vo; - -import lombok.Data; - -import java.io.Serial; -import java.io.Serializable; -import java.util.Date; - -/** - * 流程定义视图 - * - * @author may - */ -@Data -public class ProcessDefinitionVo implements Serializable { - - @Serial - private static final long serialVersionUID = 1L; - - /** - * 流程定义id - */ - private String id; - - /** - * 流程定义名称 - */ - private String name; - - /** - * 流程定义标识key - */ - private String key; - - /** - * 流程定义版本 - */ - private int version; - - /** - * 流程定义挂起或激活 1激活 2挂起 - */ - private int suspensionState; - - /** - * 流程xml名称 - */ - private String resourceName; - - /** - * 流程图片名称 - */ - private String diagramResourceName; - - /** - * 流程部署id - */ - private String deploymentId; - - /** - * 流程部署时间 - */ - private Date deploymentTime; - - /** - * 流程定义配置 - */ - private WfDefinitionConfigVo wfDefinitionConfigVo; - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/ProcessInstanceVo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/ProcessInstanceVo.java deleted file mode 100644 index ab3e7a130..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/ProcessInstanceVo.java +++ /dev/null @@ -1,100 +0,0 @@ -package org.dromara.workflow.domain.vo; - -import lombok.Data; - -import java.io.Serial; -import java.io.Serializable; -import java.util.Date; -import java.util.List; - -/** - * 流程实例视图 - * - * @author may - */ -@Data -public class ProcessInstanceVo implements Serializable { - - @Serial - private static final long serialVersionUID = 1L; - - /** - * 流程实例id - */ - private String id; - - /** - * 流程定义id - */ - private String processDefinitionId; - - /** - * 流程定义名称 - */ - private String processDefinitionName; - - /** - * 流程定义key - */ - private String processDefinitionKey; - - /** - * 流程定义版本 - */ - private Integer processDefinitionVersion; - - /** - * 部署id - */ - private String deploymentId; - - /** - * 业务id - */ - private String businessKey; - - /** - * 是否挂起 - */ - private Boolean isSuspended; - - /** - * 租户id - */ - private String tenantId; - - /** - * 启动时间 - */ - private Date startTime; - - /** - * 结束时间 - */ - private Date endTime; - - /** - * 启动人id - */ - private String startUserId; - - /** - * 流程状态 - */ - private String businessStatus; - - /** - * 流程状态 - */ - private String businessStatusName; - - /** - * 待办任务集合 - */ - private List taskVoList; - - /** - * 节点配置 - */ - private WfNodeConfigVo wfNodeConfigVo; -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/TaskVo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/TaskVo.java deleted file mode 100644 index 466e77690..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/TaskVo.java +++ /dev/null @@ -1,173 +0,0 @@ -package org.dromara.workflow.domain.vo; - -import lombok.Data; -import org.dromara.common.translation.annotation.Translation; -import org.dromara.common.translation.constant.TransConstant; - -import java.io.Serial; -import java.io.Serializable; -import java.util.Date; - -/** - * 任务视图 - * - * @author may - */ -@Data -public class TaskVo implements Serializable { - - @Serial - private static final long serialVersionUID = 1L; - - /** - * 任务id - */ - private String id; - - /** - * 任务名称 - */ - private String name; - - /** - * 描述 - */ - private String description; - - /** - * 优先级 - */ - private Integer priority; - - /** - * 负责此任务的人员的用户id - */ - private String owner; - - /** - * 办理人id - */ - private Long assignee; - - /** - * 办理人 - */ - @Translation(type = TransConstant.USER_ID_TO_NICKNAME, mapper = "assignee") - private String assigneeName; - - - /** - * 流程实例id - */ - private String processInstanceId; - - /** - * 执行id - */ - private String executionId; - - /** - * 无用 - */ - private String taskDefinitionId; - - /** - * 流程定义id - */ - private String processDefinitionId; - - /** - * 创建时间 - */ - private Date createTime; - - /** - * 已办任务-创建时间 - */ - private Date startTime; - - /** - * 结束时间 - */ - private Date endTime; - - /** - * 节点id - */ - private String taskDefinitionKey; - - /** - * 任务截止日期 - */ - private Date dueDate; - - /** - * 流程类别 - */ - private String category; - - /** - * 父级任务id - */ - private String parentTaskId; - - /** - * 租户id - */ - private String tenantId; - - /** - * 认领时间 - */ - private Date claimTime; - - /** - * 流程状态 - */ - private String businessStatus; - - /** - * 流程状态 - */ - private String businessStatusName; - - /** - * 流程定义名称 - */ - private String processDefinitionName; - - /** - * 流程定义key - */ - private String processDefinitionKey; - - /** - * 流程定义版本 - */ - private Integer processDefinitionVersion; - - /** - * 参与者 - */ - private ParticipantVo participantVo; - - /** - * 是否会签 - */ - private Boolean multiInstance; - - /** - * 业务id - */ - private String businessKey; - - /** - * 流程定义配置 - */ - private WfDefinitionConfigVo wfDefinitionConfigVo; - - /** - * 节点配置 - */ - private WfNodeConfigVo wfNodeConfigVo; -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/WfCategoryVo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/WfCategoryVo.java deleted file mode 100644 index 362f64625..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/WfCategoryVo.java +++ /dev/null @@ -1,58 +0,0 @@ -package org.dromara.workflow.domain.vo; - -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; -import io.github.linpeilie.annotations.AutoMapper; -import lombok.Data; -import org.dromara.workflow.domain.WfCategory; - -import java.io.Serial; -import java.io.Serializable; - - -/** - * 流程分类视图对象 wf_category - * - * @author may - * @date 2023-06-27 - */ -@Data -@ExcelIgnoreUnannotated -@AutoMapper(target = WfCategory.class) -public class WfCategoryVo implements Serializable { - - @Serial - private static final long serialVersionUID = 1L; - - /** - * 主键 - */ - @ExcelProperty(value = "主键") - private Long id; - - /** - * 分类名称 - */ - @ExcelProperty(value = "分类名称") - private String categoryName; - - /** - * 分类编码 - */ - @ExcelProperty(value = "分类编码") - private String categoryCode; - - /** - * 父级id - */ - @ExcelProperty(value = "父级id") - private Long parentId; - - /** - * 排序 - */ - @ExcelProperty(value = "排序") - private Long sortNum; - - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/WfDefinitionConfigVo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/WfDefinitionConfigVo.java deleted file mode 100644 index 9c7b0d7db..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/WfDefinitionConfigVo.java +++ /dev/null @@ -1,70 +0,0 @@ -package org.dromara.workflow.domain.vo; - -import org.dromara.workflow.domain.WfDefinitionConfig; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; -import io.github.linpeilie.annotations.AutoMapper; -import lombok.Data; - -import java.io.Serial; -import java.io.Serializable; - - -/** - * 流程定义配置视图对象 wf_definition_config - * - * @author may - * @date 2024-03-18 - */ -@Data -@ExcelIgnoreUnannotated -@AutoMapper(target = WfDefinitionConfig.class) -public class WfDefinitionConfigVo implements Serializable { - - @Serial - private static final long serialVersionUID = 1L; - - /** - * 主键 - */ - @ExcelProperty(value = "主键") - private Long id; - - /** - * 表名 - */ - @ExcelProperty(value = "表名") - private String tableName; - - /** - * 流程定义ID - */ - @ExcelProperty(value = "流程定义ID") - private String definitionId; - - /** - * 流程KEY - */ - @ExcelProperty(value = "流程KEY") - private String processKey; - - - /** - * 流程版本 - */ - @ExcelProperty(value = "流程版本") - private Integer version; - - /** - * 备注 - */ - @ExcelProperty(value = "备注") - private String remark; - - /** - * 表单管理 - */ - private WfFormManageVo wfFormManageVo; - - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/WfFormManageVo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/WfFormManageVo.java deleted file mode 100644 index 302df2396..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/WfFormManageVo.java +++ /dev/null @@ -1,63 +0,0 @@ -package org.dromara.workflow.domain.vo; - -import org.dromara.workflow.domain.WfFormManage; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; -import io.github.linpeilie.annotations.AutoMapper; -import lombok.Data; - -import java.io.Serial; -import java.io.Serializable; - - -/** - * 表单管理视图对象 wf_form_manage - * - * @author may - * @date 2024-03-29 - */ -@Data -@ExcelIgnoreUnannotated -@AutoMapper(target = WfFormManage.class) -public class WfFormManageVo implements Serializable { - - @Serial - private static final long serialVersionUID = 1L; - - /** - * 主键 - */ - @ExcelProperty(value = "主键") - private Long id; - - /** - * 表单名称 - */ - @ExcelProperty(value = "表单名称") - private String formName; - - /** - * 表单类型 - */ - @ExcelProperty(value = "表单类型") - private String formType; - - /** - * 表单类型名称 - */ - private String formTypeName; - - /** - * 路由地址/表单ID - */ - @ExcelProperty(value = "路由地址/表单ID") - private String router; - - /** - * 备注 - */ - @ExcelProperty(value = "备注") - private String remark; - - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/WfNodeConfigVo.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/WfNodeConfigVo.java deleted file mode 100644 index 89e9d9b3f..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/WfNodeConfigVo.java +++ /dev/null @@ -1,75 +0,0 @@ -package org.dromara.workflow.domain.vo; - -import org.dromara.workflow.domain.WfNodeConfig; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; -import io.github.linpeilie.annotations.AutoMapper; -import lombok.Data; - -import java.io.Serial; -import java.io.Serializable; - - -/** - * 节点配置视图对象 wf_node_config - * - * @author may - * @date 2024-03-30 - */ -@Data -@ExcelIgnoreUnannotated -@AutoMapper(target = WfNodeConfig.class) -public class WfNodeConfigVo implements Serializable { - - @Serial - private static final long serialVersionUID = 1L; - - /** - * 主键 - */ - @ExcelProperty(value = "主键") - private Long id; - - /** - * 表单id - */ - @ExcelProperty(value = "表单id") - private Long formId; - - /** - * 表单类型 - */ - @ExcelProperty(value = "表单类型") - private String formType; - - /** - * 节点名称 - */ - @ExcelProperty(value = "节点名称") - private String nodeName; - - /** - * 节点id - */ - @ExcelProperty(value = "节点id") - private String nodeId; - - /** - * 流程定义id - */ - @ExcelProperty(value = "流程定义id") - private String definitionId; - - /** - * 是否为申请人节点 (0是 1否) - */ - @ExcelProperty(value = "是否为申请人节点 (0是 1否)") - private String applyUserTask; - - /** - * 表单管理 - */ - private WfFormManageVo wfFormManageVo; - - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/CustomDefaultProcessDiagramCanvas.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/CustomDefaultProcessDiagramCanvas.java deleted file mode 100644 index 39fd9d363..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/CustomDefaultProcessDiagramCanvas.java +++ /dev/null @@ -1,108 +0,0 @@ -package org.dromara.workflow.flowable; - -import org.flowable.bpmn.model.AssociationDirection; -import org.flowable.image.impl.DefaultProcessDiagramCanvas; - -import java.awt.*; -import java.awt.geom.Line2D; -import java.awt.geom.RoundRectangle2D; - -public class CustomDefaultProcessDiagramCanvas extends DefaultProcessDiagramCanvas { - //设置高亮线的颜色 这里我设置成绿色 - protected static Color HIGHLIGHT_SEQUENCEFLOW_COLOR = Color.GREEN; - - public CustomDefaultProcessDiagramCanvas(int width, int height, int minX, int minY, String imageType, String activityFontName, String labelFontName, String annotationFontName, ClassLoader customClassLoader) { - super(width, height, minX, minY, imageType, activityFontName, labelFontName, annotationFontName, customClassLoader); - } - - /** - * 画线颜色设置 - */ - public void drawConnection(int[] xPoints, int[] yPoints, boolean conditional, boolean isDefault, String connectionType, - AssociationDirection associationDirection, boolean highLighted, double scaleFactor) { - - Paint originalPaint = g.getPaint(); - Stroke originalStroke = g.getStroke(); - - g.setPaint(CONNECTION_COLOR); - if (connectionType.equals("association")) { - g.setStroke(ASSOCIATION_STROKE); - } else if (highLighted) { - //设置线的颜色 - g.setPaint(HIGHLIGHT_SEQUENCEFLOW_COLOR); - g.setStroke(HIGHLIGHT_FLOW_STROKE); - } - - for (int i = 1; i < xPoints.length; i++) { - Integer sourceX = xPoints[i - 1]; - Integer sourceY = yPoints[i - 1]; - Integer targetX = xPoints[i]; - Integer targetY = yPoints[i]; - Line2D.Double line = new Line2D.Double(sourceX, sourceY, targetX, targetY); - g.draw(line); - } - - if (isDefault) { - Line2D.Double line = new Line2D.Double(xPoints[0], yPoints[0], xPoints[1], yPoints[1]); - drawDefaultSequenceFlowIndicator(line, scaleFactor); - } - - if (conditional) { - Line2D.Double line = new Line2D.Double(xPoints[0], yPoints[0], xPoints[1], yPoints[1]); - drawConditionalSequenceFlowIndicator(line, scaleFactor); - } - - if (associationDirection == AssociationDirection.ONE || associationDirection == AssociationDirection.BOTH) { - Line2D.Double line = new Line2D.Double(xPoints[xPoints.length - 2], yPoints[xPoints.length - 2], xPoints[xPoints.length - 1], yPoints[xPoints.length - 1]); - drawArrowHead(line, scaleFactor); - } - if (associationDirection == AssociationDirection.BOTH) { - Line2D.Double line = new Line2D.Double(xPoints[1], yPoints[1], xPoints[0], yPoints[0]); - drawArrowHead(line, scaleFactor); - } - g.setPaint(originalPaint); - g.setStroke(originalStroke); - } - - /** - * 高亮节点设置 - */ - public void drawHighLight(int x, int y, int width, int height) { - Paint originalPaint = g.getPaint(); - Stroke originalStroke = g.getStroke(); - //设置高亮节点的颜色 - g.setPaint(HIGHLIGHT_COLOR); - g.setStroke(THICK_TASK_BORDER_STROKE); - - RoundRectangle2D rect = new RoundRectangle2D.Double(x, y, width, height, 20, 20); - g.draw(rect); - - g.setPaint(originalPaint); - g.setStroke(originalStroke); - } - - /** - * @description: 高亮节点红色 - * @param: x - * @param: y - * @param: width - * @param: height - * @return: void - * @author: gssong - * @date: 2022/4/12 - */ - public void drawHighLightRed(int x, int y, int width, int height) { - Paint originalPaint = g.getPaint(); - Stroke originalStroke = g.getStroke(); - //设置高亮节点的颜色 - g.setPaint(Color.green); - g.setStroke(THICK_TASK_BORDER_STROKE); - - RoundRectangle2D rect = new RoundRectangle2D.Double(x, y, width, height, 20, 20); - g.draw(rect); - - g.setPaint(originalPaint); - g.setStroke(originalStroke); - } - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/CustomDefaultProcessDiagramGenerator.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/CustomDefaultProcessDiagramGenerator.java deleted file mode 100644 index e4793a26f..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/CustomDefaultProcessDiagramGenerator.java +++ /dev/null @@ -1,1120 +0,0 @@ -/* Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.dromara.workflow.flowable; - -import org.flowable.bpmn.model.Event; -import org.flowable.bpmn.model.Process; -import org.flowable.bpmn.model.*; -import org.flowable.image.ProcessDiagramGenerator; - -import java.awt.*; -import java.awt.image.BufferedImage; -import java.io.InputStream; -import java.util.List; -import java.util.*; - -/** - * Class to generate an image based the diagram interchange information in a BPMN 2.0 process. - * - * @author Joram Barrez - * @author Tijs Rademakers - * @author Zheng Ji - */ -public class CustomDefaultProcessDiagramGenerator implements ProcessDiagramGenerator { - - protected Map, ActivityDrawInstruction> activityDrawInstructions = new HashMap<>(); - protected Map, ArtifactDrawInstruction> artifactDrawInstructions = new HashMap<>(); - - public CustomDefaultProcessDiagramGenerator() { - this(1.0); - } - - // The instructions on how to draw a certain construct is - // created statically and stored in a map for performance. - public CustomDefaultProcessDiagramGenerator(final double scaleFactor) { - // start event - activityDrawInstructions.put(StartEvent.class, new ActivityDrawInstruction() { - - @Override - public void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId()); - StartEvent startEvent = (StartEvent) flowNode; - if (startEvent.getEventDefinitions() != null && !startEvent.getEventDefinitions().isEmpty()) { - EventDefinition eventDefinition = startEvent.getEventDefinitions().get(0); - if (eventDefinition instanceof TimerEventDefinition) { - processDiagramCanvas.drawTimerStartEvent(graphicInfo, scaleFactor); - } else if (eventDefinition instanceof ErrorEventDefinition) { - processDiagramCanvas.drawErrorStartEvent(graphicInfo, scaleFactor); - } else if (eventDefinition instanceof EscalationEventDefinition) { - processDiagramCanvas.drawEscalationStartEvent(graphicInfo, scaleFactor); - } else if (eventDefinition instanceof ConditionalEventDefinition) { - processDiagramCanvas.drawConditionalStartEvent(graphicInfo, scaleFactor); - } else if (eventDefinition instanceof SignalEventDefinition) { - processDiagramCanvas.drawSignalStartEvent(graphicInfo, scaleFactor); - } else if (eventDefinition instanceof MessageEventDefinition) { - processDiagramCanvas.drawMessageStartEvent(graphicInfo, scaleFactor); - } else { - processDiagramCanvas.drawNoneStartEvent(graphicInfo); - } - } else { - List eventTypeElements = startEvent.getExtensionElements().get("eventType"); - if (eventTypeElements != null && eventTypeElements.size() > 0) { - processDiagramCanvas.drawEventRegistryStartEvent(graphicInfo, scaleFactor); - - } else { - processDiagramCanvas.drawNoneStartEvent(graphicInfo); - } - } - } - }); - - // signal catch - activityDrawInstructions.put(IntermediateCatchEvent.class, new ActivityDrawInstruction() { - - @Override - public void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId()); - IntermediateCatchEvent intermediateCatchEvent = (IntermediateCatchEvent) flowNode; - if (intermediateCatchEvent.getEventDefinitions() != null && !intermediateCatchEvent.getEventDefinitions().isEmpty()) { - - if (intermediateCatchEvent.getEventDefinitions().get(0) instanceof SignalEventDefinition) { - processDiagramCanvas.drawCatchingSignalEvent(flowNode.getName(), graphicInfo, true, scaleFactor); - } else if (intermediateCatchEvent.getEventDefinitions().get(0) instanceof TimerEventDefinition) { - processDiagramCanvas.drawCatchingTimerEvent(flowNode.getName(), graphicInfo, true, scaleFactor); - } else if (intermediateCatchEvent.getEventDefinitions().get(0) instanceof MessageEventDefinition) { - processDiagramCanvas.drawCatchingMessageEvent(flowNode.getName(), graphicInfo, true, scaleFactor); - } else if (intermediateCatchEvent.getEventDefinitions().get(0) instanceof ConditionalEventDefinition) { - processDiagramCanvas.drawCatchingConditionalEvent(flowNode.getName(), graphicInfo, true, scaleFactor); - } - } - } - }); - - // signal throw - activityDrawInstructions.put(ThrowEvent.class, new ActivityDrawInstruction() { - - @Override - public void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId()); - ThrowEvent throwEvent = (ThrowEvent) flowNode; - if (throwEvent.getEventDefinitions() != null && !throwEvent.getEventDefinitions().isEmpty()) { - if (throwEvent.getEventDefinitions().get(0) instanceof SignalEventDefinition) { - processDiagramCanvas.drawThrowingSignalEvent(graphicInfo, scaleFactor); - } else if (throwEvent.getEventDefinitions().get(0) instanceof EscalationEventDefinition) { - processDiagramCanvas.drawThrowingEscalationEvent(graphicInfo, scaleFactor); - } else if (throwEvent.getEventDefinitions().get(0) instanceof CompensateEventDefinition) { - processDiagramCanvas.drawThrowingCompensateEvent(graphicInfo, scaleFactor); - } else { - processDiagramCanvas.drawThrowingNoneEvent(graphicInfo, scaleFactor); - } - } else { - processDiagramCanvas.drawThrowingNoneEvent(graphicInfo, scaleFactor); - } - } - }); - - // end event - activityDrawInstructions.put(EndEvent.class, new ActivityDrawInstruction() { - - @Override - public void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId()); - EndEvent endEvent = (EndEvent) flowNode; - if (endEvent.getEventDefinitions() != null && !endEvent.getEventDefinitions().isEmpty()) { - if (endEvent.getEventDefinitions().get(0) instanceof ErrorEventDefinition) { - processDiagramCanvas.drawErrorEndEvent(flowNode.getName(), graphicInfo, scaleFactor); - } else if (endEvent.getEventDefinitions().get(0) instanceof EscalationEventDefinition) { - processDiagramCanvas.drawEscalationEndEvent(flowNode.getName(), graphicInfo, scaleFactor); - } else { - processDiagramCanvas.drawNoneEndEvent(graphicInfo, scaleFactor); - } - } else { - processDiagramCanvas.drawNoneEndEvent(graphicInfo, scaleFactor); - } - } - }); - - // task - activityDrawInstructions.put(Task.class, new ActivityDrawInstruction() { - - @Override - public void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId()); - processDiagramCanvas.drawTask(flowNode.getName(), graphicInfo, scaleFactor); - } - }); - - // user task - activityDrawInstructions.put(UserTask.class, new ActivityDrawInstruction() { - - @Override - public void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId()); - processDiagramCanvas.drawUserTask(flowNode.getName(), graphicInfo, scaleFactor); - } - }); - - // script task - activityDrawInstructions.put(ScriptTask.class, new ActivityDrawInstruction() { - - @Override - public void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId()); - processDiagramCanvas.drawScriptTask(flowNode.getName(), graphicInfo, scaleFactor); - } - }); - - // service task - activityDrawInstructions.put(ServiceTask.class, new ActivityDrawInstruction() { - - @Override - public void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId()); - ServiceTask serviceTask = (ServiceTask) flowNode; - if ("camel".equalsIgnoreCase(serviceTask.getType())) { - processDiagramCanvas.drawCamelTask(serviceTask.getName(), graphicInfo, scaleFactor); - }else if (ServiceTask.HTTP_TASK.equalsIgnoreCase(serviceTask.getType())) { - processDiagramCanvas.drawHttpTask(serviceTask.getName(), graphicInfo, scaleFactor); - } else if (ServiceTask.DMN_TASK.equalsIgnoreCase(serviceTask.getType())) { - processDiagramCanvas.drawDMNTask(serviceTask.getName(), graphicInfo, scaleFactor); - } else if (ServiceTask.SHELL_TASK.equalsIgnoreCase(serviceTask.getType())) { - processDiagramCanvas.drawShellTask(serviceTask.getName(), graphicInfo, scaleFactor); - } else { - processDiagramCanvas.drawServiceTask(serviceTask.getName(), graphicInfo, scaleFactor); - } - } - }); - - // http service task - activityDrawInstructions.put(HttpServiceTask.class, new ActivityDrawInstruction() { - - @Override - public void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId()); - processDiagramCanvas.drawHttpTask(flowNode.getName(), graphicInfo, scaleFactor); - } - }); - - // receive task - activityDrawInstructions.put(ReceiveTask.class, new ActivityDrawInstruction() { - - @Override - public void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId()); - processDiagramCanvas.drawReceiveTask(flowNode.getName(), graphicInfo, scaleFactor); - } - }); - - // send task - activityDrawInstructions.put(SendTask.class, new ActivityDrawInstruction() { - - @Override - public void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId()); - processDiagramCanvas.drawSendTask(flowNode.getName(), graphicInfo, scaleFactor); - } - }); - - // manual task - activityDrawInstructions.put(ManualTask.class, new ActivityDrawInstruction() { - - @Override - public void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId()); - processDiagramCanvas.drawManualTask(flowNode.getName(), graphicInfo, scaleFactor); - } - }); - - // send event service task - activityDrawInstructions.put(SendEventServiceTask.class, new ActivityDrawInstruction() { - - @Override - public void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId()); - processDiagramCanvas.drawSendEventServiceTask(flowNode.getName(), graphicInfo, scaleFactor); - } - }); - - // external worker service task - activityDrawInstructions.put(ExternalWorkerServiceTask.class, new ActivityDrawInstruction() { - - @Override - public void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId()); - ServiceTask serviceTask = (ServiceTask) flowNode; - processDiagramCanvas.drawServiceTask(serviceTask.getName(), graphicInfo, scaleFactor); - } - }); - - // case service task - activityDrawInstructions.put(CaseServiceTask.class, new ActivityDrawInstruction() { - - @Override - public void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId()); - processDiagramCanvas.drawCaseServiceTask(flowNode.getName(), graphicInfo, scaleFactor); - } - }); - - // businessRuleTask task - activityDrawInstructions.put(BusinessRuleTask.class, new ActivityDrawInstruction() { - - @Override - public void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId()); - processDiagramCanvas.drawBusinessRuleTask(flowNode.getName(), graphicInfo, scaleFactor); - } - }); - - // exclusive gateway - activityDrawInstructions.put(ExclusiveGateway.class, new ActivityDrawInstruction() { - - @Override - public void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId()); - processDiagramCanvas.drawExclusiveGateway(graphicInfo, scaleFactor); - } - }); - - // inclusive gateway - activityDrawInstructions.put(InclusiveGateway.class, new ActivityDrawInstruction() { - - @Override - public void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId()); - processDiagramCanvas.drawInclusiveGateway(graphicInfo, scaleFactor); - } - }); - - // parallel gateway - activityDrawInstructions.put(ParallelGateway.class, new ActivityDrawInstruction() { - - @Override - public void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId()); - processDiagramCanvas.drawParallelGateway(graphicInfo, scaleFactor); - } - }); - - // event based gateway - activityDrawInstructions.put(EventGateway.class, new ActivityDrawInstruction() { - - @Override - public void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId()); - processDiagramCanvas.drawEventBasedGateway(graphicInfo, scaleFactor); - } - }); - - // Boundary timer - activityDrawInstructions.put(BoundaryEvent.class, new ActivityDrawInstruction() { - - @Override - public void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId()); - BoundaryEvent boundaryEvent = (BoundaryEvent) flowNode; - if (boundaryEvent.getEventDefinitions() != null && !boundaryEvent.getEventDefinitions().isEmpty()) { - EventDefinition eventDefinition = boundaryEvent.getEventDefinitions().get(0); - if (eventDefinition instanceof TimerEventDefinition) { - processDiagramCanvas.drawCatchingTimerEvent(flowNode.getName(), graphicInfo, boundaryEvent.isCancelActivity(), scaleFactor); - - } else if (eventDefinition instanceof ConditionalEventDefinition) { - processDiagramCanvas.drawCatchingConditionalEvent(graphicInfo, boundaryEvent.isCancelActivity(), scaleFactor); - - } else if (eventDefinition instanceof ErrorEventDefinition) { - processDiagramCanvas.drawCatchingErrorEvent(graphicInfo, boundaryEvent.isCancelActivity(), scaleFactor); - - } else if (eventDefinition instanceof EscalationEventDefinition) { - processDiagramCanvas.drawCatchingEscalationEvent(graphicInfo, boundaryEvent.isCancelActivity(), scaleFactor); - - } else if (eventDefinition instanceof SignalEventDefinition) { - processDiagramCanvas.drawCatchingSignalEvent(flowNode.getName(), graphicInfo, boundaryEvent.isCancelActivity(), scaleFactor); - - } else if (eventDefinition instanceof MessageEventDefinition) { - processDiagramCanvas.drawCatchingMessageEvent(flowNode.getName(), graphicInfo, boundaryEvent.isCancelActivity(), scaleFactor); - - } else if (eventDefinition instanceof CompensateEventDefinition) { - processDiagramCanvas.drawCatchingCompensateEvent(graphicInfo, boundaryEvent.isCancelActivity(), scaleFactor); - } - - } else { - List eventTypeElements = boundaryEvent.getExtensionElements().get("eventType"); - if (eventTypeElements != null && eventTypeElements.size() > 0) { - processDiagramCanvas.drawCatchingEventRegistryEvent(flowNode.getName(), graphicInfo, boundaryEvent.isCancelActivity(), scaleFactor); - } - } - } - }); - - // subprocess - activityDrawInstructions.put(SubProcess.class, new ActivityDrawInstruction() { - - @Override - public void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId()); - if (graphicInfo.getExpanded() != null && !graphicInfo.getExpanded()) { - processDiagramCanvas.drawCollapsedSubProcess(flowNode.getName(), graphicInfo, false, scaleFactor); - } else { - processDiagramCanvas.drawExpandedSubProcess(flowNode.getName(), graphicInfo, false, scaleFactor); - } - } - }); - - // transaction - activityDrawInstructions.put(Transaction.class, new ActivityDrawInstruction() { - - @Override - public void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId()); - if (graphicInfo.getExpanded() != null && !graphicInfo.getExpanded()) { - processDiagramCanvas.drawCollapsedSubProcess(flowNode.getName(), graphicInfo, false, scaleFactor); - } else { - processDiagramCanvas.drawExpandedTransaction(flowNode.getName(), graphicInfo, scaleFactor); - } - } - }); - - // Event subprocess - activityDrawInstructions.put(EventSubProcess.class, new ActivityDrawInstruction() { - - @Override - public void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId()); - if (graphicInfo.getExpanded() != null && !graphicInfo.getExpanded()) { - processDiagramCanvas.drawCollapsedSubProcess(flowNode.getName(), graphicInfo, true, scaleFactor); - } else { - processDiagramCanvas.drawExpandedSubProcess(flowNode.getName(), graphicInfo, true, scaleFactor); - } - } - }); - - // Adhoc subprocess - activityDrawInstructions.put(AdhocSubProcess.class, new ActivityDrawInstruction() { - - @Override - public void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId()); - if (graphicInfo.getExpanded() != null && !graphicInfo.getExpanded()) { - processDiagramCanvas.drawCollapsedSubProcess(flowNode.getName(), graphicInfo, false, scaleFactor); - } else { - processDiagramCanvas.drawExpandedSubProcess(flowNode.getName(), graphicInfo, false, scaleFactor); - } - } - }); - - // call activity - activityDrawInstructions.put(CallActivity.class, new ActivityDrawInstruction() { - - @Override - public void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId()); - processDiagramCanvas.drawCollapsedCallActivity(flowNode.getName(), graphicInfo, scaleFactor); - } - }); - - // text annotation - artifactDrawInstructions.put(TextAnnotation.class, new ArtifactDrawInstruction() { - - @Override - public void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, Artifact artifact) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(artifact.getId()); - TextAnnotation textAnnotation = (TextAnnotation) artifact; - processDiagramCanvas.drawTextAnnotation(textAnnotation.getText(), graphicInfo, scaleFactor); - } - }); - - // association - artifactDrawInstructions.put(Association.class, new ArtifactDrawInstruction() { - - @Override - public void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, Artifact artifact) { - Association association = (Association) artifact; - String sourceRef = association.getSourceRef(); - String targetRef = association.getTargetRef(); - - // source and target can be instance of FlowElement or Artifact - BaseElement sourceElement = bpmnModel.getFlowElement(sourceRef); - BaseElement targetElement = bpmnModel.getFlowElement(targetRef); - if (sourceElement == null) { - sourceElement = bpmnModel.getArtifact(sourceRef); - } - if (targetElement == null) { - targetElement = bpmnModel.getArtifact(targetRef); - } - List graphicInfoList = bpmnModel.getFlowLocationGraphicInfo(artifact.getId()); - graphicInfoList = connectionPerfectionizer(processDiagramCanvas, bpmnModel, sourceElement, targetElement, graphicInfoList); - int[] xPoints = new int[graphicInfoList.size()]; - int[] yPoints = new int[graphicInfoList.size()]; - for (int i = 1; i < graphicInfoList.size(); i++) { - GraphicInfo graphicInfo = graphicInfoList.get(i); - GraphicInfo previousGraphicInfo = graphicInfoList.get(i - 1); - - if (i == 1) { - xPoints[0] = (int) previousGraphicInfo.getX(); - yPoints[0] = (int) previousGraphicInfo.getY(); - } - xPoints[i] = (int) graphicInfo.getX(); - yPoints[i] = (int) graphicInfo.getY(); - } - - AssociationDirection associationDirection = association.getAssociationDirection(); - processDiagramCanvas.drawAssociation(xPoints, yPoints, associationDirection, false, scaleFactor); - } - }); - } - - @Override - public InputStream generateDiagram(BpmnModel bpmnModel, String imageType, List highLightedActivities, List highLightedFlows, - String activityFontName, String labelFontName, String annotationFontName, ClassLoader customClassLoader, double scaleFactor, boolean drawSequenceFlowNameWithNoLabelDI) { - - return generateProcessDiagram(bpmnModel, imageType, highLightedActivities, highLightedFlows, - activityFontName, labelFontName, annotationFontName, customClassLoader, scaleFactor, drawSequenceFlowNameWithNoLabelDI).generateImage(imageType); - } - - @Override - public InputStream generateDiagram(BpmnModel bpmnModel, String imageType, List highLightedActivities, List highLightedFlows, boolean drawSequenceFlowNameWithNoLabelDI) { - return generateDiagram(bpmnModel, imageType, highLightedActivities, highLightedFlows, null, null, null, null, 1.0, drawSequenceFlowNameWithNoLabelDI); - } - - @Override - public InputStream generateDiagram(BpmnModel bpmnModel, String imageType, - List highLightedActivities, List highLightedFlows, double scaleFactor, boolean drawSequenceFlowNameWithNoLabelDI) { - return generateDiagram(bpmnModel, imageType, highLightedActivities, highLightedFlows, null, null, null, null, scaleFactor, drawSequenceFlowNameWithNoLabelDI); - } - - @Override - public InputStream generateDiagram(BpmnModel bpmnModel, String imageType, List highLightedActivities, boolean drawSequenceFlowNameWithNoLabelDI) { - return generateDiagram(bpmnModel, imageType, highLightedActivities, Collections.emptyList(), drawSequenceFlowNameWithNoLabelDI); - } - - @Override - public InputStream generateDiagram(BpmnModel bpmnModel, String imageType, List highLightedActivities, double scaleFactor, boolean drawSequenceFlowNameWithNoLabelDI) { - return generateDiagram(bpmnModel, imageType, highLightedActivities, Collections.emptyList(), scaleFactor, drawSequenceFlowNameWithNoLabelDI); - } - - @Override - public InputStream generateDiagram(BpmnModel bpmnModel, String imageType, String activityFontName, - String labelFontName, String annotationFontName, ClassLoader customClassLoader, boolean drawSequenceFlowNameWithNoLabelDI) { - - return generateDiagram(bpmnModel, imageType, Collections.emptyList(), Collections.emptyList(), - activityFontName, labelFontName, annotationFontName, customClassLoader, 1.0, drawSequenceFlowNameWithNoLabelDI); - } - - @Override - public InputStream generateDiagram(BpmnModel bpmnModel, String imageType, String activityFontName, - String labelFontName, String annotationFontName, ClassLoader customClassLoader, double scaleFactor, boolean drawSequenceFlowNameWithNoLabelDI) { - - return generateDiagram(bpmnModel, imageType, Collections.emptyList(), Collections.emptyList(), - activityFontName, labelFontName, annotationFontName, customClassLoader, scaleFactor, drawSequenceFlowNameWithNoLabelDI); - } - - @Override - public InputStream generatePngDiagram(BpmnModel bpmnModel, boolean drawSequenceFlowNameWithNoLabelDI) { - return generatePngDiagram(bpmnModel, 1.0, drawSequenceFlowNameWithNoLabelDI); - } - - @Override - public InputStream generatePngDiagram(BpmnModel bpmnModel, double scaleFactor, boolean drawSequenceFlowNameWithNoLabelDI) { - return generateDiagram(bpmnModel, "png", Collections.emptyList(), Collections.emptyList(), scaleFactor, drawSequenceFlowNameWithNoLabelDI); - } - - @Override - public InputStream generateJpgDiagram(BpmnModel bpmnModel) { - return generateJpgDiagram(bpmnModel, 1.0, false); - } - - @Override - public InputStream generateJpgDiagram(BpmnModel bpmnModel, double scaleFactor, boolean drawSequenceFlowNameWithNoLabelDI) { - return generateDiagram(bpmnModel, "jpg", Collections.emptyList(), Collections.emptyList(), drawSequenceFlowNameWithNoLabelDI); - } - - public BufferedImage generateImage(BpmnModel bpmnModel, String imageType, List highLightedActivities, List highLightedFlows, - String activityFontName, String labelFontName, String annotationFontName, ClassLoader customClassLoader, double scaleFactor, boolean drawSequenceFlowNameWithNoLabelDI) { - - return generateProcessDiagram(bpmnModel, imageType, highLightedActivities, highLightedFlows, - activityFontName, labelFontName, annotationFontName, customClassLoader, scaleFactor, drawSequenceFlowNameWithNoLabelDI).generateBufferedImage(imageType); - } - - public BufferedImage generateImage(BpmnModel bpmnModel, String imageType, - List highLightedActivities, List highLightedFlows, double scaleFactor, boolean drawSequenceFlowNameWithNoLabelDI) { - - return generateImage(bpmnModel, imageType, highLightedActivities, highLightedFlows, null, null, null, null, scaleFactor, drawSequenceFlowNameWithNoLabelDI); - } - - @Override - public BufferedImage generatePngImage(BpmnModel bpmnModel, double scaleFactor) { - return generateImage(bpmnModel, "png", Collections.emptyList(), Collections.emptyList(), scaleFactor, false); - } - - protected CustomDefaultProcessDiagramCanvas generateProcessDiagram(BpmnModel bpmnModel, String imageType, - List highLightedActivities, List highLightedFlows, - String activityFontName, String labelFontName, String annotationFontName, ClassLoader customClassLoader, double scaleFactor, boolean drawSequenceFlowNameWithNoLabelDI) { - - prepareBpmnModel(bpmnModel); - - CustomDefaultProcessDiagramCanvas processDiagramCanvas = initProcessDiagramCanvas(bpmnModel, imageType, activityFontName, labelFontName, annotationFontName, customClassLoader); - - // Draw pool shape, if process is participant in collaboration - for (Pool pool : bpmnModel.getPools()) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(pool.getId()); - processDiagramCanvas.drawPoolOrLane(pool.getName(), graphicInfo, scaleFactor); - } - - // Draw lanes - for (Process process : bpmnModel.getProcesses()) { - for (Lane lane : process.getLanes()) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(lane.getId()); - processDiagramCanvas.drawPoolOrLane(lane.getName(), graphicInfo, scaleFactor); - } - } - - // Draw activities and their sequence-flows - for (Process process : bpmnModel.getProcesses()) { - for (FlowNode flowNode : process.findFlowElementsOfType(FlowNode.class)) { - if (!isPartOfCollapsedSubProcess(flowNode, bpmnModel)) { - drawActivity(processDiagramCanvas, bpmnModel, flowNode, highLightedActivities, highLightedFlows, scaleFactor, drawSequenceFlowNameWithNoLabelDI); - } - } - } - - // Draw artifacts - for (Process process : bpmnModel.getProcesses()) { - - for (Artifact artifact : process.getArtifacts()) { - drawArtifact(processDiagramCanvas, bpmnModel, artifact); - } - - List subProcesses = process.findFlowElementsOfType(SubProcess.class, true); - if (subProcesses != null) { - for (SubProcess subProcess : subProcesses) { - - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(subProcess.getId()); - if (graphicInfo != null && graphicInfo.getExpanded() != null && !graphicInfo.getExpanded()) { - continue; - } - - if (!isPartOfCollapsedSubProcess(subProcess, bpmnModel)) { - for (Artifact subProcessArtifact : subProcess.getArtifacts()) { - drawArtifact(processDiagramCanvas, bpmnModel, subProcessArtifact); - } - } - } - } - } - - return processDiagramCanvas; - } - - protected void prepareBpmnModel(BpmnModel bpmnModel) { - - // Need to make sure all elements have positive x and y. - // Check all graphicInfo and update the elements accordingly - - List allGraphicInfos = new ArrayList<>(); - if (bpmnModel.getLocationMap() != null) { - allGraphicInfos.addAll(bpmnModel.getLocationMap().values()); - } - if (bpmnModel.getLabelLocationMap() != null) { - allGraphicInfos.addAll(bpmnModel.getLabelLocationMap().values()); - } - if (bpmnModel.getFlowLocationMap() != null) { - for (List flowGraphicInfos : bpmnModel.getFlowLocationMap().values()) { - allGraphicInfos.addAll(flowGraphicInfos); - } - } - - if (allGraphicInfos.size() > 0) { - - boolean needsTranslationX = false; - boolean needsTranslationY = false; - - double lowestX = 0.0; - double lowestY = 0.0; - - // Collect lowest x and y - for (GraphicInfo graphicInfo : allGraphicInfos) { - - double x = graphicInfo.getX(); - double y = graphicInfo.getY(); - - if (x < lowestX) { - needsTranslationX = true; - lowestX = x; - } - if (y < lowestY) { - needsTranslationY = true; - lowestY = y; - } - - } - - // Update all graphicInfo objects - if (needsTranslationX || needsTranslationY) { - - double translationX = Math.abs(lowestX); - double translationY = Math.abs(lowestY); - - for (GraphicInfo graphicInfo : allGraphicInfos) { - if (needsTranslationX) { - graphicInfo.setX(graphicInfo.getX() + translationX); - } - if (needsTranslationY) { - graphicInfo.setY(graphicInfo.getY() + translationY); - } - } - } - - } - - } - - protected void drawActivity(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, - FlowNode flowNode, List highLightedActivities, List highLightedFlows, double scaleFactor, Boolean drawSequenceFlowNameWithNoLabelDI) { - - ActivityDrawInstruction drawInstruction = activityDrawInstructions.get(flowNode.getClass()); - if (drawInstruction != null) { - - drawInstruction.draw(processDiagramCanvas, bpmnModel, flowNode); - - // Gather info on the multi instance marker - boolean multiInstanceSequential = false; - boolean multiInstanceParallel = false; - boolean collapsed = false; - if (flowNode instanceof Activity) { - Activity activity = (Activity) flowNode; - MultiInstanceLoopCharacteristics multiInstanceLoopCharacteristics = activity.getLoopCharacteristics(); - if (multiInstanceLoopCharacteristics != null) { - multiInstanceSequential = multiInstanceLoopCharacteristics.isSequential(); - multiInstanceParallel = !multiInstanceSequential; - } - } - - // Gather info on the collapsed marker - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId()); - if (flowNode instanceof SubProcess) { - collapsed = graphicInfo.getExpanded() != null && !graphicInfo.getExpanded(); - } else if (flowNode instanceof CallActivity) { - collapsed = true; - } - - if (scaleFactor == 1.0) { - // Actually draw the markers - processDiagramCanvas.drawActivityMarkers((int) graphicInfo.getX(), (int) graphicInfo.getY(), (int) graphicInfo.getWidth(), (int) graphicInfo.getHeight(), - multiInstanceSequential, multiInstanceParallel, collapsed); - } - - // Draw highlighted activities - if (highLightedActivities.contains(flowNode.getId())) { - drawHighLightRed(processDiagramCanvas, bpmnModel.getGraphicInfo(flowNode.getId())); - } else if (highLightedActivities.contains(Color.RED.toString() + flowNode.getId())) { - drawHighLight(processDiagramCanvas, bpmnModel.getGraphicInfo(flowNode.getId())); - } - - } else if (flowNode instanceof Task) { - activityDrawInstructions.get(Task.class).draw(processDiagramCanvas, bpmnModel, flowNode); - - if (highLightedActivities.contains(flowNode.getId())) { - drawHighLightRed(processDiagramCanvas, bpmnModel.getGraphicInfo(flowNode.getId())); - } else if (highLightedActivities.contains(Color.RED.toString() + flowNode.getId())) { - drawHighLight(processDiagramCanvas, bpmnModel.getGraphicInfo(flowNode.getId())); - } - } - - // Outgoing transitions of activity - for (SequenceFlow sequenceFlow : flowNode.getOutgoingFlows()) { - boolean highLighted = (highLightedFlows.contains(sequenceFlow.getId())); - String defaultFlow = null; - if (flowNode instanceof Activity) { - defaultFlow = ((Activity) flowNode).getDefaultFlow(); - } else if (flowNode instanceof Gateway) { - defaultFlow = ((Gateway) flowNode).getDefaultFlow(); - } - - boolean isDefault = false; - if (defaultFlow != null && defaultFlow.equalsIgnoreCase(sequenceFlow.getId())) { - isDefault = true; - } - boolean drawConditionalIndicator = sequenceFlow.getConditionExpression() != null && sequenceFlow.getConditionExpression().trim().length() > 0 && !(flowNode instanceof Gateway); - - String sourceRef = sequenceFlow.getSourceRef(); - String targetRef = sequenceFlow.getTargetRef(); - FlowElement sourceElement = bpmnModel.getFlowElement(sourceRef); - FlowElement targetElement = bpmnModel.getFlowElement(targetRef); - List graphicInfoList = bpmnModel.getFlowLocationGraphicInfo(sequenceFlow.getId()); - if (graphicInfoList != null && graphicInfoList.size() > 0) { - graphicInfoList = connectionPerfectionizer(processDiagramCanvas, bpmnModel, sourceElement, targetElement, graphicInfoList); - int[] xPoints = new int[graphicInfoList.size()]; - int[] yPoints = new int[graphicInfoList.size()]; - - for (int i = 1; i < graphicInfoList.size(); i++) { - GraphicInfo graphicInfo = graphicInfoList.get(i); - GraphicInfo previousGraphicInfo = graphicInfoList.get(i - 1); - - if (i == 1) { - xPoints[0] = (int) previousGraphicInfo.getX(); - yPoints[0] = (int) previousGraphicInfo.getY(); - } - xPoints[i] = (int) graphicInfo.getX(); - yPoints[i] = (int) graphicInfo.getY(); - - } - - processDiagramCanvas.drawSequenceflow(xPoints, yPoints, drawConditionalIndicator, isDefault, highLighted, scaleFactor); - - // Draw sequenceflow label - GraphicInfo labelGraphicInfo = bpmnModel.getLabelGraphicInfo(sequenceFlow.getId()); - if (labelGraphicInfo != null) { - processDiagramCanvas.drawLabel(sequenceFlow.getName(), labelGraphicInfo, false); - } else { - if (drawSequenceFlowNameWithNoLabelDI) { - GraphicInfo lineCenter = getLineCenter(graphicInfoList); - processDiagramCanvas.drawLabel(sequenceFlow.getName(), lineCenter, false); - } - - } - } - } - - // Nested elements - if (flowNode instanceof FlowElementsContainer) { - for (FlowElement nestedFlowElement : ((FlowElementsContainer) flowNode).getFlowElements()) { - if (nestedFlowElement instanceof FlowNode && !isPartOfCollapsedSubProcess(nestedFlowElement, bpmnModel)) { - drawActivity(processDiagramCanvas, bpmnModel, (FlowNode) nestedFlowElement, - highLightedActivities, highLightedFlows, scaleFactor, drawSequenceFlowNameWithNoLabelDI); - } - } - } - } - - /** - * This method makes coordinates of connection flow better. - * - * @param processDiagramCanvas - * @param bpmnModel - * @param sourceElement - * @param targetElement - * @param graphicInfoList - * @return - */ - protected static List connectionPerfectionizer(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, BaseElement sourceElement, BaseElement targetElement, List graphicInfoList) { - GraphicInfo sourceGraphicInfo = bpmnModel.getGraphicInfo(sourceElement.getId()); - GraphicInfo targetGraphicInfo = bpmnModel.getGraphicInfo(targetElement.getId()); - - CustomDefaultProcessDiagramCanvas.SHAPE_TYPE sourceShapeType = getShapeType(sourceElement); - CustomDefaultProcessDiagramCanvas.SHAPE_TYPE targetShapeType = getShapeType(targetElement); - - return processDiagramCanvas.connectionPerfectionizer(sourceShapeType, targetShapeType, sourceGraphicInfo, targetGraphicInfo, graphicInfoList); - } - - /** - * This method returns shape type of base element.
- * Each element can be presented as rectangle, rhombus, or ellipse. - * - * @param baseElement - * @return CustomDefaultProcessDiagramCanvas.SHAPE_TYPE - */ - protected static CustomDefaultProcessDiagramCanvas.SHAPE_TYPE getShapeType(BaseElement baseElement) { - if (baseElement instanceof Task || baseElement instanceof Activity || baseElement instanceof TextAnnotation) { - return CustomDefaultProcessDiagramCanvas.SHAPE_TYPE.Rectangle; - } else if (baseElement instanceof Gateway) { - return CustomDefaultProcessDiagramCanvas.SHAPE_TYPE.Rhombus; - } else if (baseElement instanceof Event) { - return CustomDefaultProcessDiagramCanvas.SHAPE_TYPE.Ellipse; - } else { - // unknown source element, just do not correct coordinates - } - return null; - } - - protected static GraphicInfo getLineCenter(List graphicInfoList) { - GraphicInfo gi = new GraphicInfo(); - - int[] xPoints = new int[graphicInfoList.size()]; - int[] yPoints = new int[graphicInfoList.size()]; - - double length = 0; - double[] lengths = new double[graphicInfoList.size()]; - lengths[0] = 0; - double m; - for (int i = 1; i < graphicInfoList.size(); i++) { - GraphicInfo graphicInfo = graphicInfoList.get(i); - GraphicInfo previousGraphicInfo = graphicInfoList.get(i - 1); - - if (i == 1) { - xPoints[0] = (int) previousGraphicInfo.getX(); - yPoints[0] = (int) previousGraphicInfo.getY(); - } - xPoints[i] = (int) graphicInfo.getX(); - yPoints[i] = (int) graphicInfo.getY(); - - length += Math.sqrt( - Math.pow((int) graphicInfo.getX() - (int) previousGraphicInfo.getX(), 2) + - Math.pow((int) graphicInfo.getY() - (int) previousGraphicInfo.getY(), 2)); - lengths[i] = length; - } - m = length / 2; - int p1 = 0; - int p2 = 1; - for (int i = 1; i < lengths.length; i++) { - double len = lengths[i]; - p1 = i - 1; - p2 = i; - if (len > m) { - break; - } - } - - GraphicInfo graphicInfo1 = graphicInfoList.get(p1); - GraphicInfo graphicInfo2 = graphicInfoList.get(p2); - - double AB = (int) graphicInfo2.getX() - (int) graphicInfo1.getX(); - double OA = (int) graphicInfo2.getY() - (int) graphicInfo1.getY(); - double OB = lengths[p2] - lengths[p1]; - double ob = m - lengths[p1]; - double ab = AB * ob / OB; - double oa = OA * ob / OB; - - double mx = graphicInfo1.getX() + ab; - double my = graphicInfo1.getY() + oa; - - gi.setX(mx); - gi.setY(my); - return gi; - } - - protected void drawArtifact(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, Artifact artifact) { - - ArtifactDrawInstruction drawInstruction = artifactDrawInstructions.get(artifact.getClass()); - if (drawInstruction != null) { - drawInstruction.draw(processDiagramCanvas, bpmnModel, artifact); - } - } - - private static void drawHighLight(CustomDefaultProcessDiagramCanvas processDiagramCanvas, GraphicInfo graphicInfo) { - processDiagramCanvas.drawHighLight((int) graphicInfo.getX(), (int) graphicInfo.getY(), (int) graphicInfo.getWidth(), (int) graphicInfo.getHeight()); - - } - - private static void drawHighLightRed(CustomDefaultProcessDiagramCanvas processDiagramCanvas, GraphicInfo graphicInfo) { - processDiagramCanvas.drawHighLightRed((int) graphicInfo.getX(), (int) graphicInfo.getY(), (int) graphicInfo.getWidth(), (int) graphicInfo.getHeight()); - - } - - protected static CustomDefaultProcessDiagramCanvas initProcessDiagramCanvas(BpmnModel bpmnModel, String imageType, - String activityFontName, String labelFontName, String annotationFontName, ClassLoader customClassLoader) { - - // We need to calculate maximum values to know how big the image will be in its entirety - double minX = Double.MAX_VALUE; - double maxX = 0; - double minY = Double.MAX_VALUE; - double maxY = 0; - - for (Pool pool : bpmnModel.getPools()) { - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(pool.getId()); - minX = graphicInfo.getX(); - maxX = graphicInfo.getX() + graphicInfo.getWidth(); - minY = graphicInfo.getY(); - maxY = graphicInfo.getY() + graphicInfo.getHeight(); - } - - List flowNodes = gatherAllFlowNodes(bpmnModel); - for (FlowNode flowNode : flowNodes) { - - GraphicInfo flowNodeGraphicInfo = bpmnModel.getGraphicInfo(flowNode.getId()); - - // width - if (flowNodeGraphicInfo.getX() + flowNodeGraphicInfo.getWidth() > maxX) { - maxX = flowNodeGraphicInfo.getX() + flowNodeGraphicInfo.getWidth(); - } - if (flowNodeGraphicInfo.getX() < minX) { - minX = flowNodeGraphicInfo.getX(); - } - // height - if (flowNodeGraphicInfo.getY() + flowNodeGraphicInfo.getHeight() > maxY) { - maxY = flowNodeGraphicInfo.getY() + flowNodeGraphicInfo.getHeight(); - } - if (flowNodeGraphicInfo.getY() < minY) { - minY = flowNodeGraphicInfo.getY(); - } - - for (SequenceFlow sequenceFlow : flowNode.getOutgoingFlows()) { - List graphicInfoList = bpmnModel.getFlowLocationGraphicInfo(sequenceFlow.getId()); - if (graphicInfoList != null) { - for (GraphicInfo graphicInfo : graphicInfoList) { - // width - if (graphicInfo.getX() > maxX) { - maxX = graphicInfo.getX(); - } - if (graphicInfo.getX() < minX) { - minX = graphicInfo.getX(); - } - // height - if (graphicInfo.getY() > maxY) { - maxY = graphicInfo.getY(); - } - if (graphicInfo.getY() < minY) { - minY = graphicInfo.getY(); - } - } - } - } - } - - List artifacts = gatherAllArtifacts(bpmnModel); - for (Artifact artifact : artifacts) { - - GraphicInfo artifactGraphicInfo = bpmnModel.getGraphicInfo(artifact.getId()); - - if (artifactGraphicInfo != null) { - // width - if (artifactGraphicInfo.getX() + artifactGraphicInfo.getWidth() > maxX) { - maxX = artifactGraphicInfo.getX() + artifactGraphicInfo.getWidth(); - } - if (artifactGraphicInfo.getX() < minX) { - minX = artifactGraphicInfo.getX(); - } - // height - if (artifactGraphicInfo.getY() + artifactGraphicInfo.getHeight() > maxY) { - maxY = artifactGraphicInfo.getY() + artifactGraphicInfo.getHeight(); - } - if (artifactGraphicInfo.getY() < minY) { - minY = artifactGraphicInfo.getY(); - } - } - - List graphicInfoList = bpmnModel.getFlowLocationGraphicInfo(artifact.getId()); - if (graphicInfoList != null) { - for (GraphicInfo graphicInfo : graphicInfoList) { - // width - if (graphicInfo.getX() > maxX) { - maxX = graphicInfo.getX(); - } - if (graphicInfo.getX() < minX) { - minX = graphicInfo.getX(); - } - // height - if (graphicInfo.getY() > maxY) { - maxY = graphicInfo.getY(); - } - if (graphicInfo.getY() < minY) { - minY = graphicInfo.getY(); - } - } - } - } - - int nrOfLanes = 0; - for (Process process : bpmnModel.getProcesses()) { - for (Lane l : process.getLanes()) { - - nrOfLanes++; - - GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(l.getId()); - // // width - if (graphicInfo.getX() + graphicInfo.getWidth() > maxX) { - maxX = graphicInfo.getX() + graphicInfo.getWidth(); - } - if (graphicInfo.getX() < minX) { - minX = graphicInfo.getX(); - } - // height - if (graphicInfo.getY() + graphicInfo.getHeight() > maxY) { - maxY = graphicInfo.getY() + graphicInfo.getHeight(); - } - if (graphicInfo.getY() < minY) { - minY = graphicInfo.getY(); - } - } - } - - // Special case, see https://activiti.atlassian.net/browse/ACT-1431 - if (flowNodes.isEmpty() && bpmnModel.getPools().isEmpty() && nrOfLanes == 0) { - // Nothing to show - minX = 0; - minY = 0; - } - - return new CustomDefaultProcessDiagramCanvas((int) maxX + 10, (int) maxY + 10, (int) minX, (int) minY, - imageType, activityFontName, labelFontName, annotationFontName, customClassLoader); - } - - protected static List gatherAllArtifacts(BpmnModel bpmnModel) { - List artifacts = new ArrayList<>(); - for (Process process : bpmnModel.getProcesses()) { - artifacts.addAll(process.getArtifacts()); - } - return artifacts; - } - - protected static List gatherAllFlowNodes(BpmnModel bpmnModel) { - List flowNodes = new ArrayList<>(); - for (Process process : bpmnModel.getProcesses()) { - flowNodes.addAll(gatherAllFlowNodes(process)); - } - return flowNodes; - } - - protected static List gatherAllFlowNodes(FlowElementsContainer flowElementsContainer) { - List flowNodes = new ArrayList<>(); - for (FlowElement flowElement : flowElementsContainer.getFlowElements()) { - if (flowElement instanceof FlowNode) { - flowNodes.add((FlowNode) flowElement); - } - if (flowElement instanceof FlowElementsContainer) { - flowNodes.addAll(gatherAllFlowNodes((FlowElementsContainer) flowElement)); - } - } - return flowNodes; - } - - protected boolean isPartOfCollapsedSubProcess(FlowElement flowElement, BpmnModel model) { - SubProcess subProcess = flowElement.getSubProcess(); - if (subProcess != null) { - GraphicInfo graphicInfo = model.getGraphicInfo(subProcess.getId()); - if (graphicInfo != null && graphicInfo.getExpanded() != null && !graphicInfo.getExpanded()) { - return true; - } - - return isPartOfCollapsedSubProcess(subProcess, model); - } - - return false; - } - - public Map, ActivityDrawInstruction> getActivityDrawInstructions() { - return activityDrawInstructions; - } - - public void setActivityDrawInstructions( - Map, ActivityDrawInstruction> activityDrawInstructions) { - this.activityDrawInstructions = activityDrawInstructions; - } - - public Map, ArtifactDrawInstruction> getArtifactDrawInstructions() { - return artifactDrawInstructions; - } - - public void setArtifactDrawInstructions( - Map, ArtifactDrawInstruction> artifactDrawInstructions) { - this.artifactDrawInstructions = artifactDrawInstructions; - } - - protected interface ActivityDrawInstruction { - void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode); - } - - protected interface ArtifactDrawInstruction { - void draw(CustomDefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, Artifact artifact); - } -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/AddSequenceMultiInstanceCmd.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/AddSequenceMultiInstanceCmd.java deleted file mode 100644 index 3cdfcf415..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/AddSequenceMultiInstanceCmd.java +++ /dev/null @@ -1,61 +0,0 @@ -package org.dromara.workflow.flowable.cmd; - -import cn.hutool.core.collection.CollUtil; -import org.flowable.common.engine.impl.interceptor.Command; -import org.flowable.common.engine.impl.interceptor.CommandContext; -import org.flowable.engine.impl.persistence.entity.ExecutionEntity; -import org.flowable.engine.impl.persistence.entity.ExecutionEntityManager; -import org.flowable.engine.impl.util.CommandContextUtil; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static org.dromara.workflow.common.constant.FlowConstant.NUMBER_OF_INSTANCES; - -/** - * 串行加签 - * - * @author may - */ -public class AddSequenceMultiInstanceCmd implements Command { - - /** - * 执行id - */ - private final String executionId; - - /** - * 会签人员集合KEY - */ - private final String assigneeList; - - /** - * 加签人员 - */ - private final List assignees; - - public AddSequenceMultiInstanceCmd(String executionId, String assigneeList, List assignees) { - this.executionId = executionId; - this.assigneeList = assigneeList; - this.assignees = assignees; - } - - @Override - public Void execute(CommandContext commandContext) { - ExecutionEntityManager executionEntityManager = CommandContextUtil.getExecutionEntityManager(); - ExecutionEntity entity = executionEntityManager.findById(executionId); - // 多实例任务总数加 assignees.size() - if (entity.getVariable(NUMBER_OF_INSTANCES) instanceof Integer nrOfInstances) { - entity.setVariable(NUMBER_OF_INSTANCES, nrOfInstances + assignees.size()); - } - // 设置流程变量 - if (entity.getVariable(assigneeList) instanceof List userIds) { - CollUtil.addAll(userIds, assignees); - Map variables = new HashMap<>(16); - variables.put(assigneeList, userIds); - entity.setVariables(variables); - } - return null; - } -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/AttachmentCmd.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/AttachmentCmd.java deleted file mode 100644 index 20a0a5f3a..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/AttachmentCmd.java +++ /dev/null @@ -1,66 +0,0 @@ -package org.dromara.workflow.flowable.cmd; - -import cn.hutool.core.collection.CollUtil; -import org.dromara.common.core.domain.dto.OssDTO; -import org.dromara.common.core.service.OssService; -import org.dromara.common.core.utils.StringUtils; -import org.dromara.common.satoken.utils.LoginHelper; -import org.flowable.common.engine.impl.interceptor.Command; -import org.flowable.common.engine.impl.interceptor.CommandContext; -import org.flowable.engine.impl.persistence.entity.AttachmentEntity; -import org.flowable.engine.impl.persistence.entity.AttachmentEntityManager; -import org.flowable.engine.impl.util.CommandContextUtil; - -import java.util.Date; -import java.util.List; - -/** - * 附件上传 - * - * @author may - */ -public class AttachmentCmd implements Command { - - private final String fileId; - - private final String taskId; - - private final String processInstanceId; - - private final OssService ossService; - - public AttachmentCmd(String fileId, String taskId, String processInstanceId, OssService ossService) { - this.fileId = fileId; - this.taskId = taskId; - this.processInstanceId = processInstanceId; - this.ossService = ossService; - } - - @Override - public Boolean execute(CommandContext commandContext) { - try { - if (StringUtils.isNotBlank(fileId)) { - List ossList = ossService.selectByIds(fileId); - if (CollUtil.isNotEmpty(ossList)) { - for (OssDTO oss : ossList) { - AttachmentEntityManager attachmentEntityManager = CommandContextUtil.getAttachmentEntityManager(); - AttachmentEntity attachmentEntity = attachmentEntityManager.create(); - attachmentEntity.setRevision(1); - attachmentEntity.setUserId(LoginHelper.getUserId().toString()); - attachmentEntity.setName(oss.getOriginalName()); - attachmentEntity.setDescription(oss.getOriginalName()); - attachmentEntity.setType(oss.getFileSuffix()); - attachmentEntity.setTaskId(taskId); - attachmentEntity.setProcessInstanceId(processInstanceId); - attachmentEntity.setContentId(oss.getOssId().toString()); - attachmentEntity.setTime(new Date()); - attachmentEntityManager.insert(attachmentEntity); - } - } - } - } catch (Exception e) { - throw new RuntimeException(e); - } - return true; - } -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/DeleteExecutionCmd.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/DeleteExecutionCmd.java deleted file mode 100644 index 215d31023..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/DeleteExecutionCmd.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.dromara.workflow.flowable.cmd; - -import org.flowable.common.engine.impl.interceptor.Command; -import org.flowable.common.engine.impl.interceptor.CommandContext; -import org.flowable.engine.impl.persistence.entity.ExecutionEntity; -import org.flowable.engine.impl.persistence.entity.ExecutionEntityManager; -import org.flowable.engine.impl.util.CommandContextUtil; - -import java.io.Serializable; - -/** - * 删除执行数据 - * - * @author may - */ -public class DeleteExecutionCmd implements Command, Serializable { - - /** - * 执行id - */ - private final String executionId; - - public DeleteExecutionCmd(String executionId) { - this.executionId = executionId; - } - - @Override - public Void execute(CommandContext commandContext) { - ExecutionEntityManager executionEntityManager = CommandContextUtil.getExecutionEntityManager(); - ExecutionEntity entity = executionEntityManager.findById(executionId); - if (entity != null) { - executionEntityManager.deleteExecutionAndRelatedData(entity, "", false, false); - } - return null; - } -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/DeleteSequenceMultiInstanceCmd.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/DeleteSequenceMultiInstanceCmd.java deleted file mode 100644 index a61daebc5..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/DeleteSequenceMultiInstanceCmd.java +++ /dev/null @@ -1,83 +0,0 @@ -package org.dromara.workflow.flowable.cmd; - -import cn.hutool.core.util.ObjectUtil; -import lombok.AllArgsConstructor; -import org.dromara.common.core.utils.StreamUtils; -import org.flowable.common.engine.impl.interceptor.Command; -import org.flowable.common.engine.impl.interceptor.CommandContext; -import org.flowable.engine.impl.persistence.entity.ExecutionEntity; -import org.flowable.engine.impl.persistence.entity.ExecutionEntityManager; -import org.flowable.engine.impl.util.CommandContextUtil; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static org.dromara.workflow.common.constant.FlowConstant.LOOP_COUNTER; -import static org.dromara.workflow.common.constant.FlowConstant.NUMBER_OF_INSTANCES; - - -/** - * 串行减签 - * - * @author may - */ -@AllArgsConstructor -public class DeleteSequenceMultiInstanceCmd implements Command { - - /** - * 当前节点审批人员id - */ - private final String currentUserId; - - /** - * 执行id - */ - private final String executionId; - - /** - * 会签人员集合KEY - */ - private final String assigneeList; - - /** - * 减签人员 - */ - private final List assignees; - - - @Override - @SuppressWarnings("unchecked") - public Void execute(CommandContext commandContext) { - ExecutionEntityManager executionEntityManager = CommandContextUtil.getExecutionEntityManager(); - ExecutionEntity entity = executionEntityManager.findById(executionId); - // 设置流程变量 - List userIds = new ArrayList<>(); - List variable = (List) entity.getVariable(assigneeList); - for (Object o : variable) { - userIds.add(Long.valueOf(o.toString())); - } - List userIdList = new ArrayList<>(); - userIds.forEach(e -> { - Long userId = StreamUtils.findFirst(assignees, id -> ObjectUtil.equals(id, e)); - if (userId == null) { - userIdList.add(e); - } - }); - // 当前任务执行位置 - int loopCounterIndex = -1; - for (int i = 0; i < userIdList.size(); i++) { - Long userId = userIdList.get(i); - if (currentUserId.equals(userId.toString())) { - loopCounterIndex = i; - } - } - Map variables = new HashMap<>(16); - variables.put(NUMBER_OF_INSTANCES, userIdList.size()); - variables.put(assigneeList, userIdList); - variables.put(LOOP_COUNTER, loopCounterIndex); - entity.setVariables(variables); - return null; - } -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/ExecutionChildByExecutionIdCmd.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/ExecutionChildByExecutionIdCmd.java deleted file mode 100644 index 1f3088bfc..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/ExecutionChildByExecutionIdCmd.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.dromara.workflow.flowable.cmd; - -import org.dromara.common.core.utils.StreamUtils; -import org.flowable.common.engine.impl.interceptor.Command; -import org.flowable.common.engine.impl.interceptor.CommandContext; -import org.flowable.engine.impl.persistence.entity.ExecutionEntity; -import org.flowable.engine.impl.persistence.entity.ExecutionEntityManager; -import org.flowable.engine.impl.util.CommandContextUtil; - -import java.io.Serializable; -import java.util.List; - -/** - * 获取并行网关执行后保留的执行实例数据 - * - * @author may - */ -public class ExecutionChildByExecutionIdCmd implements Command>, Serializable { - - /** - * 当前任务执行实例id - */ - private final String executionId; - - public ExecutionChildByExecutionIdCmd(String executionId) { - this.executionId = executionId; - } - - @Override - public List execute(CommandContext commandContext) { - ExecutionEntityManager executionEntityManager = CommandContextUtil.getExecutionEntityManager(); - // 获取当前执行数据 - ExecutionEntity executionEntity = executionEntityManager.findById(executionId); - // 通过当前执行数据的父执行,查询所有子执行数据 - List allChildrenExecution = - executionEntityManager.collectChildren(executionEntity.getParent()); - return StreamUtils.filter(allChildrenExecution, e -> !e.isActive()); - } -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/UpdateBusinessStatusCmd.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/UpdateBusinessStatusCmd.java deleted file mode 100644 index 3ba120aef..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/UpdateBusinessStatusCmd.java +++ /dev/null @@ -1,37 +0,0 @@ -package org.dromara.workflow.flowable.cmd; - -import org.dromara.common.core.exception.ServiceException; -import org.flowable.common.engine.impl.interceptor.Command; -import org.flowable.common.engine.impl.interceptor.CommandContext; -import org.flowable.engine.impl.persistence.entity.HistoricProcessInstanceEntity; -import org.flowable.engine.impl.persistence.entity.HistoricProcessInstanceEntityManager; -import org.flowable.engine.impl.util.CommandContextUtil; - -/** - * 修改流程状态 - * - * @author may - */ -public class UpdateBusinessStatusCmd implements Command { - - private final String processInstanceId; - private final String status; - - public UpdateBusinessStatusCmd(String processInstanceId, String status) { - this.processInstanceId = processInstanceId; - this.status = status; - } - - @Override - public Boolean execute(CommandContext commandContext) { - try { - HistoricProcessInstanceEntityManager manager = CommandContextUtil.getHistoricProcessInstanceEntityManager(); - HistoricProcessInstanceEntity processInstance = manager.findById(processInstanceId); - processInstance.setBusinessStatus(status); - manager.update(processInstance); - return true; - } catch (Exception e) { - throw new ServiceException(e.getMessage()); - } - } -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/UpdateHiTaskInstCmd.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/UpdateHiTaskInstCmd.java deleted file mode 100644 index 42f6d1c78..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/UpdateHiTaskInstCmd.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.dromara.workflow.flowable.cmd; - -import org.dromara.common.core.exception.ServiceException; -import org.flowable.common.engine.impl.interceptor.Command; -import org.flowable.common.engine.impl.interceptor.CommandContext; -import org.flowable.engine.impl.util.CommandContextUtil; -import org.flowable.task.service.HistoricTaskService; -import org.flowable.task.service.impl.persistence.entity.HistoricTaskInstanceEntity; - -import java.util.Date; -import java.util.List; - - -/** - * 修改流程历史 - * - * @author may - */ -public class UpdateHiTaskInstCmd implements Command { - - private final List taskIds; - - private final String processDefinitionId; - - private final String processInstanceId; - - public UpdateHiTaskInstCmd(List taskIds, String processDefinitionId, String processInstanceId) { - this.taskIds = taskIds; - this.processDefinitionId = processDefinitionId; - this.processInstanceId = processInstanceId; - } - - @Override - public Boolean execute(CommandContext commandContext) { - try { - HistoricTaskService historicTaskService = CommandContextUtil.getHistoricTaskService(); - for (String taskId : taskIds) { - HistoricTaskInstanceEntity historicTask = historicTaskService.getHistoricTask(taskId); - if (historicTask != null) { - historicTask.setProcessDefinitionId(processDefinitionId); - historicTask.setProcessInstanceId(processInstanceId); - historicTask.setCreateTime(new Date()); - CommandContextUtil.getHistoricTaskService().updateHistoricTask(historicTask, true); - } - } - return true; - } catch (Exception e) { - throw new ServiceException(e.getMessage()); - } - } -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/config/FlowableConfig.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/config/FlowableConfig.java deleted file mode 100644 index 1494bf37f..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/config/FlowableConfig.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.dromara.workflow.flowable.config; - -import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator; -import org.dromara.workflow.flowable.handler.TaskTimeoutJobHandler; -import org.flowable.spring.SpringProcessEngineConfiguration; -import org.flowable.spring.boot.EngineConfigurationConfigurer; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Configuration; - -import java.util.Collections; - - -/** - * flowable配置 - * - * @author may - */ -@Configuration -public class FlowableConfig implements EngineConfigurationConfigurer { - - @Autowired - private GlobalFlowableListener globalFlowableListener; - @Autowired - private IdentifierGenerator identifierGenerator; - - @Override - public void configure(SpringProcessEngineConfiguration processEngineConfiguration) { - processEngineConfiguration.setIdGenerator(() -> identifierGenerator.nextId(null).toString()); - processEngineConfiguration.setEventListeners(Collections.singletonList(globalFlowableListener)); - processEngineConfiguration.addCustomJobHandler(new TaskTimeoutJobHandler()); - } -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/config/GlobalFlowableListener.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/config/GlobalFlowableListener.java deleted file mode 100644 index 9bb971a8c..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/config/GlobalFlowableListener.java +++ /dev/null @@ -1,139 +0,0 @@ -package org.dromara.workflow.flowable.config; - -import cn.hutool.core.collection.CollUtil; -import org.dromara.common.core.utils.StringUtils; -import org.dromara.common.tenant.helper.TenantHelper; -import org.dromara.workflow.common.enums.TaskStatusEnum; -import org.dromara.workflow.flowable.handler.TaskTimeoutJobHandler; -import org.dromara.workflow.utils.QueryUtils; -import org.flowable.bpmn.model.BoundaryEvent; -import org.flowable.bpmn.model.BpmnModel; -import org.flowable.bpmn.model.FlowElement; -import org.flowable.common.engine.api.delegate.event.*; -import org.flowable.common.engine.impl.cfg.TransactionState; -import org.flowable.engine.RepositoryService; -import org.flowable.engine.RuntimeService; -import org.flowable.engine.TaskService; -import org.flowable.engine.impl.util.CommandContextUtil; -import org.flowable.engine.runtime.Execution; -import org.flowable.engine.task.Comment; -import org.flowable.job.service.TimerJobService; -import org.flowable.job.service.impl.persistence.entity.JobEntity; -import org.flowable.job.service.impl.persistence.entity.TimerJobEntity; -import org.flowable.task.api.Task; -import org.flowable.task.service.impl.persistence.entity.TaskEntity; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Lazy; -import org.springframework.stereotype.Component; - -import java.util.Date; -import java.util.List; - - -/** - * 引擎调度监听 - * - * @author may - */ -@Component -public class GlobalFlowableListener implements FlowableEventListener { - - @Autowired - @Lazy - private TaskService taskService; - - @Autowired - @Lazy - private RuntimeService runtimeService; - - @Autowired - @Lazy - private RepositoryService repositoryService; - - @Value("${flowable.async-executor-activate}") - private boolean asyncExecutorActivate; - - @Override - public void onEvent(FlowableEvent flowableEvent) { - if (flowableEvent instanceof FlowableEngineEvent flowableEngineEvent) { - FlowableEngineEventType engineEventType = (FlowableEngineEventType) flowableEvent.getType(); - switch (engineEventType) { - case JOB_EXECUTION_SUCCESS -> jobExecutionSuccess((FlowableEngineEntityEvent) flowableEngineEvent); - case TASK_DUEDATE_CHANGED, TASK_CREATED -> { - FlowableEntityEvent flowableEntityEvent = (FlowableEntityEvent) flowableEngineEvent; - Object entityObject = flowableEntityEvent.getEntity(); - TaskEntity task = (TaskEntity) entityObject; - if (asyncExecutorActivate && task.getDueDate() != null && task.getDueDate().after(new Date())) { - //删除之前已经存在的定时任务 - TimerJobService timerJobService = CommandContextUtil.getTimerJobService(); - List timerJobEntityList = timerJobService.findTimerJobsByProcessInstanceId(task.getProcessInstanceId()); - if (!CollUtil.isEmpty(timerJobEntityList)) { - for (TimerJobEntity timerJobEntity : timerJobEntityList) { - String taskId = timerJobEntity.getJobHandlerConfiguration(); - if (task.getId().equals(taskId)) { - timerJobService.deleteTimerJob(timerJobEntity); - } - } - } - //创建job对象 - TimerJobEntity timer = timerJobService.createTimerJob(); - timer.setTenantId(TenantHelper.getTenantId()); - //设置job类型 - timer.setJobType(JobEntity.JOB_TYPE_TIMER); - timer.setJobHandlerType(TaskTimeoutJobHandler.TYPE); - timer.setDuedate(task.getDueDate()); - timer.setProcessInstanceId(task.getProcessInstanceId()); - //设置任务id - timer.setJobHandlerConfiguration(task.getId()); - //保存并触发事件 - timerJobService.scheduleTimerJob(timer); - } - } - } - } - } - - @Override - public boolean isFailOnException() { - return true; - } - - @Override - public boolean isFireOnTransactionLifecycleEvent() { - return false; - } - - @Override - public String getOnTransaction() { - return TransactionState.COMMITTED.name(); - } - - /** - * 处理边界定时事件自动审批记录 - * - * @param event 事件 - */ - protected void jobExecutionSuccess(FlowableEngineEntityEvent event) { - if (event != null && StringUtils.isNotBlank(event.getExecutionId())) { - Execution execution = runtimeService.createExecutionQuery().executionId(event.getExecutionId()).singleResult(); - if (execution != null) { - BpmnModel bpmnModel = repositoryService.getBpmnModel(event.getProcessDefinitionId()); - FlowElement flowElement = bpmnModel.getFlowElement(execution.getActivityId()); - if (flowElement instanceof BoundaryEvent) { - String attachedToRefId = ((BoundaryEvent) flowElement).getAttachedToRefId(); - List list = runtimeService.createExecutionQuery().activityId(attachedToRefId).list(); - for (Execution ex : list) { - Task task = QueryUtils.taskQuery().executionId(ex.getId()).singleResult(); - if (task != null) { - List taskComments = taskService.getTaskComments(task.getId()); - if (CollUtil.isEmpty(taskComments)) { - taskService.addComment(task.getId(), task.getProcessInstanceId(), TaskStatusEnum.PASS.getStatus(), "超时自动审批!"); - } - } - } - } - } - } - } -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/handler/FlowProcessEventHandler.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/handler/FlowProcessEventHandler.java deleted file mode 100644 index 69ae70a07..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/handler/FlowProcessEventHandler.java +++ /dev/null @@ -1,50 +0,0 @@ -package org.dromara.workflow.flowable.handler; - -import org.dromara.common.core.domain.event.ProcessEvent; -import org.dromara.common.core.domain.event.ProcessTaskEvent; -import org.dromara.common.core.utils.SpringUtils; -import org.springframework.stereotype.Component; - -/** - * 流程监听服务 - * - * @author may - * @date 2024-06-02 - */ -@Component -public class FlowProcessEventHandler { - - /** - * 总体流程监听(例如: 提交 退回 撤销 终止 作废等) - * - * @param key 流程key - * @param businessKey 业务id - * @param status 状态 - * @param submit 当为true时为申请人节点办理 - */ - public void processHandler(String key, String businessKey, String status, boolean submit) { - ProcessEvent processEvent = new ProcessEvent(); - processEvent.setKey(key); - processEvent.setBusinessKey(businessKey); - processEvent.setStatus(status); - processEvent.setSubmit(submit); - SpringUtils.context().publishEvent(processEvent); - } - - /** - * 执行办理任务监听 - * - * @param key 流程key - * @param taskDefinitionKey 审批节点key - * @param taskId 任务id - * @param businessKey 业务id - */ - public void processTaskHandler(String key, String taskDefinitionKey, String taskId, String businessKey) { - ProcessTaskEvent processTaskEvent = new ProcessTaskEvent(); - processTaskEvent.setKey(key); - processTaskEvent.setTaskDefinitionKey(taskDefinitionKey); - processTaskEvent.setTaskId(taskId); - processTaskEvent.setBusinessKey(businessKey); - SpringUtils.context().publishEvent(processTaskEvent); - } -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/handler/TaskTimeoutJobHandler.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/handler/TaskTimeoutJobHandler.java deleted file mode 100644 index 61c938864..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/handler/TaskTimeoutJobHandler.java +++ /dev/null @@ -1,37 +0,0 @@ -package org.dromara.workflow.flowable.handler; - -import org.dromara.workflow.common.enums.TaskStatusEnum; -import org.flowable.common.engine.impl.interceptor.CommandContext; -import org.flowable.engine.TaskService; -import org.flowable.engine.impl.jobexecutor.TimerEventHandler; -import org.flowable.engine.impl.util.CommandContextUtil; -import org.flowable.job.service.JobHandler; -import org.flowable.job.service.impl.persistence.entity.JobEntity; -import org.flowable.task.api.Task; -import org.flowable.variable.api.delegate.VariableScope; - -/** - * 办理超时(过期)任务 - * - * @author may - */ -public class TaskTimeoutJobHandler extends TimerEventHandler implements JobHandler { - - public static final String TYPE = "taskTimeout"; - - @Override - public String getType() { - return TYPE; - } - - @Override - public void execute(JobEntity job, String configuration, VariableScope variableScope, CommandContext commandContext) { - TaskService taskService = CommandContextUtil.getProcessEngineConfiguration(commandContext) - .getTaskService(); - Task task = taskService.createTaskQuery().taskId(configuration).singleResult(); - if (task != null) { - taskService.addComment(task.getId(), task.getProcessInstanceId(), TaskStatusEnum.TIMEOUT.getStatus(), "超时自动审批!"); - taskService.complete(configuration); - } - } -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/handler/FlowProcessEventHandler.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/handler/FlowProcessEventHandler.java new file mode 100644 index 000000000..9bac6bcd2 --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/handler/FlowProcessEventHandler.java @@ -0,0 +1,77 @@ +package org.dromara.workflow.handler; + +import lombok.extern.slf4j.Slf4j; +import org.dromara.common.core.domain.event.ProcessDeleteEvent; +import org.dromara.common.core.domain.event.ProcessEvent; +import org.dromara.common.core.domain.event.ProcessTaskEvent; +import org.dromara.common.core.utils.SpringUtils; +import org.dromara.common.tenant.helper.TenantHelper; +import org.springframework.stereotype.Component; + +/** + * 流程监听服务 + * + * @author may + * @date 2024-06-02 + */ +@Slf4j +@Component +public class FlowProcessEventHandler { + + /** + * 总体流程监听(例如: 草稿,撤销,退回,作废,终止,已完成等) + * + * @param flowCode 流程定义编码 + * @param businessId 业务id + * @param status 状态 + * @param submit 当为true时为申请人节点办理 + */ + public void processHandler(String flowCode, String businessId, String status, boolean submit) { + String tenantId = TenantHelper.getTenantId(); + log.info("发布流程事件,租户ID: {}, 流程状态: {}, 流程编码: {}, 业务ID: {}, 是否申请人节点办理: {}", tenantId, status, flowCode, businessId, submit); + ProcessEvent processEvent = new ProcessEvent(); + processEvent.setTenantId(tenantId); + processEvent.setFlowCode(flowCode); + processEvent.setBusinessId(businessId); + processEvent.setStatus(status); + processEvent.setSubmit(submit); + SpringUtils.context().publishEvent(processEvent); + } + + /** + * 执行办理任务监听 + * + * @param flowCode 流程定义编码 + * @param nodeCode 审批节点编码 + * @param taskId 任务id + * @param businessId 业务id + */ + public void processTaskHandler(String flowCode, String nodeCode, Long taskId, String businessId) { + String tenantId = TenantHelper.getTenantId(); + log.info("发布流程任务事件, 租户ID: {}, 流程编码: {}, 节点编码: {}, 任务ID: {}, 业务ID: {}", tenantId, flowCode, nodeCode, taskId, businessId); + ProcessTaskEvent processTaskEvent = new ProcessTaskEvent(); + processTaskEvent.setTenantId(tenantId); + processTaskEvent.setFlowCode(flowCode); + processTaskEvent.setNodeCode(nodeCode); + processTaskEvent.setTaskId(taskId); + processTaskEvent.setBusinessId(businessId); + SpringUtils.context().publishEvent(processTaskEvent); + } + + /** + * 删除流程监听 + * + * @param flowCode 流程定义编码 + * @param businessId 业务ID + */ + public void processDeleteHandler(String flowCode, String businessId) { + String tenantId = TenantHelper.getTenantId(); + log.info("发布删除流程事件, 租户ID: {}, 流程编码: {}, 业务ID: {}", tenantId, flowCode, businessId); + ProcessDeleteEvent processDeleteEvent = new ProcessDeleteEvent(); + processDeleteEvent.setTenantId(tenantId); + processDeleteEvent.setFlowCode(flowCode); + processDeleteEvent.setBusinessId(businessId); + SpringUtils.context().publishEvent(processDeleteEvent); + } + +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/handler/WorkflowPermissionHandler.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/handler/WorkflowPermissionHandler.java new file mode 100644 index 000000000..a58709a5f --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/handler/WorkflowPermissionHandler.java @@ -0,0 +1,71 @@ +package org.dromara.workflow.handler; + +import cn.hutool.core.util.ObjectUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.dromara.common.core.domain.model.LoginUser; +import org.dromara.workflow.common.enums.TaskAssigneeEnum; +import org.dromara.common.satoken.utils.LoginHelper; +import org.dromara.warm.flow.core.dto.FlowParams; +import org.dromara.warm.flow.core.handler.PermissionHandler; +import org.dromara.warm.flow.core.service.impl.TaskServiceImpl; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * 办理人权限处理器 + * + * @author AprilWind + */ +@RequiredArgsConstructor +@Component +@Slf4j +public class WorkflowPermissionHandler implements PermissionHandler { + + /** + * 审批前获取当前办理人,办理时会校验的该权限集合 + * 后续在{@link TaskServiceImpl#checkAuth(Task, FlowParams)} 中调用 + * 返回当前用户权限集合 + */ + @Override + public List permissions() { + LoginUser loginUser = LoginHelper.getLoginUser(); + if (ObjectUtil.isNull(loginUser)) { + return new ArrayList<>(); + } + // 使用一个流来构建权限列表 + return Stream.of( + // 角色权限前缀 + loginUser.getRoles().stream() + .map(role -> TaskAssigneeEnum.ROLE.getCode() + role.getRoleId()), + + // 岗位权限前缀 + Stream.ofNullable(loginUser.getPosts()) + .flatMap(Collection::stream) + .map(post -> TaskAssigneeEnum.POST.getCode() + post.getPostId()), + + // 用户和部门权限 + Stream.of(String.valueOf(loginUser.getUserId()), + TaskAssigneeEnum.DEPT.getCode() + loginUser.getDeptId() + ) + ) + .flatMap(stream -> stream) + .collect(Collectors.toList()); + } + + /** + * 获取当前办理人 + * + * @return 当前办理人 + */ + @Override + public String getHandler() { + return LoginHelper.getUserIdStr(); + } + +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/listener/WorkflowGlobalListener.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/listener/WorkflowGlobalListener.java new file mode 100644 index 000000000..29b8b7279 --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/listener/WorkflowGlobalListener.java @@ -0,0 +1,115 @@ +package org.dromara.workflow.listener; + +import cn.hutool.core.collection.CollUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.dromara.common.core.enums.BusinessStatusEnum; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.warm.flow.core.entity.Definition; +import org.dromara.warm.flow.core.entity.Instance; +import org.dromara.warm.flow.core.entity.Task; +import org.dromara.warm.flow.core.listener.GlobalListener; +import org.dromara.warm.flow.core.listener.ListenerVariable; +import org.dromara.warm.flow.orm.entity.FlowTask; +import org.dromara.workflow.handler.FlowProcessEventHandler; +import org.dromara.workflow.service.IFlwInstanceService; +import org.dromara.workflow.service.IFlwTaskService; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * 全局任务办理监听 + * + * @author may + */ +@Component +@Slf4j +@RequiredArgsConstructor +public class WorkflowGlobalListener implements GlobalListener { + + private final IFlwTaskService taskService; + private final IFlwInstanceService instanceService; + private final FlowProcessEventHandler flowProcessEventHandler; + + /** + * 创建监听器,任务创建时执行 + * + * @param listenerVariable 监听器变量 + */ + @Override + public void create(ListenerVariable listenerVariable) { + Instance instance = listenerVariable.getInstance(); + Definition definition = listenerVariable.getDefinition(); + String businessId = instance.getBusinessId(); + String flowStatus = instance.getFlowStatus(); + Task task = listenerVariable.getTask(); + if (task != null && BusinessStatusEnum.WAITING.getStatus().equals(flowStatus)) { + // 判断流程状态(发布审批中事件) + flowProcessEventHandler.processTaskHandler(definition.getFlowCode(), task.getNodeCode(), task.getId(), businessId); + } + } + + /** + * 开始监听器,任务开始办理时执行 + * + * @param listenerVariable 监听器变量 + */ + @Override + public void start(ListenerVariable listenerVariable) { + } + + /** + * 分派监听器,动态修改代办任务信息 + * + * @param listenerVariable 监听器变量 + */ + @Override + public void assignment(ListenerVariable listenerVariable) { + } + + /** + * 完成监听器,当前任务完成后执行 + * + * @param listenerVariable 监听器变量 + */ + @Override + public void finish(ListenerVariable listenerVariable) { + Instance instance = listenerVariable.getInstance(); + Definition definition = listenerVariable.getDefinition(); + String businessId = instance.getBusinessId(); + String flowStatus = instance.getFlowStatus(); + // 判断流程状态(发布:撤销,退回,作废,终止,已完成事件) + String status = determineFlowStatus(instance, flowStatus); + if (StringUtils.isNotBlank(status)) { + flowProcessEventHandler.processHandler(definition.getFlowCode(), businessId, status, false); + } + } + + /** + * 根据流程实例和当前流程状态确定最终状态 + * + * @param instance 流程实例 + * @param flowStatus 流程实例当前状态 + * @return 流程最终状态 + */ + private String determineFlowStatus(Instance instance, String flowStatus) { + if (StringUtils.isNotBlank(flowStatus) && BusinessStatusEnum.initialState(flowStatus)) { + log.info("流程实例当前状态: {}", flowStatus); + return flowStatus; + } else { + Long instanceId = instance.getId(); + List flowTasks = taskService.selectByInstId(instanceId); + if (CollUtil.isEmpty(flowTasks)) { + String status = BusinessStatusEnum.FINISH.getStatus(); + // 更新流程状态为已完成 + instanceService.updateStatus(instanceId, status); + log.info("流程已结束,状态更新为: {}", status); + return status; + } + log.warn("流程未结束,实例ID: {}", instanceId); + return null; + } + } + +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/ActHiProcinstMapper.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/ActHiProcinstMapper.java deleted file mode 100644 index a3a41c924..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/ActHiProcinstMapper.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.dromara.workflow.mapper; - -import com.baomidou.mybatisplus.annotation.InterceptorIgnore; -import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; -import org.dromara.workflow.domain.ActHiProcinst; - -/** - * 流程实例Mapper接口 - * - * @author may - * @date 2023-07-22 - */ -@InterceptorIgnore(tenantLine = "true") -public interface ActHiProcinstMapper extends BaseMapperPlus { - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/ActHiTaskinstMapper.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/ActHiTaskinstMapper.java deleted file mode 100644 index 63b394b6f..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/ActHiTaskinstMapper.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.dromara.workflow.mapper; - -import com.baomidou.mybatisplus.annotation.InterceptorIgnore; -import org.dromara.workflow.domain.ActHiTaskinst; -import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; - -/** - * 流程历史任务Mapper接口 - * - * @author may - * @date 2024-03-02 - */ -@InterceptorIgnore(tenantLine = "true") -public interface ActHiTaskinstMapper extends BaseMapperPlus { - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/ActTaskMapper.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/ActTaskMapper.java deleted file mode 100644 index 63c5ecb7b..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/ActTaskMapper.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.dromara.workflow.mapper; - -import com.baomidou.mybatisplus.annotation.InterceptorIgnore; -import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.baomidou.mybatisplus.core.toolkit.Constants; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import org.apache.ibatis.annotations.Param; -import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; -import org.dromara.workflow.domain.vo.TaskVo; - - -/** - * 任务信息Mapper接口 - * - * @author may - * @date 2024-03-02 - */ -@InterceptorIgnore(tenantLine = "true") -public interface ActTaskMapper extends BaseMapperPlus { - /** - * 获取待办信息 - * - * @param page 分页 - * @param queryWrapper 条件 - * @return 结果 - */ - Page getTaskWaitByPage(@Param("page") Page page, @Param(Constants.WRAPPER) Wrapper queryWrapper); - - /** - * 获取已办 - * - * @param page 分页 - * @param queryWrapper 条件 - * @return 结果 - */ - Page getTaskFinishByPage(@Param("page") Page page, @Param(Constants.WRAPPER) Wrapper queryWrapper); - - /** - * 查询当前用户的抄送 - * - * @param page 分页 - * @param queryWrapper 条件 - * @return 结果 - */ - Page getTaskCopyByPage(@Param("page") Page page, @Param(Constants.WRAPPER) QueryWrapper queryWrapper); -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/FlwCategoryMapper.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/FlwCategoryMapper.java new file mode 100644 index 000000000..d2c0b3a4d --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/FlwCategoryMapper.java @@ -0,0 +1,60 @@ +package org.dromara.workflow.mapper; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import org.dromara.common.mybatis.annotation.DataColumn; +import org.dromara.common.mybatis.annotation.DataPermission; +import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; +import org.dromara.common.mybatis.helper.DataBaseHelper; +import org.dromara.workflow.domain.FlowCategory; +import org.dromara.workflow.domain.vo.FlowCategoryVo; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * 流程分类Mapper接口 + * + * @author may + * @date 2023-06-27 + */ +public interface FlwCategoryMapper extends BaseMapperPlus { + + /** + * 统计指定流程分类ID的分类数量 + * + * @param categoryId 流程分类ID + * @return 该流程分类ID的分类数量 + */ + @DataPermission({ + @DataColumn(key = "deptName", value = "createDept") + }) + long countCategoryById(Long categoryId); + + /** + * 根据父流程分类ID查询其所有子流程分类的列表 + * + * @param parentId 父流程分类ID + * @return 包含子流程分类的列表 + */ + default List selectListByParentId(Long parentId) { + return this.selectList(new LambdaQueryWrapper() + .select(FlowCategory::getCategoryId) + .apply(DataBaseHelper.findInSet(parentId, "ancestors"))); + } + + /** + * 根据父流程分类ID查询包括父ID及其所有子流程分类ID的列表 + * + * @param parentId 父流程分类ID + * @return 包含父ID和子流程分类ID的列表 + */ + default List selectCategoryIdsByParentId(Long parentId) { + return Stream.concat( + this.selectListByParentId(parentId).stream() + .map(FlowCategory::getCategoryId), + Stream.of(parentId) + ).collect(Collectors.toList()); + } + +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/FlwInstanceMapper.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/FlwInstanceMapper.java new file mode 100644 index 000000000..92809c80f --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/FlwInstanceMapper.java @@ -0,0 +1,27 @@ +package org.dromara.workflow.mapper; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Constants; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.apache.ibatis.annotations.Param; +import org.dromara.workflow.domain.bo.FlowInstanceBo; +import org.dromara.workflow.domain.vo.FlowInstanceVo; + +/** + * 实例信息Mapper接口 + * + * @author may + * @date 2024-03-02 + */ +public interface FlwInstanceMapper { + + /** + * 流程实例信息 + * + * @param page 分页 + * @param queryWrapper 条件 + * @return 结果 + */ + Page selectInstanceList(@Param("page") Page page, @Param(Constants.WRAPPER) Wrapper queryWrapper); + +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/FlwTaskMapper.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/FlwTaskMapper.java new file mode 100644 index 000000000..fd86c82de --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/FlwTaskMapper.java @@ -0,0 +1,57 @@ +package org.dromara.workflow.mapper; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Constants; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.apache.ibatis.annotations.Param; +import org.dromara.workflow.domain.bo.FlowTaskBo; +import org.dromara.workflow.domain.vo.FlowHisTaskVo; +import org.dromara.workflow.domain.vo.FlowTaskVo; + +import java.util.List; + + +/** + * 任务信息Mapper接口 + * + * @author may + * @date 2024-03-02 + */ +public interface FlwTaskMapper { + + /** + * 获取待办信息 + * + * @param page 分页 + * @param queryWrapper 条件 + * @return 结果 + */ + Page getListRunTask(@Param("page") Page page, @Param(Constants.WRAPPER) Wrapper queryWrapper); + + /** + * 获取待办信息 + * + * @param queryWrapper 条件 + * @return 结果 + */ + List getListRunTask(@Param(Constants.WRAPPER) Wrapper queryWrapper); + + /** + * 获取已办 + * + * @param page 分页 + * @param queryWrapper 条件 + * @return 结果 + */ + Page getListFinishTask(@Param("page") Page page, @Param(Constants.WRAPPER) Wrapper queryWrapper); + + /** + * 查询当前用户的抄送 + * + * @param page 分页 + * @param queryWrapper 条件 + * @return 结果 + */ + Page getTaskCopyByPage(@Param("page") Page page, @Param(Constants.WRAPPER) QueryWrapper queryWrapper); +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/WfCategoryMapper.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/WfCategoryMapper.java deleted file mode 100644 index 98aea024e..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/WfCategoryMapper.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.dromara.workflow.mapper; - -import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; -import org.dromara.workflow.domain.WfCategory; -import org.dromara.workflow.domain.vo.WfCategoryVo; - -/** - * 流程分类Mapper接口 - * - * @author may - * @date 2023-06-27 - */ -public interface WfCategoryMapper extends BaseMapperPlus { - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/WfDefinitionConfigMapper.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/WfDefinitionConfigMapper.java deleted file mode 100644 index ee2088255..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/WfDefinitionConfigMapper.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.dromara.workflow.mapper; - -import org.dromara.workflow.domain.WfDefinitionConfig; -import org.dromara.workflow.domain.vo.WfDefinitionConfigVo; -import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; - -/** - * 流程定义配置Mapper接口 - * - * @author may - * @date 2024-03-18 - */ -public interface WfDefinitionConfigMapper extends BaseMapperPlus { - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/WfFormManageMapper.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/WfFormManageMapper.java deleted file mode 100644 index acf8111ad..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/WfFormManageMapper.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.dromara.workflow.mapper; - -import org.dromara.workflow.domain.WfFormManage; -import org.dromara.workflow.domain.vo.WfFormManageVo; -import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; - -/** - * 表单管理Mapper接口 - * - * @author may - * @date 2024-03-29 - */ -public interface WfFormManageMapper extends BaseMapperPlus { - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/WfNodeConfigMapper.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/WfNodeConfigMapper.java deleted file mode 100644 index d2aecacb9..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/WfNodeConfigMapper.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.dromara.workflow.mapper; - -import org.dromara.workflow.domain.WfNodeConfig; -import org.dromara.workflow.domain.vo.WfNodeConfigVo; -import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; - -/** - * 节点配置Mapper接口 - * - * @author may - * @date 2024-03-30 - */ -public interface WfNodeConfigMapper extends BaseMapperPlus { - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/WfTaskBackNodeMapper.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/WfTaskBackNodeMapper.java deleted file mode 100644 index 9b291feb4..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/WfTaskBackNodeMapper.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.dromara.workflow.mapper; - -import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; -import org.dromara.workflow.domain.WfTaskBackNode; - -/** - * 节点驳回记录Mapper接口 - * - * @author may - * @date 2024-03-13 - */ -public interface WfTaskBackNodeMapper extends BaseMapperPlus { -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActHiProcinstService.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActHiProcinstService.java deleted file mode 100644 index e802c6972..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActHiProcinstService.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.dromara.workflow.service; - - -import org.dromara.workflow.domain.ActHiProcinst; - -import java.util.List; - -/** - * 流程实例Service接口 - * - * @author may - * @date 2023-07-22 - */ -public interface IActHiProcinstService { - - /** - * 按照业务id查询 - * - * @param businessKeys 业务id - * @return 结果 - */ - List selectByBusinessKeyIn(List businessKeys); - - /** - * 按照业务id查询 - * - * @param businessKey 业务id - * @return 结果 - */ - ActHiProcinst selectByBusinessKey(String businessKey); -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActHiTaskinstService.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActHiTaskinstService.java deleted file mode 100644 index ad286e242..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActHiTaskinstService.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.dromara.workflow.service; - - -/** - * 流程历史任务Service接口 - * - * @author may - * @date 2024-03-02 - */ -public interface IActHiTaskinstService { -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActModelService.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActModelService.java deleted file mode 100644 index 4a6d17062..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActModelService.java +++ /dev/null @@ -1,83 +0,0 @@ -package org.dromara.workflow.service; - -import jakarta.servlet.http.HttpServletResponse; -import org.dromara.common.mybatis.core.page.PageQuery; -import org.dromara.common.mybatis.core.page.TableDataInfo; -import org.dromara.workflow.domain.bo.ModelBo; -import org.dromara.workflow.domain.vo.ModelVo; -import org.flowable.engine.repository.Model; - -import java.util.List; - - -/** - * 模型管理 服务层 - * - * @author may - */ -public interface IActModelService { - /** - * 分页查询模型 - * - * @param modelBo 模型参数 - * @param pageQuery 参数 - * @return 返回分页列表 - */ - TableDataInfo page(ModelBo modelBo, PageQuery pageQuery); - - /** - * 新增模型 - * - * @param modelBo 模型请求对象 - * @return 结果 - */ - boolean saveNewModel(ModelBo modelBo); - - /** - * 查询模型 - * - * @param modelId 模型id - * @return 模型数据 - */ - ModelVo getInfo(String modelId); - - /** - * 修改模型信息 - * - * @param modelBo 模型数据 - * @return 结果 - */ - boolean update(ModelBo modelBo); - - /** - * 编辑模型XML - * - * @param modelBo 模型数据 - * @return 结果 - */ - boolean editModelXml(ModelBo modelBo); - - /** - * 模型部署 - * - * @param id 模型id - * @return 结果 - */ - boolean modelDeploy(String id); - - /** - * 导出模型zip压缩包 - * - * @param modelIds 模型id - * @param response 响应 - */ - void exportZip(List modelIds, HttpServletResponse response); - - /** - * 复制模型 - * - * @param modelBo 模型数据 - * @return 结果 - */ - boolean copyModel(ModelBo modelBo); -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActProcessDefinitionService.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActProcessDefinitionService.java deleted file mode 100644 index 5d00e4199..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActProcessDefinitionService.java +++ /dev/null @@ -1,91 +0,0 @@ -package org.dromara.workflow.service; - -import org.dromara.common.mybatis.core.page.PageQuery; -import org.dromara.common.mybatis.core.page.TableDataInfo; -import org.dromara.workflow.domain.bo.ProcessDefinitionBo; -import org.dromara.workflow.domain.vo.ProcessDefinitionVo; -import org.springframework.web.multipart.MultipartFile; - -import java.util.List; - -/** - * 流程定义 服务层 - * - * @author may - */ -public interface IActProcessDefinitionService { - /** - * 分页查询 - * - * @param processDefinitionBo 参数 - * @param pageQuery 分页 - * @return 返回分页列表 - */ - TableDataInfo page(ProcessDefinitionBo processDefinitionBo, PageQuery pageQuery); - - /** - * 查询历史流程定义列表 - * - * @param key 流程定义key - * @return 结果 - */ - List getListByKey(String key); - - /** - * 查看流程定义图片 - * - * @param processDefinitionId 流程定义id - * @return 结果 - */ - String definitionImage(String processDefinitionId); - - /** - * 查看流程定义xml文件 - * - * @param processDefinitionId 流程定义id - * @return 结果 - */ - String definitionXml(String processDefinitionId); - - /** - * 删除流程定义 - * - * @param deploymentIds 部署id - * @param processDefinitionIds 流程定义id - * @return 结果 - */ - boolean deleteDeployment(List deploymentIds, List processDefinitionIds); - - /** - * 激活或者挂起流程定义 - * - * @param processDefinitionId 流程定义id - * @return 结果 - */ - boolean updateDefinitionState(String processDefinitionId); - - /** - * 迁移流程定义 - * - * @param currentProcessDefinitionId 当前流程定义id - * @param fromProcessDefinitionId 需要迁移到的流程定义id - * @return 结果 - */ - boolean migrationDefinition(String currentProcessDefinitionId, String fromProcessDefinitionId); - - /** - * 流程定义转换为模型 - * - * @param processDefinitionId 流程定义id - * @return 结果 - */ - boolean convertToModel(String processDefinitionId); - - /** - * 通过zip或xml部署流程定义 - * - * @param file 文件 - * @param categoryCode 分类 - */ - void deployByFile(MultipartFile file, String categoryCode); -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActProcessInstanceService.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActProcessInstanceService.java deleted file mode 100644 index ca3b6fb8e..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActProcessInstanceService.java +++ /dev/null @@ -1,110 +0,0 @@ -package org.dromara.workflow.service; - -import org.dromara.common.mybatis.core.page.PageQuery; -import org.dromara.common.mybatis.core.page.TableDataInfo; -import org.dromara.workflow.domain.bo.ProcessInstanceBo; -import org.dromara.workflow.domain.bo.ProcessInvalidBo; -import org.dromara.workflow.domain.bo.TaskUrgingBo; -import org.dromara.workflow.domain.vo.ActHistoryInfoVo; -import org.dromara.workflow.domain.vo.ProcessInstanceVo; - -import java.util.List; -import java.util.Map; - -/** - * 流程实例 服务层 - * - * @author may - */ -public interface IActProcessInstanceService { - /** - * 通过流程实例id获取历史流程图 - * - * @param businessKey 流程实例id - * @return 结果 - */ - String getHistoryImage(String businessKey); - - /** - * 通过业务id获取历史流程图运行中,历史等节点 - * - * @param businessKey 业务id - * @return 结果 - */ - Map getHistoryList(String businessKey); - - /** - * 分页查询正在运行的流程实例 - * - * @param processInstanceBo 参数 - * @param pageQuery 分页 - * @return 结果 - */ - TableDataInfo getPageByRunning(ProcessInstanceBo processInstanceBo, PageQuery pageQuery); - - /** - * 分页查询已结束的流程实例 - * - * @param processInstanceBo 参数 - * @param pageQuery 分页 - * @return 结果 - */ - TableDataInfo getPageByFinish(ProcessInstanceBo processInstanceBo, PageQuery pageQuery); - - /** - * 获取审批记录 - * - * @param businessKey 业务id - * @return 结果 - */ - List getHistoryRecord(String businessKey); - - /** - * 作废流程实例,不会删除历史记录(删除运行中的实例) - * - * @param processInvalidBo 参数 - * @return 结果 - */ - boolean deleteRunInstance(ProcessInvalidBo processInvalidBo); - - /** - * 运行中的实例 删除程实例,删除历史记录,删除业务与流程关联信息 - * - * @param businessKeys 业务id - * @return 结果 - */ - boolean deleteRunAndHisInstance(List businessKeys); - - /** - * 已完成的实例 删除程实例,删除历史记录,删除业务与流程关联信息 - * - * @param businessKeys 业务id - * @return 结果 - */ - boolean deleteFinishAndHisInstance(List businessKeys); - - /** - * 撤销流程申请 - * - * @param businessKey 业务id - * @return 结果 - */ - boolean cancelProcessApply(String businessKey); - - /** - * 分页查询当前登录人单据 - * - * @param processInstanceBo 参数 - * @param pageQuery 分页 - * @return 结果 - */ - TableDataInfo getPageByCurrent(ProcessInstanceBo processInstanceBo, PageQuery pageQuery); - - /** - * 任务催办(给当前任务办理人发送站内信,邮件,短信等) - * - * @param taskUrgingBo 任务催办 - * @return 结果 - */ - boolean taskUrging(TaskUrgingBo taskUrgingBo); -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActTaskService.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActTaskService.java deleted file mode 100644 index 8e9f76367..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IActTaskService.java +++ /dev/null @@ -1,161 +0,0 @@ -package org.dromara.workflow.service; - -import org.dromara.common.mybatis.core.page.PageQuery; -import org.dromara.common.mybatis.core.page.TableDataInfo; -import org.dromara.workflow.domain.bo.*; -import org.dromara.workflow.domain.vo.TaskVo; -import org.dromara.workflow.domain.vo.VariableVo; - -import java.util.List; -import java.util.Map; - -/** - * 任务 服务层 - * - * @author may - */ -public interface IActTaskService { - /** - * 启动任务 - * - * @param startProcessBo 启动流程参数 - * @return 结果 - */ - Map startWorkFlow(StartProcessBo startProcessBo); - - - /** - * 办理任务 - * - * @param completeTaskBo 办理任务参数 - * @return 结果 - */ - boolean completeTask(CompleteTaskBo completeTaskBo); - - /** - * 查询当前用户的待办任务 - * - * @param taskBo 参数 - * @param pageQuery 分页 - * @return 结果 - */ - TableDataInfo getPageByTaskWait(TaskBo taskBo, PageQuery pageQuery); - - /** - * 查询当前租户所有待办任务 - * - * @param taskBo 参数 - * @param pageQuery 分页 - * @return 结果 - */ - TableDataInfo getPageByAllTaskWait(TaskBo taskBo, PageQuery pageQuery); - - - /** - * 查询当前用户的已办任务 - * - * @param taskBo 参数 - * @param pageQuery 参数 - * @return 结果 - */ - TableDataInfo getPageByTaskFinish(TaskBo taskBo, PageQuery pageQuery); - - /** - * 查询当前用户的抄送 - * - * @param taskBo 参数 - * @param pageQuery 参数 - * @return 结果 - */ - TableDataInfo getPageByTaskCopy(TaskBo taskBo, PageQuery pageQuery); - - /** - * 查询当前租户所有已办任务 - * - * @param taskBo 参数 - * @param pageQuery 参数 - * @return 结果 - */ - TableDataInfo getPageByAllTaskFinish(TaskBo taskBo, PageQuery pageQuery); - - /** - * 委派任务 - * - * @param delegateBo 参数 - * @return 结果 - */ - boolean delegateTask(DelegateBo delegateBo); - - /** - * 终止任务 - * - * @param terminationBo 参数 - * @return 结果 - */ - boolean terminationTask(TerminationBo terminationBo); - - /** - * 转办任务 - * - * @param transmitBo 参数 - * @return 结果 - */ - boolean transferTask(TransmitBo transmitBo); - - /** - * 会签任务加签 - * - * @param addMultiBo 参数 - * @return 结果 - */ - boolean addMultiInstanceExecution(AddMultiBo addMultiBo); - - /** - * 会签任务减签 - * - * @param deleteMultiBo 参数 - * @return 结果 - */ - boolean deleteMultiInstanceExecution(DeleteMultiBo deleteMultiBo); - - /** - * 驳回审批 - * - * @param backProcessBo 参数 - * @return 流程实例id - */ - String backProcess(BackProcessBo backProcessBo); - - /** - * 修改任务办理人 - * - * @param taskIds 任务id - * @param userId 办理人id - * @return 结果 - */ - boolean updateAssignee(String[] taskIds, String userId); - - /** - * 查询流程变量 - * - * @param taskId 任务id - * @return 结果 - */ - List getInstanceVariable(String taskId); - - /** - * 查询工作流任务用户选择加签人员 - * - * @param taskId 任务id - * @return 结果 - */ - String getTaskUserIdsByAddMultiInstance(String taskId); - - /** - * 查询工作流选择减签人员 - * - * @param taskId 任务id - * @return 结果 - */ - List getListByDeleteMultiInstance(String taskId); -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwCategoryService.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwCategoryService.java new file mode 100644 index 000000000..43bc175fd --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwCategoryService.java @@ -0,0 +1,102 @@ +package org.dromara.workflow.service; + +import cn.hutool.core.lang.tree.Tree; +import org.dromara.workflow.domain.bo.FlowCategoryBo; +import org.dromara.workflow.domain.vo.FlowCategoryVo; + +import java.util.List; + +/** + * 流程分类Service接口 + * + * @author may + */ +public interface IFlwCategoryService { + + /** + * 查询流程分类 + * + * @param categoryId 主键 + * @return 流程分类 + */ + FlowCategoryVo queryById(Long categoryId); + + /** + * 根据流程分类ID查询流程分类名称 + * + * @param categoryId 流程分类ID + * @return 流程分类名称 + */ + String selectCategoryNameById(String categoryId); + + /** + * 查询符合条件的流程分类列表 + * + * @param bo 查询条件 + * @return 流程分类列表 + */ + List queryList(FlowCategoryBo bo); + + /** + * 查询流程分类树结构信息 + * + * @param category 流程分类信息 + * @return 流程分类树信息集合 + */ + List> selectCategoryTreeList(FlowCategoryBo category); + + /** + * 校验流程分类是否有数据权限 + * + * @param categoryId 流程分类ID + */ + void checkCategoryDataScope(Long categoryId); + + /** + * 校验流程分类名称是否唯一 + * + * @param category 流程分类信息 + * @return 结果 + */ + boolean checkCategoryNameUnique(FlowCategoryBo category); + + /** + * 查询流程分类是否存在流程定义 + * + * @param categoryId 流程分类ID + * @return 结果 true 存在 false 不存在 + */ + boolean checkCategoryExistDefinition(Long categoryId); + + /** + * 是否存在流程分类子节点 + * + * @param categoryId 流程分类ID + * @return 结果 + */ + boolean hasChildByCategoryId(Long categoryId); + + /** + * 新增流程分类 + * + * @param bo 流程分类 + * @return 是否新增成功 + */ + int insertByBo(FlowCategoryBo bo); + + /** + * 修改流程分类 + * + * @param bo 流程分类 + * @return 是否修改成功 + */ + int updateByBo(FlowCategoryBo bo); + + /** + * 删除流程分类信息 + * + * @param categoryId 主键 + * @return 是否删除成功 + */ + int deleteWithValidById(Long categoryId); +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwDefinitionService.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwDefinitionService.java new file mode 100644 index 000000000..6b5ca594a --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwDefinitionService.java @@ -0,0 +1,79 @@ +package org.dromara.workflow.service; + +import jakarta.servlet.http.HttpServletResponse; +import org.dromara.common.mybatis.core.page.PageQuery; +import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.warm.flow.orm.entity.FlowDefinition; +import org.dromara.workflow.domain.vo.FlowDefinitionVo; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.util.List; + +/** + * 流程定义 服务层 + * + * @author may + */ +public interface IFlwDefinitionService { + + /** + * 查询流程定义列表 + * + * @param flowDefinition 参数 + * @param pageQuery 分页 + * @return 返回分页列表 + */ + TableDataInfo queryList(FlowDefinition flowDefinition, PageQuery pageQuery); + + /** + * 查询未发布的流程定义列表 + * + * @param flowDefinition 参数 + * @param pageQuery 分页 + * @return 返回分页列表 + */ + TableDataInfo unPublishList(FlowDefinition flowDefinition, PageQuery pageQuery); + + + /** + * 发布流程定义 + * + * @param id 流程定义id + * @return 结果 + */ + boolean publish(Long id); + + /** + * 导出流程定义 + * + * @param id 流程定义id + * @param response 响应 + * @throws IOException 异常 + */ + void exportDef(Long id, HttpServletResponse response) throws IOException; + + /** + * 导入流程定义 + * + * @param file 文件 + * @param category 分类 + * @return 结果 + */ + boolean importXml(MultipartFile file, String category); + + /** + * 删除流程定义 + * + * @param ids 流程定义id + * @return 结果 + */ + boolean removeDef(List ids); + + /** + * 新增租户流程定义 + * + * @param tenantId 租户id + */ + void syncDef(String tenantId); +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwInstanceService.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwInstanceService.java new file mode 100644 index 000000000..97d84a280 --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwInstanceService.java @@ -0,0 +1,159 @@ +package org.dromara.workflow.service; + +import org.dromara.common.mybatis.core.page.PageQuery; +import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.warm.flow.orm.entity.FlowInstance; +import org.dromara.workflow.domain.bo.FlowCancelBo; +import org.dromara.workflow.domain.bo.FlowInstanceBo; +import org.dromara.workflow.domain.bo.FlowInvalidBo; +import org.dromara.workflow.domain.vo.FlowInstanceVo; + +import java.util.List; +import java.util.Map; + +/** + * 流程实例 服务层 + * + * @author may + */ +public interface IFlwInstanceService { + + /** + * 分页查询正在运行的流程实例 + * + * @param flowInstanceBo 流程实例 + * @param pageQuery 分页 + * @return 结果 + */ + TableDataInfo selectRunningInstanceList(FlowInstanceBo flowInstanceBo, PageQuery pageQuery); + + /** + * 分页查询已结束的流程实例 + * + * @param flowInstanceBo 流程实例 + * @param pageQuery 分页 + * @return 结果 + */ + TableDataInfo selectFinishInstanceList(FlowInstanceBo flowInstanceBo, PageQuery pageQuery); + + /** + * 根据业务id查询流程实例详细信息 + * + * @param businessId 业务id + * @return 结果 + */ + FlowInstanceVo queryByBusinessId(Long businessId); + + /** + * 按照业务id查询流程实例 + * + * @param businessId 业务id + * @return 结果 + */ + FlowInstance selectInstByBusinessId(String businessId); + + /** + * 按照实例id查询流程实例 + * + * @param instanceId 实例id + * @return 结果 + */ + FlowInstance selectInstById(Long instanceId); + + /** + * 按照实例id查询流程实例 + * + * @param instanceIds 实例id + * @return 结果 + */ + List selectInstListByIdList(List instanceIds); + + /** + * 按照业务id删除流程实例 + * + * @param businessIds 业务id + * @return 结果 + */ + boolean deleteByBusinessIds(List businessIds); + + /** + * 按照实例id删除流程实例 + * + * @param instanceIds 实例id + * @return 结果 + */ + boolean deleteByInstanceIds(List instanceIds); + + /** + * 撤销流程 + * + * @param bo 参数 + * @return 结果 + */ + boolean cancelProcessApply(FlowCancelBo bo); + + /** + * 获取当前登陆人发起的流程实例 + * + * @param instanceBo 流程实例 + * @param pageQuery 分页 + * @return 结果 + */ + TableDataInfo selectCurrentInstanceList(FlowInstanceBo instanceBo, PageQuery pageQuery); + + /** + * 获取流程图,流程记录 + * + * @param businessId 业务id + * @return 结果 + */ + Map flowImage(String businessId); + + /** + * 按照实例id更新状态 + * + * @param instanceId 实例id + * @param status 状态 + */ + void updateStatus(Long instanceId, String status); + + /** + * 获取流程变量 + * + * @param instanceId 实例id + * @return 结果 + */ + Map instanceVariable(String instanceId); + + /** + * 设置流程变量 + * + * @param instanceId 实例id + * @param variable 流程变量 + */ + void setVariable(Long instanceId, Map variable); + + /** + * 按任务id查询实例 + * + * @param taskId 任务id + * @return 结果 + */ + FlowInstance selectByTaskId(Long taskId); + + /** + * 按任务id查询实例 + * + * @param taskIdList 任务id + * @return 结果 + */ + List selectByTaskIdList(List taskIdList); + + /** + * 作废流程 + * + * @param bo 流程实例 + * @return 结果 + */ + boolean processInvalid(FlowInvalidBo bo); +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwTaskAssigneeService.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwTaskAssigneeService.java new file mode 100644 index 000000000..116cb74f3 --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwTaskAssigneeService.java @@ -0,0 +1,22 @@ +package org.dromara.workflow.service; + +import org.dromara.common.core.domain.dto.UserDTO; + +import java.util.List; + +/** + * 流程设计器-获取办理人 + * + * @author AprilWind + */ +public interface IFlwTaskAssigneeService { + + /** + * 根据存储标识符(storageId)解析分配类型和ID,并获取对应的用户列表 + * + * @param storageId 包含分配类型和ID的字符串(例如 "user:123" 或 "role:456") + * @return 与分配类型和ID匹配的用户列表,如果格式无效则返回空列表 + */ + List fetchUsersByStorageId(String storageId); + +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwTaskService.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwTaskService.java new file mode 100644 index 000000000..80bfa948c --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwTaskService.java @@ -0,0 +1,190 @@ +package org.dromara.workflow.service; + +import org.dromara.common.core.domain.dto.UserDTO; +import org.dromara.common.mybatis.core.page.PageQuery; +import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.warm.flow.core.entity.Node; +import org.dromara.warm.flow.orm.entity.FlowHisTask; +import org.dromara.warm.flow.orm.entity.FlowTask; +import org.dromara.workflow.domain.bo.*; +import org.dromara.workflow.domain.vo.FlowHisTaskVo; +import org.dromara.workflow.domain.vo.FlowTaskVo; + +import java.util.List; +import java.util.Map; + +/** + * 任务 服务层 + * + * @author may + */ +public interface IFlwTaskService { + + /** + * 启动任务 + * + * @param startProcessBo 启动流程参数 + * @return 结果 + */ + Map startWorkFlow(StartProcessBo startProcessBo); + + /** + * 办理任务 + * + * @param completeTaskBo 办理任务参数 + * @return 结果 + */ + boolean completeTask(CompleteTaskBo completeTaskBo); + + /** + * 查询当前用户的待办任务 + * + * @param flowTaskBo 参数 + * @param pageQuery 分页 + * @return 结果 + */ + TableDataInfo pageByTaskWait(FlowTaskBo flowTaskBo, PageQuery pageQuery); + + /** + * 查询当前租户所有待办任务 + * + * @param flowTaskBo 参数 + * @param pageQuery 分页 + * @return 结果 + */ + TableDataInfo pageByTaskFinish(FlowTaskBo flowTaskBo, PageQuery pageQuery); + + /** + * 查询待办任务 + * + * @param flowTaskBo 参数 + * @param pageQuery 分页 + * @return 结果 + */ + TableDataInfo pageByAllTaskWait(FlowTaskBo flowTaskBo, PageQuery pageQuery); + + /** + * 查询已办任务 + * + * @param flowTaskBo 参数 + * @param pageQuery 分页 + * @return 结果 + */ + TableDataInfo pageByAllTaskFinish(FlowTaskBo flowTaskBo, PageQuery pageQuery); + + /** + * 查询当前用户的抄送 + * + * @param flowTaskBo 参数 + * @param pageQuery 分页 + * @return 结果 + */ + TableDataInfo pageByTaskCopy(FlowTaskBo flowTaskBo, PageQuery pageQuery); + + /** + * 修改任务办理人 + * + * @param taskIdList 任务id + * @param userId 用户id + * @return 结果 + */ + boolean updateAssignee(List taskIdList, String userId); + + /** + * 驳回审批 + * + * @param bo 参数 + * @return 结果 + */ + boolean backProcess(BackProcessBo bo); + + /** + * 获取可驳回的前置节点 + * + * @param definitionId 流程定义id + * @param nowNodeCode 当前节点 + * @return 结果 + */ + List getBackTaskNode(Long definitionId, String nowNodeCode); + + /** + * 终止任务 + * + * @param bo 参数 + * @return 结果 + */ + boolean terminationTask(FlowTerminationBo bo); + + /** + * 按照任务id查询任务 + * + * @param taskIdList 任务id + * @return 结果 + */ + List selectByIdList(List taskIdList); + + /** + * 按照任务id查询任务 + * + * @param taskId 任务id + * @return 结果 + */ + FlowTaskVo selectById(Long taskId); + + /** + * 按照任务id查询任务 + * + * @param taskIdList 任务id + * @return 结果 + */ + List selectHisTaskByIdList(List taskIdList); + + /** + * 按照任务id查询任务 + * + * @param taskId 任务id + * @return 结果 + */ + FlowHisTask selectHisTaskById(Long taskId); + + /** + * 按照实例id查询任务 + * + * @param instanceIdList 流程实例id + * @return 结果 + */ + List selectByInstIdList(List instanceIdList); + + /** + * 按照实例id查询任务 + * + * @param instanceId 流程实例id + * @return 结果 + */ + List selectByInstId(Long instanceId); + + /** + * 任务操作 + * + * @param bo 参数 + * @param taskOperation 操作类型,委派 delegateTask、转办 transferTask、加签 addSignature、减签 reductionSignature + * @return 结果 + */ + boolean taskOperation(TaskOperationBo bo, String taskOperation); + + /** + * 获取任务所有办理人 + * + * @param taskIdList 任务id + * @return 结果 + */ + Map> currentTaskAllUser(List taskIdList); + + /** + * 获取当前任务的所有办理人 + * + * @param taskId 任务id + * @return 结果 + */ + List currentTaskAllUser(Long taskId); +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/ITestLeaveService.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/ITestLeaveService.java index 943c919ae..67b50baf3 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/ITestLeaveService.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/ITestLeaveService.java @@ -5,7 +5,6 @@ import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.workflow.domain.bo.TestLeaveBo; import org.dromara.workflow.domain.vo.TestLeaveVo; -import java.util.Collection; import java.util.List; /** @@ -44,5 +43,5 @@ public interface ITestLeaveService { /** * 校验并批量删除请假信息 */ - Boolean deleteWithValidByIds(Collection ids); + Boolean deleteWithValidByIds(List ids); } diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IWfCategoryService.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IWfCategoryService.java deleted file mode 100644 index acf0aa2bc..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IWfCategoryService.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.dromara.workflow.service; - -import org.dromara.workflow.domain.WfCategory; -import org.dromara.workflow.domain.bo.WfCategoryBo; -import org.dromara.workflow.domain.vo.WfCategoryVo; - -import java.util.Collection; -import java.util.List; - -/** - * 流程分类Service接口 - * - * @author may - * @date 2023-06-28 - */ -public interface IWfCategoryService { - - /** - * 查询流程分类 - */ - WfCategoryVo queryById(Long id); - - - /** - * 查询流程分类列表 - */ - List queryList(WfCategoryBo bo); - - /** - * 新增流程分类 - */ - Boolean insertByBo(WfCategoryBo bo); - - /** - * 修改流程分类 - */ - Boolean updateByBo(WfCategoryBo bo); - - /** - * 校验并批量删除流程分类信息 - */ - Boolean deleteWithValidByIds(Collection ids, Boolean isValid); - - /** - * 按照类别编码查询 - * - * @param categoryCode 分类比吗 - * @return 结果 - */ - WfCategory queryByCategoryCode(String categoryCode); -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IWfDefinitionConfigService.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IWfDefinitionConfigService.java deleted file mode 100644 index fe5cf7ad3..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IWfDefinitionConfigService.java +++ /dev/null @@ -1,83 +0,0 @@ -package org.dromara.workflow.service; - -import org.dromara.workflow.domain.vo.WfDefinitionConfigVo; -import org.dromara.workflow.domain.bo.WfDefinitionConfigBo; - -import java.util.Collection; -import java.util.List; - -/** - * 流程定义配置Service接口 - * - * @author may - * @date 2024-03-18 - */ -public interface IWfDefinitionConfigService { - - /** - * 查询流程定义配置 - * - * @param definitionId 流程定义id - * @return 结果 - */ - WfDefinitionConfigVo getByDefId(String definitionId); - - /** - * 查询流程定义配置 - * - * @param tableName 表名 - * @return 结果 - */ - WfDefinitionConfigVo getByTableNameLastVersion(String tableName); - - /** - * 查询流程定义配置 - * - * @param definitionId 流程定义id - * @param tableName 表名 - * @return 结果 - */ - WfDefinitionConfigVo getByDefIdAndTableName(String definitionId, String tableName); - - /** - * 查询流程定义配置排除当前查询的流程定义 - * - * @param definitionId 流程定义id - * @param tableName 表名 - * @return 结果 - */ - List getByTableNameNotDefId(String tableName, String definitionId); - - /** - * 查询流程定义配置列表 - * - * @param definitionIds 流程定义id - * @return 结果 - */ - List queryList(List definitionIds); - - - /** - * 新增流程定义配置 - * - * @param bo 参数 - * @return 结果 - */ - Boolean saveOrUpdate(WfDefinitionConfigBo bo); - - /** - * 删除 - * - * @param ids id - * @return 结果 - */ - Boolean deleteByIds(Collection ids); - - /** - * 按照流程定义id删除 - * - * @param ids 流程定义id - * @return 结果 - */ - Boolean deleteByDefIds(Collection ids); -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IWfFormManageService.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IWfFormManageService.java deleted file mode 100644 index 2ca2264b0..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IWfFormManageService.java +++ /dev/null @@ -1,81 +0,0 @@ -package org.dromara.workflow.service; - -import org.dromara.workflow.domain.vo.WfFormManageVo; -import org.dromara.workflow.domain.bo.WfFormManageBo; -import org.dromara.common.mybatis.core.page.TableDataInfo; -import org.dromara.common.mybatis.core.page.PageQuery; - -import java.util.Collection; -import java.util.List; - -/** - * 表单管理Service接口 - * - * @author may - * @date 2024-03-29 - */ -public interface IWfFormManageService { - - /** - * 查询表单管理 - * - * @param id 主键 - * @return 结果 - */ - WfFormManageVo queryById(Long id); - - /** - * 查询表单管理 - * - * @param ids 主键 - * @return 结果 - */ - List queryByIds(List ids); - - /** - * 查询表单管理列表 - * - * @param bo 参数 - * @param pageQuery 分页 - * @return 结果 - */ - TableDataInfo queryPageList(WfFormManageBo bo, PageQuery pageQuery); - - /** - * 查询表单管理列表 - * - * @return 结果 - */ - List selectList(); - /** - * 查询表单管理列表 - * - * @param bo 参数 - * @return 结果 - */ - List queryList(WfFormManageBo bo); - - /** - * 新增表单管理 - * - * @param bo 参数 - * @return 结果 - */ - Boolean insertByBo(WfFormManageBo bo); - - /** - * 修改表单管理 - * - * @param bo 参数 - * @return 结果 - */ - Boolean updateByBo(WfFormManageBo bo); - - /** - * 批量删除表单管理信息 - * - * @param ids 主键 - * @return 结果 - */ - Boolean deleteByIds(Collection ids); -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IWfNodeConfigService.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IWfNodeConfigService.java deleted file mode 100644 index 5e64d64a5..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IWfNodeConfigService.java +++ /dev/null @@ -1,56 +0,0 @@ -package org.dromara.workflow.service; - -import org.dromara.workflow.domain.WfNodeConfig; -import org.dromara.workflow.domain.vo.WfNodeConfigVo; - -import java.util.Collection; -import java.util.List; - -/** - * 节点配置Service接口 - * - * @author may - * @date 2024-03-30 - */ -public interface IWfNodeConfigService { - - /** - * 查询节点配置 - * - * @param id 主键 - * @return 结果 - */ - WfNodeConfigVo queryById(Long id); - - /** - * 保存节点配置 - * - * @param list 参数 - * @return 结果 - */ - Boolean saveOrUpdate(List list); - - /** - * 批量删除节点配置信息 - * - * @param ids 主键 - * @return 结果 - */ - Boolean deleteByIds(Collection ids); - - /** - * 按照流程定义id删除 - * - * @param ids 流程定义id - * @return 结果 - */ - Boolean deleteByDefIds(Collection ids); - - /** - * 按照流程定义id查询 - * - * @param ids 流程定义id - * @return 结果 - */ - List selectByDefIds(Collection ids); -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IWfTaskBackNodeService.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IWfTaskBackNodeService.java deleted file mode 100644 index 97f940671..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IWfTaskBackNodeService.java +++ /dev/null @@ -1,65 +0,0 @@ -package org.dromara.workflow.service; - - -import org.dromara.workflow.domain.WfTaskBackNode; -import org.flowable.task.api.Task; - -import java.util.List; - -/** - * 节点驳回记录Service接口 - * - * @author may - * @date 2024-03-13 - */ -public interface IWfTaskBackNodeService { - - /** - * 记录审批节点 - * - * @param task 任务 - */ - void recordExecuteNode(Task task); - - /** - * 按流程实例id查询 - * - * @param processInstanceId 流程实例id - * @return 结果 - */ - List getListByInstanceId(String processInstanceId); - - /** - * 按照流程实例id,节点id查询 - * - * @param processInstanceId 流程实例id - * @param nodeId 节点id - * @return 结果 - */ - WfTaskBackNode getListByInstanceIdAndNodeId(String processInstanceId, String nodeId); - - /** - * 删除驳回后的节点 - * - * @param processInstanceId 流程实例id - * @param targetActivityId 节点id - * @return 结果 - */ - boolean deleteBackTaskNode(String processInstanceId, String targetActivityId); - - /** - * 按流程实例id删除 - * - * @param processInstanceId 流程实例id - * @return 结果 - */ - boolean deleteByInstanceId(String processInstanceId); - - /** - * 按流程实例id删除 - * - * @param processInstanceIds 流程实例id - * @return 结果 - */ - boolean deleteByInstanceIds(List processInstanceIds); -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActHiProcinstServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActHiProcinstServiceImpl.java deleted file mode 100644 index 06d607b4f..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActHiProcinstServiceImpl.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.dromara.workflow.service.impl; - - -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import lombok.RequiredArgsConstructor; -import org.dromara.common.tenant.helper.TenantHelper; -import org.dromara.workflow.domain.ActHiProcinst; -import org.dromara.workflow.mapper.ActHiProcinstMapper; -import org.dromara.workflow.service.IActHiProcinstService; -import org.springframework.stereotype.Service; - -import java.util.List; - - -/** - * 流程实例Service业务层处理 - * - * @author may - * @date 2023-07-22 - */ -@RequiredArgsConstructor -@Service -public class ActHiProcinstServiceImpl implements IActHiProcinstService { - - private final ActHiProcinstMapper baseMapper; - - /** - * 按照业务id查询 - * - * @param businessKeys 业务id - */ - @Override - public List selectByBusinessKeyIn(List businessKeys) { - return baseMapper.selectList(new LambdaQueryWrapper() - .in(ActHiProcinst::getBusinessKey, businessKeys) - .eq(TenantHelper.isEnable(), ActHiProcinst::getTenantId, TenantHelper.getTenantId())); - } - - /** - * 按照业务id查询 - * - * @param businessKey 业务id - */ - @Override - public ActHiProcinst selectByBusinessKey(String businessKey) { - return baseMapper.selectOne(new LambdaQueryWrapper() - .eq(ActHiProcinst::getBusinessKey, businessKey) - .eq(TenantHelper.isEnable(), ActHiProcinst::getTenantId, TenantHelper.getTenantId())); - - } -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActHiTaskinstServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActHiTaskinstServiceImpl.java deleted file mode 100644 index 5548f22f5..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActHiTaskinstServiceImpl.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.dromara.workflow.service.impl; - -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.dromara.workflow.service.IActHiTaskinstService; - - -/** - * 流程历史任务Service业务层处理 - * - * @author may - * @date 2024-03-02 - */ -@RequiredArgsConstructor -@Service -public class ActHiTaskinstServiceImpl implements IActHiTaskinstService { - -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActModelServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActModelServiceImpl.java deleted file mode 100644 index 217538e44..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActModelServiceImpl.java +++ /dev/null @@ -1,431 +0,0 @@ -package org.dromara.workflow.service.impl; - -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.lang.Validator; -import cn.hutool.core.util.ArrayUtil; -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.core.util.StrUtil; -import cn.hutool.core.util.ZipUtil; -import cn.hutool.json.JSONUtil; -import com.alibaba.excel.util.StringUtils; -import jakarta.servlet.http.HttpServletResponse; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.apache.batik.transcoder.TranscoderInput; -import org.apache.batik.transcoder.TranscoderOutput; -import org.apache.batik.transcoder.image.PNGTranscoder; -import org.dromara.common.core.exception.ServiceException; -import org.dromara.common.mybatis.core.page.PageQuery; -import org.dromara.common.mybatis.core.page.TableDataInfo; -import org.dromara.common.tenant.helper.TenantHelper; -import org.dromara.workflow.common.constant.FlowConstant; -import org.dromara.workflow.domain.WfNodeConfig; -import org.dromara.workflow.domain.bo.ModelBo; -import org.dromara.workflow.domain.bo.WfDefinitionConfigBo; -import org.dromara.workflow.domain.vo.ModelVo; -import org.dromara.workflow.domain.vo.WfDefinitionConfigVo; -import org.dromara.workflow.service.IActModelService; -import org.dromara.workflow.service.IWfDefinitionConfigService; -import org.dromara.workflow.service.IWfNodeConfigService; -import org.dromara.workflow.utils.ModelUtils; -import org.dromara.workflow.utils.QueryUtils; -import org.flowable.bpmn.converter.BpmnXMLConverter; -import org.flowable.bpmn.model.BpmnModel; -import org.flowable.bpmn.model.Process; -import org.flowable.bpmn.model.UserTask; -import org.flowable.engine.RepositoryService; -import org.flowable.engine.repository.Deployment; -import org.flowable.engine.repository.Model; -import org.flowable.engine.repository.ModelQuery; -import org.flowable.engine.repository.ProcessDefinition; -import org.flowable.validation.ValidationError; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.URLEncoder; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.stream.Collectors; -import java.util.zip.ZipEntry; -import java.util.zip.ZipOutputStream; - -/** - * 模型管理 服务层实现 - * - * @author may - */ -@Slf4j -@RequiredArgsConstructor -@Service -public class ActModelServiceImpl implements IActModelService { - - @Autowired(required = false) - private RepositoryService repositoryService; - private final IWfNodeConfigService wfNodeConfigService; - private final IWfDefinitionConfigService wfDefinitionConfigService; - - /** - * 分页查询模型 - * - * @param modelBo 模型参数 - * @return 返回分页列表 - */ - @Override - public TableDataInfo page(ModelBo modelBo, PageQuery pageQuery) { - ModelQuery query = QueryUtils.modelQuery(); - if (StringUtils.isNotBlank(modelBo.getName())) { - query.modelNameLike("%" + modelBo.getName() + "%"); - } - if (StringUtils.isNotBlank(modelBo.getKey())) { - query.modelKey(modelBo.getKey()); - } - if (StringUtils.isNotBlank(modelBo.getCategoryCode())) { - query.modelCategory(modelBo.getCategoryCode()); - } - query.orderByLastUpdateTime().desc(); - // 创建时间降序排列 - query.orderByCreateTime().desc(); - // 分页查询 - List modelList = query.listPage(pageQuery.getFirstNum(), pageQuery.getPageSize()); - // 总记录数 - long total = query.count(); - TableDataInfo build = TableDataInfo.build(); - build.setRows(modelList); - build.setTotal(total); - return build; - } - - /** - * 新增模型 - * - * @param modelBo 模型请求对象 - * @return 结果 - */ - @Override - @Transactional(rollbackFor = Exception.class) - public boolean saveNewModel(ModelBo modelBo) { - try { - int version = 0; - String key = modelBo.getKey(); - String name = modelBo.getName(); - String description = modelBo.getDescription(); - String categoryCode = modelBo.getCategoryCode(); - String xml = modelBo.getXml(); - Model checkModel = QueryUtils.modelQuery().modelKey(key).singleResult(); - if (ObjectUtil.isNotNull(checkModel)) { - throw new ServiceException("模型key已存在!"); - } - //初始空的模型 - Model model = repositoryService.newModel(); - model.setKey(key); - model.setName(name); - model.setVersion(version); - model.setCategory(categoryCode); - model.setMetaInfo(description); - model.setTenantId(TenantHelper.getTenantId()); - //保存初始化的模型基本信息数据 - repositoryService.saveModel(model); - repositoryService.addModelEditorSource(model.getId(), StrUtil.utf8Bytes(xml)); - return true; - } catch (Exception e) { - log.error(e.getMessage(), e); - throw new ServiceException(e.getMessage()); - } - } - - /** - * 查询模型 - * - * @param id 模型id - * @return 模型数据 - */ - @Override - public ModelVo getInfo(String id) { - ModelVo modelVo = new ModelVo(); - Model model = repositoryService.getModel(id); - if (model != null) { - try { - byte[] modelEditorSource = repositoryService.getModelEditorSource(model.getId()); - modelVo.setXml(StrUtil.utf8Str(modelEditorSource)); - modelVo.setId(model.getId()); - modelVo.setKey(model.getKey()); - modelVo.setName(model.getName()); - modelVo.setCategoryCode(model.getCategory()); - modelVo.setDescription(model.getMetaInfo()); - return modelVo; - } catch (Exception e) { - log.error(e.getMessage(), e); - throw new ServiceException(e.getMessage()); - } - } - return modelVo; - } - - /** - * 修改模型信息 - * - * @param modelBo 模型数据 - * @return 结果 - */ - @Override - public boolean update(ModelBo modelBo) { - try { - Model model = repositoryService.getModel(modelBo.getId()); - List list = QueryUtils.modelQuery().modelKey(modelBo.getKey()).list(); - list.stream().filter(e -> !e.getId().equals(model.getId())).findFirst().ifPresent(e -> { - throw new ServiceException("模型KEY已存在!"); - }); - model.setCategory(modelBo.getCategoryCode()); - model.setMetaInfo(modelBo.getDescription()); - repositoryService.saveModel(model); - } catch (Exception e) { - log.error(e.getMessage(), e); - throw new ServiceException(e.getMessage()); - } - return true; - } - - /** - * 编辑模型XML - * - * @param modelBo 模型数据 - * @return 结果 - */ - @Override - @Transactional(rollbackFor = Exception.class) - public boolean editModelXml(ModelBo modelBo) { - try { - String xml = modelBo.getXml(); - String svg = modelBo.getSvg(); - String modelId = modelBo.getId(); - String key = modelBo.getKey(); - String name = modelBo.getName(); - BpmnModel bpmnModel = ModelUtils.xmlToBpmnModel(xml); - ModelUtils.checkBpmnModel(bpmnModel); - Model model = repositoryService.getModel(modelId); - List list = QueryUtils.modelQuery().modelKey(key).list(); - list.stream().filter(e -> !e.getId().equals(model.getId())).findFirst().ifPresent(e -> { - throw new ServiceException("模型KEY已存在!"); - }); - // 校验key命名规范 - if (!Validator.isMatchRegex(FlowConstant.MODEL_KEY_PATTERN, key)) { - throw new ServiceException("模型标识KEY只能字符或者下划线开头!"); - } - model.setKey(key); - model.setName(name); - model.setVersion(model.getVersion() + 1); - repositoryService.saveModel(model); - repositoryService.addModelEditorSource(model.getId(), StrUtil.utf8Bytes(xml)); - // 转换图片 - InputStream svgStream = new ByteArrayInputStream(StrUtil.utf8Bytes(svg)); - TranscoderInput input = new TranscoderInput(svgStream); - - PNGTranscoder transcoder = new PNGTranscoder(); - ByteArrayOutputStream outStream = new ByteArrayOutputStream(); - TranscoderOutput output = new TranscoderOutput(outStream); - - transcoder.transcode(input, output); - final byte[] result = outStream.toByteArray(); - repositoryService.addModelEditorSourceExtra(model.getId(), result); - return true; - } catch (Exception e) { - log.error(e.getMessage(), e); - throw new ServiceException(e.getMessage()); - } - } - - /** - * 模型部署 - * - * @param id 模型id - * @return 结果 - */ - @Override - @Transactional(rollbackFor = Exception.class) - public boolean modelDeploy(String id) { - try { - // 查询流程定义模型xml - byte[] xmlBytes = repositoryService.getModelEditorSource(id); - if (ArrayUtil.isEmpty(xmlBytes)) { - throw new ServiceException("模型数据为空,请先设计流程定义模型,再进行部署!"); - } - if (JSONUtil.isTypeJSON(new String(xmlBytes, StandardCharsets.UTF_8))) { - byte[] bytes = ModelUtils.bpmnJsonToXmlBytes(xmlBytes); - if (ArrayUtil.isEmpty(bytes)) { - throw new ServiceException("模型不能为空,请至少设计一条主线流程!"); - } - } - BpmnModel bpmnModel = ModelUtils.xmlToBpmnModel(xmlBytes); - // 校验模型 - ModelUtils.checkBpmnModel(bpmnModel); - List validationErrors = repositoryService.validateProcess(bpmnModel); - if (CollUtil.isNotEmpty(validationErrors)) { - String errorMsg = validationErrors.stream().map(ValidationError::getProblem).distinct().collect(Collectors.joining(",")); - throw new ServiceException(errorMsg); - } - // 查询模型的基本信息 - Model model = repositoryService.getModel(id); - ProcessDefinition processDefinition = QueryUtils.definitionQuery().processDefinitionKey(model.getKey()).latestVersion().singleResult(); - // xml资源的名称 ,对应act_ge_bytearray表中的name_字段 - String processName = model.getName() + ".bpmn20.xml"; - // 调用部署相关的api方法进行部署流程定义 - Deployment deployment = repositoryService.createDeployment() - // 部署名称 - .name(model.getName()) - // 部署标识key - .key(model.getKey()) - // 部署流程分类 - .category(model.getCategory()) - // bpmn20.xml资源 - .addBytes(processName, xmlBytes) - // 租户id - .tenantId(TenantHelper.getTenantId()) - .deploy(); - - // 更新 部署id 到流程定义模型数据表中 - model.setDeploymentId(deployment.getId()); - repositoryService.saveModel(model); - // 更新分类 - ProcessDefinition definition = QueryUtils.definitionQuery().deploymentId(deployment.getId()).singleResult(); - repositoryService.setProcessDefinitionCategory(definition.getId(), model.getCategory()); - //更新流程定义配置 - if (processDefinition != null) { - WfDefinitionConfigVo definitionVo = wfDefinitionConfigService.getByDefId(processDefinition.getId()); - if (definitionVo != null) { - wfDefinitionConfigService.deleteByDefIds(Collections.singletonList(processDefinition.getId())); - WfDefinitionConfigBo wfFormDefinition = new WfDefinitionConfigBo(); - wfFormDefinition.setDefinitionId(definition.getId()); - wfFormDefinition.setProcessKey(definition.getKey()); - wfFormDefinition.setTableName(definitionVo.getTableName()); - wfFormDefinition.setVersion(definition.getVersion()); - wfFormDefinition.setRemark(definitionVo.getRemark()); - wfDefinitionConfigService.saveOrUpdate(wfFormDefinition); - } - } - //更新流程节点配置表单 - List userTasks = ModelUtils.getUserTaskFlowElements(definition.getId()); - UserTask applyUserTask = ModelUtils.getApplyUserTask(definition.getId()); - List wfNodeConfigList = new ArrayList<>(); - for (UserTask userTask : userTasks) { - if (StringUtils.isNotBlank(userTask.getFormKey()) && userTask.getFormKey().contains(StrUtil.COLON)) { - WfNodeConfig wfNodeConfig = new WfNodeConfig(); - wfNodeConfig.setNodeId(userTask.getId()); - wfNodeConfig.setNodeName(userTask.getName()); - wfNodeConfig.setDefinitionId(definition.getId()); - String[] split = userTask.getFormKey().split(StrUtil.COLON); - wfNodeConfig.setFormType(split[0]); - wfNodeConfig.setFormId(Long.valueOf(split[1])); - wfNodeConfig.setApplyUserTask(applyUserTask.getId().equals(userTask.getId()) ? FlowConstant.TRUE : FlowConstant.FALSE); - wfNodeConfigList.add(wfNodeConfig); - } - } - if (CollUtil.isNotEmpty(wfNodeConfigList)) { - wfNodeConfigService.saveOrUpdate(wfNodeConfigList); - } - return true; - } catch (Exception e) { - log.error(e.getMessage(), e); - throw new ServiceException(e.getMessage()); - } - } - - /** - * 导出模型zip压缩包 - * - * @param modelIds 模型id - * @param response 相应 - */ - @Override - public void exportZip(List modelIds, HttpServletResponse response) { - try (ZipOutputStream zos = ZipUtil.getZipOutputStream(response.getOutputStream(), StandardCharsets.UTF_8)) { - // 压缩包文件名 - String zipName = "模型不存在"; - // 查询模型基本信息 - for (String modelId : modelIds) { - Model model = repositoryService.getModel(modelId); - byte[] xmlBytes = repositoryService.getModelEditorSource(modelId); - if (ObjectUtil.isNotNull(model)) { - if (JSONUtil.isTypeJSON(new String(xmlBytes, StandardCharsets.UTF_8)) && ArrayUtil.isEmpty(ModelUtils.bpmnJsonToXmlBytes(xmlBytes))) { - zipName = "模型不能为空,请至少设计一条主线流程!"; - zos.putNextEntry(new ZipEntry(zipName + ".txt")); - zos.write(zipName.getBytes(StandardCharsets.UTF_8)); - } else if (ArrayUtil.isEmpty(xmlBytes)) { - zipName = "模型数据为空,请先设计流程定义模型,再进行部署!"; - zos.putNextEntry(new ZipEntry(zipName + ".txt")); - zos.write(zipName.getBytes(StandardCharsets.UTF_8)); - } else { - String fileName = model.getName() + "-" + model.getKey(); - // 压缩包文件名 - zipName = fileName + ".zip"; - // 将xml添加到压缩包中(指定xml文件名:请假流程.bpmn20.xml - zos.putNextEntry(new ZipEntry(fileName + ".bpmn20.xml")); - zos.write(xmlBytes); - } - } - } - response.setHeader("Content-Disposition", - "attachment; filename=" + URLEncoder.encode(zipName, StandardCharsets.UTF_8) + ".zip"); - response.addHeader("Access-Control-Expose-Headers", "Content-Disposition"); - // 刷出响应流 - response.flushBuffer(); - } catch (IOException e) { - log.error(e.getMessage(), e); - } - } - - /** - * 复制模型 - * - * @param modelBo 模型数据 - * @return 结果 - */ - @Override - @Transactional(rollbackFor = Exception.class) - public boolean copyModel(ModelBo modelBo) { - try { - String key = modelBo.getKey(); - if (StringUtils.isNotBlank(key)) { - // 查询模型 - Model model = repositoryService.createModelQuery().modelId(modelBo.getId()).singleResult(); - if (ObjectUtil.isNotNull(model)) { - byte[] modelEditorSource = repositoryService.getModelEditorSource(model.getId()); - List list = QueryUtils.modelQuery().modelKey(key).list(); - if (CollUtil.isNotEmpty(list)) { - throw new ServiceException("模型KEY已存在!"); - } - // 校验key命名规范 - if (!Validator.isMatchRegex(FlowConstant.MODEL_KEY_PATTERN, key)) { - throw new ServiceException("模型标识KEY只能字符或者下划线开头!"); - } - // 复制模型数据 - Model newModel = repositoryService.newModel(); - newModel.setKey(modelBo.getKey()); - newModel.setName(modelBo.getName()); - newModel.setCategory(modelBo.getCategoryCode()); - newModel.setVersion(1); - newModel.setMetaInfo(modelBo.getDescription()); - newModel.setTenantId(TenantHelper.getTenantId()); - String xml = StrUtil.utf8Str(modelEditorSource); - BpmnModel bpmnModel = ModelUtils.xmlToBpmnModel(xml); - Process mainProcess = bpmnModel.getMainProcess(); - mainProcess.setId(modelBo.getKey()); - mainProcess.setName(modelBo.getName()); - byte[] xmlBytes = new BpmnXMLConverter().convertToXML(bpmnModel); - repositoryService.saveModel(newModel); - repositoryService.addModelEditorSource(newModel.getId(), xmlBytes); - } - } - } catch (Exception e) { - log.error(e.getMessage(), e); - throw new ServiceException(e.getMessage()); - } - return true; - } -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActProcessDefinitionServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActProcessDefinitionServiceImpl.java deleted file mode 100644 index 77fb257b5..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActProcessDefinitionServiceImpl.java +++ /dev/null @@ -1,444 +0,0 @@ -package org.dromara.workflow.service.impl; - -import cn.hutool.core.bean.BeanUtil; -import cn.hutool.core.codec.Base64; -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.io.FileUtil; -import cn.hutool.core.io.IoUtil; -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.core.util.StrUtil; -import lombok.RequiredArgsConstructor; -import lombok.SneakyThrows; -import lombok.extern.slf4j.Slf4j; -import org.dromara.common.core.exception.ServiceException; -import org.dromara.common.core.utils.StreamUtils; -import org.dromara.common.core.utils.StringUtils; -import org.dromara.common.mybatis.core.page.PageQuery; -import org.dromara.common.mybatis.core.page.TableDataInfo; -import org.dromara.common.tenant.helper.TenantHelper; -import org.dromara.workflow.common.constant.FlowConstant; -import org.dromara.workflow.domain.WfCategory; -import org.dromara.workflow.domain.WfDefinitionConfig; -import org.dromara.workflow.domain.WfNodeConfig; -import org.dromara.workflow.domain.bo.ProcessDefinitionBo; -import org.dromara.workflow.domain.bo.WfDefinitionConfigBo; -import org.dromara.workflow.domain.vo.ProcessDefinitionVo; -import org.dromara.workflow.domain.vo.WfDefinitionConfigVo; -import org.dromara.workflow.mapper.WfDefinitionConfigMapper; -import org.dromara.workflow.service.IActProcessDefinitionService; -import org.dromara.workflow.service.IWfCategoryService; -import org.dromara.workflow.service.IWfDefinitionConfigService; -import org.dromara.workflow.service.IWfNodeConfigService; -import org.dromara.workflow.utils.ModelUtils; -import org.dromara.workflow.utils.QueryUtils; -import org.flowable.bpmn.model.UserTask; -import org.flowable.engine.ProcessMigrationService; -import org.flowable.engine.RepositoryService; -import org.flowable.engine.history.HistoricProcessInstance; -import org.flowable.engine.impl.bpmn.deployer.ResourceNameUtil; -import org.flowable.engine.repository.*; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.web.multipart.MultipartFile; - -import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Set; -import java.util.zip.ZipEntry; -import java.util.zip.ZipInputStream; - -/** - * 流程定义 服务层实现 - * - * @author may - */ -@Slf4j -@RequiredArgsConstructor -@Service -public class ActProcessDefinitionServiceImpl implements IActProcessDefinitionService { - - @Autowired(required = false) - private RepositoryService repositoryService; - @Autowired(required = false) - private ProcessMigrationService processMigrationService; - private final IWfCategoryService wfCategoryService; - private final IWfDefinitionConfigService wfDefinitionConfigService; - private final WfDefinitionConfigMapper wfDefinitionConfigMapper; - private final IWfNodeConfigService wfNodeConfigService; - - /** - * 分页查询 - * - * @param bo 参数 - * @return 返回分页列表 - */ - @Override - public TableDataInfo page(ProcessDefinitionBo bo, PageQuery pageQuery) { - ProcessDefinitionQuery query = QueryUtils.definitionQuery(); - if (StringUtils.isNotEmpty(bo.getKey())) { - query.processDefinitionKey(bo.getKey()); - } - if (StringUtils.isNotEmpty(bo.getCategoryCode())) { - query.processDefinitionCategory(bo.getCategoryCode()); - } - if (StringUtils.isNotEmpty(bo.getName())) { - query.processDefinitionNameLike("%" + bo.getName() + "%"); - } - query.orderByDeploymentId().desc(); - // 分页查询 - List processDefinitionVoList = new ArrayList<>(); - List definitionList = query.latestVersion().listPage(pageQuery.getFirstNum(), pageQuery.getPageSize()); - List deploymentList = null; - if (CollUtil.isNotEmpty(definitionList)) { - List deploymentIds = StreamUtils.toList(definitionList, ProcessDefinition::getDeploymentId); - deploymentList = QueryUtils.deploymentQuery(deploymentIds).list(); - } - if (CollUtil.isNotEmpty(definitionList)) { - List ids = StreamUtils.toList(definitionList, ProcessDefinition::getId); - List wfDefinitionConfigVos = wfDefinitionConfigService.queryList(ids); - for (ProcessDefinition processDefinition : definitionList) { - ProcessDefinitionVo processDefinitionVo = BeanUtil.toBean(processDefinition, ProcessDefinitionVo.class); - if (CollUtil.isNotEmpty(deploymentList)) { - // 部署时间 - deploymentList.stream().filter(e -> e.getId().equals(processDefinition.getDeploymentId())).findFirst().ifPresent(e -> { - processDefinitionVo.setDeploymentTime(e.getDeploymentTime()); - }); - } - if (CollUtil.isNotEmpty(wfDefinitionConfigVos)) { - wfDefinitionConfigVos.stream().filter(e -> e.getDefinitionId().equals(processDefinition.getId())).findFirst().ifPresent(processDefinitionVo::setWfDefinitionConfigVo); - } - processDefinitionVoList.add(processDefinitionVo); - } - } - // 总记录数 - long total = query.count(); - TableDataInfo build = TableDataInfo.build(); - build.setRows(processDefinitionVoList); - build.setTotal(total); - return build; - } - - /** - * 查询历史流程定义列表 - * - * @param key 流程定义key - */ - @Override - public List getListByKey(String key) { - List processDefinitionVoList = new ArrayList<>(); - ProcessDefinitionQuery query = QueryUtils.definitionQuery(); - List definitionList = query.processDefinitionKey(key).list(); - List deploymentList = null; - if (CollUtil.isNotEmpty(definitionList)) { - List deploymentIds = StreamUtils.toList(definitionList, ProcessDefinition::getDeploymentId); - deploymentList = QueryUtils.deploymentQuery(deploymentIds).list(); - } - if (CollUtil.isNotEmpty(definitionList)) { - List ids = StreamUtils.toList(definitionList, ProcessDefinition::getId); - List wfDefinitionConfigVos = wfDefinitionConfigService.queryList(ids); - for (ProcessDefinition processDefinition : definitionList) { - ProcessDefinitionVo processDefinitionVo = BeanUtil.toBean(processDefinition, ProcessDefinitionVo.class); - if (CollUtil.isNotEmpty(deploymentList)) { - // 部署时间 - deploymentList.stream().filter(e -> e.getId().equals(processDefinition.getDeploymentId())).findFirst().ifPresent(e -> { - processDefinitionVo.setDeploymentTime(e.getDeploymentTime()); - }); - if (CollUtil.isNotEmpty(wfDefinitionConfigVos)) { - wfDefinitionConfigVos.stream().filter(e -> e.getDefinitionId().equals(processDefinition.getId())).findFirst().ifPresent(processDefinitionVo::setWfDefinitionConfigVo); - } - } - processDefinitionVoList.add(processDefinitionVo); - } - } - return CollUtil.reverse(processDefinitionVoList); - } - - /** - * 查看流程定义图片 - * - * @param processDefinitionId 流程定义id - */ - @SneakyThrows - @Override - public String definitionImage(String processDefinitionId) { - InputStream inputStream = repositoryService.getProcessDiagram(processDefinitionId); - return Base64.encode(IoUtil.readBytes(inputStream)); - } - - /** - * 查看流程定义xml文件 - * - * @param processDefinitionId 流程定义id - */ - @Override - public String definitionXml(String processDefinitionId) { - StringBuilder xml = new StringBuilder(); - ProcessDefinition processDefinition = repositoryService.getProcessDefinition(processDefinitionId); - InputStream inputStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), processDefinition.getResourceName()); - xml.append(IoUtil.read(inputStream, StandardCharsets.UTF_8)); - return xml.toString(); - } - - /** - * 删除流程定义 - * - * @param deploymentIds 部署id - * @param processDefinitionIds 流程定义id - */ - @Override - @Transactional(rollbackFor = Exception.class) - public boolean deleteDeployment(List deploymentIds, List processDefinitionIds) { - try { - List historicProcessInstances = QueryUtils.hisInstanceQuery().deploymentIdIn(deploymentIds).list(); - if (CollUtil.isNotEmpty(historicProcessInstances)) { - Set defIds = StreamUtils.toSet(historicProcessInstances, HistoricProcessInstance::getProcessDefinitionId); - List processDefinitions = QueryUtils.definitionQuery().processDefinitionIds(defIds).list(); - if (CollUtil.isNotEmpty(processDefinitions)) { - Set keys = StreamUtils.toSet(processDefinitions, ProcessDefinition::getKey); - throw new ServiceException("当前【" + String.join(",", keys) + "】流程定义已被使用不可删除!"); - } - } - //删除流程定义 - for (String deploymentId : deploymentIds) { - repositoryService.deleteDeployment(deploymentId); - } - //删除流程定义配置 - wfDefinitionConfigService.deleteByDefIds(processDefinitionIds); - //删除节点配置 - wfNodeConfigService.deleteByDefIds(processDefinitionIds); - return true; - } catch (Exception e) { - log.error(e.getMessage(), e); - throw new ServiceException(e.getMessage()); - } - } - - /** - * 激活或者挂起流程定义 - * - * @param processDefinitionId 流程定义id - */ - @Override - public boolean updateDefinitionState(String processDefinitionId) { - try { - ProcessDefinition processDefinition = QueryUtils.definitionQuery() - .processDefinitionId(processDefinitionId).singleResult(); - //将当前为挂起状态更新为激活状态 - //参数说明:参数1:流程定义id,参数2:是否激活(true是否级联对应流程实例,激活了则对应流程实例都可以审批), - //参数3:什么时候激活,如果为null则立即激活,如果为具体时间则到达此时间后激活 - if (processDefinition.isSuspended()) { - repositoryService.activateProcessDefinitionById(processDefinitionId, true, null); - } else { - repositoryService.suspendProcessDefinitionById(processDefinitionId, true, null); - } - return true; - } catch (Exception e) { - log.error(e.getMessage(), e); - throw new ServiceException("操作失败:" + e.getMessage()); - } - } - - /** - * 迁移流程定义 - * - * @param currentProcessDefinitionId 当前流程定义id - * @param fromProcessDefinitionId 需要迁移到的流程定义id - */ - - @Override - public boolean migrationDefinition(String currentProcessDefinitionId, String fromProcessDefinitionId) { - try { - // 迁移验证 - boolean migrationValid = processMigrationService.createProcessInstanceMigrationBuilder() - .migrateToProcessDefinition(currentProcessDefinitionId) - .validateMigrationOfProcessInstances(fromProcessDefinitionId) - .isMigrationValid(); - if (!migrationValid) { - throw new ServiceException("流程定义差异过大无法迁移,请修改流程图"); - } - // 已结束的流程实例不会迁移 - processMigrationService.createProcessInstanceMigrationBuilder() - .migrateToProcessDefinition(currentProcessDefinitionId) - .migrateProcessInstances(fromProcessDefinitionId); - return true; - } catch (Exception e) { - log.error(e.getMessage(), e); - throw new ServiceException(e.getMessage()); - } - } - - /** - * 流程定义转换为模型 - * - * @param processDefinitionId 流程定义id - */ - @Override - public boolean convertToModel(String processDefinitionId) { - ProcessDefinition pd = QueryUtils.definitionQuery() - .processDefinitionId(processDefinitionId).singleResult(); - InputStream inputStream = repositoryService.getResourceAsStream(pd.getDeploymentId(), pd.getResourceName()); - ModelQuery query = QueryUtils.modelQuery(); - Model model = query.modelKey(pd.getKey()).singleResult(); - try { - if (ObjectUtil.isNotNull(model)) { - repositoryService.addModelEditorSource(model.getId(), IoUtil.readBytes(inputStream)); - } else { - Model modelData = repositoryService.newModel(); - modelData.setKey(pd.getKey()); - modelData.setName(pd.getName()); - modelData.setCategory(pd.getCategory()); - modelData.setTenantId(pd.getTenantId()); - repositoryService.saveModel(modelData); - repositoryService.addModelEditorSource(modelData.getId(), IoUtil.readBytes(inputStream)); - } - return true; - } catch (Exception e) { - log.error(e.getMessage(), e); - throw new ServiceException(e.getMessage()); - } - } - - /** - * 通过zip或xml部署流程定义 - * - * @param file 文件 - * @param categoryCode 分类 - */ - @SneakyThrows - @Override - @Transactional(rollbackFor = Exception.class) - public void deployByFile(MultipartFile file, String categoryCode) { - - WfCategory wfCategory = wfCategoryService.queryByCategoryCode(categoryCode); - if (wfCategory == null) { - throw new ServiceException("流程分类不存在"); - } - // 文件后缀名 - String suffix = FileUtil.extName(file.getOriginalFilename()); - InputStream inputStream = file.getInputStream(); - if (FlowConstant.ZIP.equalsIgnoreCase(suffix)) { - ZipInputStream zipInputStream = null; - try { - zipInputStream = new ZipInputStream(inputStream); - ZipEntry zipEntry; - while ((zipEntry = zipInputStream.getNextEntry()) != null) { - String filename = zipEntry.getName(); - String[] splitFilename = filename.substring(0, filename.lastIndexOf(".")).split("-"); - //流程名称 - String processName = splitFilename[0]; - //流程key - String processKey = splitFilename[1]; - ProcessDefinition oldProcessDefinition = QueryUtils.definitionQuery().processDefinitionKey(processKey).latestVersion().singleResult(); - DeploymentBuilder builder = repositoryService.createDeployment(); - Deployment deployment = builder.addInputStream(filename, zipInputStream) - .tenantId(TenantHelper.getTenantId()) - .name(processName).key(processKey).category(categoryCode).deploy(); - ProcessDefinition definition = QueryUtils.definitionQuery().deploymentId(deployment.getId()).singleResult(); - repositoryService.setProcessDefinitionCategory(definition.getId(), categoryCode); - setWfConfig(oldProcessDefinition, definition); - zipInputStream.closeEntry(); - } - } catch (IOException e) { - throw new RuntimeException(e); - } finally { - if (zipInputStream != null) { - zipInputStream.close(); - } - } - //初始化配置数据(demo使用,不用可删除) - initWfDefConfig(); - } else { - String originalFilename = file.getOriginalFilename(); - if (StringUtils.containsAny(originalFilename, ResourceNameUtil.BPMN_RESOURCE_SUFFIXES)) { - // 文件名 = 流程名称-流程key - String[] splitFilename = originalFilename.substring(0, originalFilename.lastIndexOf(".")).split("-"); - if (splitFilename.length < 2) { - throw new ServiceException("文件名 = 流程名称-流程KEY"); - } - //流程名称 - String processName = splitFilename[0]; - //流程key - String processKey = splitFilename[1]; - ProcessDefinition oldProcessDefinition = QueryUtils.definitionQuery().processDefinitionKey(processKey).latestVersion().singleResult(); - DeploymentBuilder builder = repositoryService.createDeployment(); - Deployment deployment = builder.addInputStream(originalFilename, inputStream) - .tenantId(TenantHelper.getTenantId()) - .name(processName).key(processKey).category(categoryCode).deploy(); - // 更新分类 - ProcessDefinition definition = QueryUtils.definitionQuery().deploymentId(deployment.getId()).singleResult(); - repositoryService.setProcessDefinitionCategory(definition.getId(), categoryCode); - setWfConfig(oldProcessDefinition, definition); - } else { - throw new ServiceException("文件类型上传错误!"); - } - } - - } - - /** - * 初始化配置数据(demo使用,不用可删除) - */ - private void initWfDefConfig() { - List wfDefinitionConfigs = wfDefinitionConfigMapper.selectList(); - if (CollUtil.isEmpty(wfDefinitionConfigs)) { - ProcessDefinition processDefinition = QueryUtils.definitionQuery().processDefinitionKey("leave1").latestVersion().singleResult(); - if (processDefinition != null) { - WfDefinitionConfigBo wfDefinitionConfigBo = new WfDefinitionConfigBo(); - wfDefinitionConfigBo.setDefinitionId(processDefinition.getId()); - wfDefinitionConfigBo.setProcessKey(processDefinition.getKey()); - wfDefinitionConfigBo.setTableName("test_leave"); - wfDefinitionConfigBo.setVersion(processDefinition.getVersion()); - wfDefinitionConfigService.saveOrUpdate(wfDefinitionConfigBo); - } - } - - } - - /** - * 设置表单内容 - * - * @param oldProcessDefinition 部署前最新流程定义 - * @param definition 部署后最新流程定义 - */ - private void setWfConfig(ProcessDefinition oldProcessDefinition, ProcessDefinition definition) { - //更新流程定义表单 - if (oldProcessDefinition != null) { - WfDefinitionConfigVo definitionVo = wfDefinitionConfigService.getByDefId(oldProcessDefinition.getId()); - if (definitionVo != null) { - wfDefinitionConfigService.deleteByDefIds(Collections.singletonList(oldProcessDefinition.getId())); - WfDefinitionConfigBo wfDefinitionConfigBo = new WfDefinitionConfigBo(); - wfDefinitionConfigBo.setDefinitionId(definition.getId()); - wfDefinitionConfigBo.setProcessKey(definition.getKey()); - wfDefinitionConfigBo.setTableName(definitionVo.getTableName()); - wfDefinitionConfigBo.setVersion(definition.getVersion()); - wfDefinitionConfigBo.setRemark(definitionVo.getRemark()); - wfDefinitionConfigService.saveOrUpdate(wfDefinitionConfigBo); - } - } - //更新流程节点配置表单 - List userTasks = ModelUtils.getUserTaskFlowElements(definition.getId()); - UserTask applyUserTask = ModelUtils.getApplyUserTask(definition.getId()); - List wfNodeConfigList = new ArrayList<>(); - for (UserTask userTask : userTasks) { - if (StringUtils.isNotBlank(userTask.getFormKey()) && userTask.getFormKey().contains(StrUtil.COLON)) { - WfNodeConfig wfNodeConfig = new WfNodeConfig(); - wfNodeConfig.setNodeId(userTask.getId()); - wfNodeConfig.setNodeName(userTask.getName()); - wfNodeConfig.setDefinitionId(definition.getId()); - String[] split = userTask.getFormKey().split(StrUtil.COLON); - wfNodeConfig.setFormType(split[0]); - wfNodeConfig.setFormId(Long.valueOf(split[1])); - wfNodeConfig.setApplyUserTask(applyUserTask.getId().equals(userTask.getId()) ? FlowConstant.TRUE : FlowConstant.FALSE); - wfNodeConfigList.add(wfNodeConfig); - } - } - if (CollUtil.isNotEmpty(wfNodeConfigList)) { - wfNodeConfigService.saveOrUpdate(wfNodeConfigList); - } - } -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActProcessInstanceServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActProcessInstanceServiceImpl.java deleted file mode 100644 index 8b9b113fd..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActProcessInstanceServiceImpl.java +++ /dev/null @@ -1,691 +0,0 @@ -package org.dromara.workflow.service.impl; - -import cn.hutool.core.bean.BeanUtil; -import cn.hutool.core.codec.Base64; -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.convert.Convert; -import cn.hutool.core.io.IoUtil; -import cn.hutool.core.util.ObjectUtil; -import lombok.RequiredArgsConstructor; -import lombok.SneakyThrows; -import lombok.extern.slf4j.Slf4j; -import org.dromara.common.core.enums.BusinessStatusEnum; -import org.dromara.common.core.exception.ServiceException; -import org.dromara.common.core.service.UserService; -import org.dromara.common.core.utils.StreamUtils; -import org.dromara.common.core.utils.StringUtils; -import org.dromara.common.mybatis.core.page.PageQuery; -import org.dromara.common.mybatis.core.page.TableDataInfo; -import org.dromara.common.satoken.utils.LoginHelper; -import org.dromara.workflow.common.constant.FlowConstant; -import org.dromara.workflow.common.enums.TaskStatusEnum; -import org.dromara.workflow.domain.ActHiProcinst; -import org.dromara.workflow.domain.bo.ProcessInstanceBo; -import org.dromara.workflow.domain.bo.ProcessInvalidBo; -import org.dromara.workflow.domain.bo.TaskUrgingBo; -import org.dromara.workflow.domain.vo.*; -import org.dromara.workflow.flowable.CustomDefaultProcessDiagramGenerator; -import org.dromara.workflow.flowable.cmd.DeleteExecutionCmd; -import org.dromara.workflow.flowable.cmd.ExecutionChildByExecutionIdCmd; -import org.dromara.workflow.flowable.handler.FlowProcessEventHandler; -import org.dromara.workflow.service.IActHiProcinstService; -import org.dromara.workflow.service.IActProcessInstanceService; -import org.dromara.workflow.service.IWfNodeConfigService; -import org.dromara.workflow.service.IWfTaskBackNodeService; -import org.dromara.workflow.utils.QueryUtils; -import org.dromara.workflow.utils.WorkflowUtils; -import org.flowable.bpmn.model.BpmnModel; -import org.flowable.engine.*; -import org.flowable.engine.history.HistoricActivityInstance; -import org.flowable.engine.history.HistoricProcessInstance; -import org.flowable.engine.history.HistoricProcessInstanceQuery; -import org.flowable.engine.impl.persistence.entity.ExecutionEntity; -import org.flowable.engine.repository.ProcessDefinition; -import org.flowable.engine.runtime.ProcessInstance; -import org.flowable.engine.runtime.ProcessInstanceQuery; -import org.flowable.engine.task.Attachment; -import org.flowable.engine.task.Comment; -import org.flowable.task.api.Task; -import org.flowable.task.api.history.HistoricTaskInstance; -import org.springframework.beans.BeanUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.awt.*; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; -import java.util.List; -import java.util.*; - -/** - * 流程实例 服务层实现 - * - * @author may - */ -@Slf4j -@RequiredArgsConstructor -@Service -public class ActProcessInstanceServiceImpl implements IActProcessInstanceService { - - @Autowired(required = false) - private RepositoryService repositoryService; - @Autowired(required = false) - private RuntimeService runtimeService; - @Autowired(required = false) - private HistoryService historyService; - @Autowired(required = false) - private TaskService taskService; - @Autowired(required = false) - private ManagementService managementService; - private final IActHiProcinstService actHiProcinstService; - private final IWfTaskBackNodeService wfTaskBackNodeService; - private final IWfNodeConfigService wfNodeConfigService; - private final FlowProcessEventHandler flowProcessEventHandler; - private final UserService userService; - - @Value("${flowable.activity-font-name}") - private String activityFontName; - - @Value("${flowable.label-font-name}") - private String labelFontName; - - @Value("${flowable.annotation-font-name}") - private String annotationFontName; - - /** - * 分页查询正在运行的流程实例 - * - * @param bo 参数 - */ - @Override - public TableDataInfo getPageByRunning(ProcessInstanceBo bo, PageQuery pageQuery) { - List list = new ArrayList<>(); - ProcessInstanceQuery query = QueryUtils.instanceQuery(); - if (StringUtils.isNotBlank(bo.getName())) { - query.processInstanceNameLikeIgnoreCase("%" + bo.getName() + "%"); - } - if (StringUtils.isNotBlank(bo.getKey())) { - query.processDefinitionKey(bo.getKey()); - } - if (StringUtils.isNotBlank(bo.getStartUserId())) { - query.startedBy(bo.getStartUserId()); - } - if (StringUtils.isNotBlank(bo.getBusinessKey())) { - query.processInstanceBusinessKey(bo.getBusinessKey()); - } - if (StringUtils.isNotBlank(bo.getCategoryCode())) { - query.processDefinitionCategory(bo.getCategoryCode()); - } - query.orderByStartTime().desc(); - List processInstances = query.listPage(pageQuery.getFirstNum(), pageQuery.getPageSize()); - for (ProcessInstance processInstance : processInstances) { - ProcessInstanceVo processInstanceVo = BeanUtil.toBean(processInstance, ProcessInstanceVo.class); - processInstanceVo.setIsSuspended(processInstance.isSuspended()); - processInstanceVo.setBusinessStatusName(BusinessStatusEnum.findByStatus(processInstance.getBusinessStatus())); - list.add(processInstanceVo); - } - if (CollUtil.isNotEmpty(list)) { - List processDefinitionIds = StreamUtils.toList(list, ProcessInstanceVo::getProcessDefinitionId); - List wfNodeConfigVoList = wfNodeConfigService.selectByDefIds(processDefinitionIds); - for (ProcessInstanceVo processInstanceVo : list) { - if (CollUtil.isNotEmpty(wfNodeConfigVoList)) { - wfNodeConfigVoList.stream().filter(e -> e.getDefinitionId().equals(processInstanceVo.getProcessDefinitionId()) && FlowConstant.TRUE.equals(e.getApplyUserTask())).findFirst().ifPresent(processInstanceVo::setWfNodeConfigVo); - } - } - } - long count = query.count(); - TableDataInfo build = TableDataInfo.build(); - build.setRows(list); - build.setTotal(count); - return build; - } - - /** - * 分页查询已结束的流程实例 - * - * @param bo 参数 - */ - @Override - public TableDataInfo getPageByFinish(ProcessInstanceBo bo, PageQuery pageQuery) { - List list = new ArrayList<>(); - HistoricProcessInstanceQuery query = QueryUtils.hisInstanceQuery() - .finished().orderByProcessInstanceEndTime().desc(); - if (StringUtils.isNotEmpty(bo.getName())) { - query.processInstanceNameLikeIgnoreCase("%" + bo.getName() + "%"); - } - if (StringUtils.isNotBlank(bo.getKey())) { - query.processDefinitionKey(bo.getKey()); - } - if (StringUtils.isNotEmpty(bo.getStartUserId())) { - query.startedBy(bo.getStartUserId()); - } - if (StringUtils.isNotBlank(bo.getBusinessKey())) { - query.processInstanceBusinessKey(bo.getBusinessKey()); - } - if (StringUtils.isNotBlank(bo.getCategoryCode())) { - query.processDefinitionCategory(bo.getCategoryCode()); - } - List historicProcessInstances = query.listPage(pageQuery.getFirstNum(), pageQuery.getPageSize()); - for (HistoricProcessInstance historicProcessInstance : historicProcessInstances) { - ProcessInstanceVo processInstanceVo = BeanUtil.toBean(historicProcessInstance, ProcessInstanceVo.class); - processInstanceVo.setBusinessStatusName(BusinessStatusEnum.findByStatus(historicProcessInstance.getBusinessStatus())); - list.add(processInstanceVo); - } - if (CollUtil.isNotEmpty(list)) { - List processDefinitionIds = StreamUtils.toList(list, ProcessInstanceVo::getProcessDefinitionId); - List wfNodeConfigVoList = wfNodeConfigService.selectByDefIds(processDefinitionIds); - for (ProcessInstanceVo processInstanceVo : list) { - if (CollUtil.isNotEmpty(wfNodeConfigVoList)) { - wfNodeConfigVoList.stream().filter(e -> e.getDefinitionId().equals(processInstanceVo.getProcessDefinitionId()) && FlowConstant.TRUE.equals(e.getApplyUserTask())).findFirst().ifPresent(processInstanceVo::setWfNodeConfigVo); - } - } - } - long count = query.count(); - TableDataInfo build = TableDataInfo.build(); - build.setRows(list); - build.setTotal(count); - return build; - } - - /** - * 通过业务id获取历史流程图 - * - * @param businessKey 业务id - */ - @SneakyThrows - @Override - public String getHistoryImage(String businessKey) { - String processDefinitionId; - // 获取当前的流程实例 - ProcessInstance processInstance = QueryUtils.businessKeyQuery(businessKey).singleResult(); - // 如果流程已经结束,则得到结束节点 - if (Objects.isNull(processInstance)) { - HistoricProcessInstance pi = QueryUtils.hisInstanceQuery().processInstanceBusinessKey(businessKey).singleResult(); - processDefinitionId = pi.getProcessDefinitionId(); - } else { - // 根据流程实例ID获得当前处于活动状态的ActivityId合集 - ProcessInstance pi = QueryUtils.instanceQuery(processInstance.getProcessInstanceId()).singleResult(); - processDefinitionId = pi.getProcessDefinitionId(); - } - - // 获得活动的节点 - List highLightedFlowList = QueryUtils.hisActivityInstanceQuery(processInstance.getProcessInstanceId()).orderByHistoricActivityInstanceStartTime().asc().list(); - - List highLightedFlows = new ArrayList<>(); - List highLightedNodes = new ArrayList<>(); - //高亮 - for (HistoricActivityInstance tempActivity : highLightedFlowList) { - if (FlowConstant.SEQUENCE_FLOW.equals(tempActivity.getActivityType())) { - //高亮线 - highLightedFlows.add(tempActivity.getActivityId()); - } else { - //高亮节点 - if (tempActivity.getEndTime() == null) { - highLightedNodes.add(Color.RED.toString() + tempActivity.getActivityId()); - } else { - highLightedNodes.add(tempActivity.getActivityId()); - } - } - } - List highLightedNodeList = new ArrayList<>(); - //运行中的节点 - List redNodeCollect = StreamUtils.filter(highLightedNodes, e -> e.contains(Color.RED.toString())); - //排除与运行中相同的节点 - for (String nodeId : highLightedNodes) { - if (!nodeId.contains(Color.RED.toString()) && !redNodeCollect.contains(Color.RED + nodeId)) { - highLightedNodeList.add(nodeId); - } - } - highLightedNodeList.addAll(redNodeCollect); - BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId); - CustomDefaultProcessDiagramGenerator diagramGenerator = new CustomDefaultProcessDiagramGenerator(); - InputStream inputStream = diagramGenerator.generateDiagram(bpmnModel, "png", highLightedNodeList, highLightedFlows, activityFontName, labelFontName, annotationFontName, null, 1.0, true); - return Base64.encode(IoUtil.readBytes(inputStream)); - } - - /** - * 通过业务id获取历史流程图运行中,历史等节点 - * - * @param businessKey 业务id - */ - @Override - public Map getHistoryList(String businessKey) { - Map map = new HashMap<>(); - List> taskList = new ArrayList<>(); - HistoricProcessInstance historicProcessInstance = QueryUtils.hisBusinessKeyQuery(businessKey).singleResult(); - String processInstanceId = historicProcessInstance.getId(); - StringBuilder xml = new StringBuilder(); - ProcessDefinition processDefinition = repositoryService.getProcessDefinition(historicProcessInstance.getProcessDefinitionId()); - // 获取节点 - List highLightedFlowList = QueryUtils.hisActivityInstanceQuery(processInstanceId).orderByHistoricActivityInstanceStartTime().asc().list(); - for (HistoricActivityInstance tempActivity : highLightedFlowList) { - Map task = new HashMap<>(); - switch (tempActivity.getActivityType()) { - case FlowConstant.SEQUENCE_FLOW, FlowConstant.PARALLEL_GATEWAY, - FlowConstant.EXCLUSIVE_GATEWAY, FlowConstant.INCLUSIVE_GATEWAY -> {} - default -> { - task.put("key", tempActivity.getActivityId()); - task.put("completed", tempActivity.getEndTime() != null); - task.put("activityType", tempActivity.getActivityType()); - taskList.add(task); - } - } - } - ProcessInstance processInstance = QueryUtils.instanceQuery(processInstanceId).singleResult(); - if (processInstance != null) { - taskList = StreamUtils.filter(taskList, e -> !e.get("activityType").equals(FlowConstant.END_EVENT)); - } - //查询出运行中节点 - List> runtimeNodeList = StreamUtils.filter(taskList, e -> !(Boolean) e.get("completed")); - if (CollUtil.isNotEmpty(runtimeNodeList)) { - Iterator> iterator = taskList.iterator(); - while (iterator.hasNext()) { - Map next = iterator.next(); - runtimeNodeList.stream().filter(t -> t.get("key").equals(next.get("key")) && (Boolean) next.get("completed")).findFirst().ifPresent(t -> iterator.remove()); - } - } - map.put("taskList", taskList); - List historyTaskList = getHistoryTaskList(processInstanceId, processDefinition.getVersion()); - map.put("historyList", historyTaskList); - InputStream inputStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), processDefinition.getResourceName()); - xml.append(IoUtil.read(inputStream, StandardCharsets.UTF_8)); - map.put("xml", xml.toString()); - return map; - } - - /** - * 获取历史任务节点信息 - * - * @param processInstanceId 流程实例id - * @param version 版本 - */ - private List getHistoryTaskList(String processInstanceId, Integer version) { - //查询任务办理记录 - List list = QueryUtils.hisTaskInstanceQuery(processInstanceId).orderByHistoricTaskInstanceEndTime().desc().list(); - list = StreamUtils.sorted(list, Comparator.comparing(HistoricTaskInstance::getEndTime, Comparator.nullsFirst(Date::compareTo)).reversed()); - List actHistoryInfoVoList = new ArrayList<>(); - for (HistoricTaskInstance historicTaskInstance : list) { - ActHistoryInfoVo actHistoryInfoVo = new ActHistoryInfoVo(); - BeanUtils.copyProperties(historicTaskInstance, actHistoryInfoVo); - actHistoryInfoVo.setStatus(actHistoryInfoVo.getEndTime() == null ? "待处理" : "已处理"); - if (ObjectUtil.isNotEmpty(historicTaskInstance.getDurationInMillis())) { - actHistoryInfoVo.setRunDuration(getDuration(historicTaskInstance.getDurationInMillis())); - } - actHistoryInfoVo.setVersion(version); - actHistoryInfoVoList.add(actHistoryInfoVo); - } - List historyInfoVoList = new ArrayList<>(); - Map> groupByKey = StreamUtils.groupByKey(actHistoryInfoVoList, ActHistoryInfoVo::getTaskDefinitionKey); - for (Map.Entry> entry : groupByKey.entrySet()) { - ActHistoryInfoVo historyInfoVo = new ActHistoryInfoVo(); - if (entry.getValue().size() > 1) { - List historyInfoVos = StreamUtils.filter(entry.getValue(), e -> StringUtils.isNotBlank(e.getAssignee())); - if (CollUtil.isNotEmpty(historyInfoVos)) { - ActHistoryInfoVo infoVo = historyInfoVos.get(0); - BeanUtils.copyProperties(infoVo, historyInfoVo); - historyInfoVo.setStatus(infoVo.getEndTime() == null ? "待处理" : "已处理"); - historyInfoVo.setStartTime(infoVo.getStartTime()); - historyInfoVo.setEndTime(infoVo.getEndTime() == null ? null : infoVo.getEndTime()); - historyInfoVo.setRunDuration(infoVo.getEndTime() == null ? null : infoVo.getRunDuration()); - if (ObjectUtil.isEmpty(infoVo.getAssignee())) { - ParticipantVo participantVo = WorkflowUtils.getCurrentTaskParticipant(infoVo.getId(), userService); - if (ObjectUtil.isNotEmpty(participantVo) && CollUtil.isNotEmpty(participantVo.getCandidate())) { - historyInfoVo.setAssignee(StreamUtils.join(participantVo.getCandidate(), Convert::toStr)); - } - } - } - } else { - actHistoryInfoVoList.stream().filter(e -> e.getTaskDefinitionKey().equals(entry.getKey())).findFirst() - .ifPresent(e -> { - BeanUtils.copyProperties(e, historyInfoVo); - historyInfoVo.setStatus(e.getEndTime() == null ? "待处理" : "已处理"); - historyInfoVo.setStartTime(e.getStartTime()); - historyInfoVo.setEndTime(e.getEndTime() == null ? null : e.getEndTime()); - historyInfoVo.setRunDuration(e.getEndTime() == null ? null : e.getRunDuration()); - if (ObjectUtil.isEmpty(e.getAssignee())) { - ParticipantVo participantVo = WorkflowUtils.getCurrentTaskParticipant(e.getId(), userService); - if (ObjectUtil.isNotEmpty(participantVo) && CollUtil.isNotEmpty(participantVo.getCandidate())) { - historyInfoVo.setAssignee(StreamUtils.join(participantVo.getCandidate(), Convert::toStr)); - } - } - }); - - } - historyInfoVoList.add(historyInfoVo); - - } - return historyInfoVoList; - } - - /** - * 获取审批记录 - * - * @param businessKey 业务id - */ - @Override - public List getHistoryRecord(String businessKey) { - // 查询任务办理记录 - List list = QueryUtils.hisTaskBusinessKeyQuery(businessKey).orderByHistoricTaskInstanceEndTime().desc().list(); - list = StreamUtils.sorted(list, Comparator.comparing(HistoricTaskInstance::getEndTime, Comparator.nullsFirst(Date::compareTo)).reversed()); - HistoricProcessInstance historicProcessInstance = QueryUtils.hisBusinessKeyQuery(businessKey).singleResult(); - String processInstanceId = historicProcessInstance.getId(); - List actHistoryInfoVoList = new ArrayList<>(); - List processInstanceComments = taskService.getProcessInstanceComments(processInstanceId); - //附件 - List attachmentList = taskService.getProcessInstanceAttachments(processInstanceId); - for (HistoricTaskInstance historicTaskInstance : list) { - ActHistoryInfoVo actHistoryInfoVo = new ActHistoryInfoVo(); - BeanUtils.copyProperties(historicTaskInstance, actHistoryInfoVo); - if (actHistoryInfoVo.getEndTime() == null) { - actHistoryInfoVo.setStatus(TaskStatusEnum.WAITING.getStatus()); - actHistoryInfoVo.setStatusName(TaskStatusEnum.WAITING.getDesc()); - } - if (CollUtil.isNotEmpty(processInstanceComments)) { - processInstanceComments.stream().filter(e -> e.getTaskId().equals(historicTaskInstance.getId())).findFirst().ifPresent(e -> { - actHistoryInfoVo.setComment(e.getFullMessage()); - actHistoryInfoVo.setStatus(e.getType()); - actHistoryInfoVo.setStatusName(TaskStatusEnum.findByStatus(e.getType())); - }); - } - if (ObjectUtil.isNotEmpty(historicTaskInstance.getDurationInMillis())) { - actHistoryInfoVo.setRunDuration(getDuration(historicTaskInstance.getDurationInMillis())); - } - //附件 - if (CollUtil.isNotEmpty(attachmentList)) { - List attachments = StreamUtils.filter(attachmentList, e -> e.getTaskId().equals(historicTaskInstance.getId())); - if (CollUtil.isNotEmpty(attachments)) { - actHistoryInfoVo.setAttachmentList(attachments); - } - } - //设置人员id - if (ObjectUtil.isEmpty(historicTaskInstance.getAssignee())) { - ParticipantVo participantVo = WorkflowUtils.getCurrentTaskParticipant(historicTaskInstance.getId(), userService); - if (ObjectUtil.isNotEmpty(participantVo) && CollUtil.isNotEmpty(participantVo.getCandidate())) { - actHistoryInfoVo.setAssignee(StreamUtils.join(participantVo.getCandidate(), Convert::toStr)); - } - } - actHistoryInfoVoList.add(actHistoryInfoVo); - } - // 审批记录 - Map> groupByKey = StreamUtils.groupByKey(actHistoryInfoVoList, ActHistoryInfoVo::getTaskDefinitionKey); - for (Map.Entry> entry : groupByKey.entrySet()) { - ActHistoryInfoVo actHistoryInfoVo = BeanUtil.toBean(entry.getValue().get(0), ActHistoryInfoVo.class); - actHistoryInfoVoList.stream().filter(e -> e.getTaskDefinitionKey().equals(entry.getKey()) && e.getEndTime() != null).findFirst() - .ifPresent(e -> { - actHistoryInfoVo.setStatus("已处理"); - actHistoryInfoVo.setStartTime(e.getStartTime()); - }); - actHistoryInfoVoList.stream().filter(e -> e.getTaskDefinitionKey().equals(entry.getKey()) && e.getEndTime() == null).findFirst() - .ifPresent(e -> { - actHistoryInfoVo.setStatus("待处理"); - actHistoryInfoVo.setStartTime(e.getStartTime()); - actHistoryInfoVo.setEndTime(null); - actHistoryInfoVo.setRunDuration(null); - }); - } - List recordList = new ArrayList<>(); - // 待办理 - recordList.addAll(StreamUtils.filter(actHistoryInfoVoList, e -> e.getEndTime() == null)); - // 已办理 - recordList.addAll(StreamUtils.filter(actHistoryInfoVoList, e -> e.getEndTime() != null)); - - return recordList; - } - - /** - * 任务完成时间处理 - * - * @param time 时间 - */ - private String getDuration(long time) { - - long day = time / (24 * 60 * 60 * 1000); - long hour = (time / (60 * 60 * 1000) - day * 24); - long minute = ((time / (60 * 1000)) - day * 24 * 60 - hour * 60); - long second = (time / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - minute * 60); - - if (day > 0) { - return day + "天" + hour + "小时" + minute + "分钟"; - } - if (hour > 0) { - return hour + "小时" + minute + "分钟"; - } - if (minute > 0) { - return minute + "分钟"; - } - if (second > 0) { - return second + "秒"; - } else { - return 0 + "秒"; - } - } - - /** - * 作废流程实例,不会删除历史记录(删除运行中的实例) - * - * @param processInvalidBo 参数 - */ - @Override - @Transactional(rollbackFor = Exception.class) - public boolean deleteRunInstance(ProcessInvalidBo processInvalidBo) { - try { - List list = QueryUtils.taskQuery().processInstanceBusinessKey(processInvalidBo.getBusinessKey()).list(); - String processInstanceId = list.get(0).getProcessInstanceId(); - List subTasks = StreamUtils.filter(list, e -> StringUtils.isNotBlank(e.getParentTaskId())); - if (CollUtil.isNotEmpty(subTasks)) { - subTasks.forEach(e -> taskService.deleteTask(e.getId())); - } - String deleteReason = LoginHelper.getLoginUser().getNickname() + "作废了当前申请!"; - if (StringUtils.isNotBlank(processInvalidBo.getDeleteReason())) { - deleteReason = LoginHelper.getLoginUser().getNickname() + "作废理由:" + processInvalidBo.getDeleteReason(); - } - for (Task task : StreamUtils.filter(list, e -> StringUtils.isBlank(e.getParentTaskId()))) { - taskService.addComment(task.getId(), task.getProcessInstanceId(), TaskStatusEnum.INVALID.getStatus(), deleteReason); - } - HistoricProcessInstance historicProcessInstance = QueryUtils.hisInstanceQuery(processInstanceId).singleResult(); - BusinessStatusEnum.checkInvalidStatus(historicProcessInstance.getBusinessStatus()); - runtimeService.updateBusinessStatus(processInstanceId, BusinessStatusEnum.INVALID.getStatus()); - runtimeService.deleteProcessInstance(processInstanceId, deleteReason); - //流程作废监听 - flowProcessEventHandler.processHandler(historicProcessInstance.getProcessDefinitionKey(), - historicProcessInstance.getBusinessKey(), BusinessStatusEnum.INVALID.getStatus(), false); - return true; - } catch (Exception e) { - log.error(e.getMessage(), e); - throw new ServiceException(e.getMessage()); - } - } - - /** - * 运行中的实例 删除程实例,删除历史记录,删除业务与流程关联信息 - * - * @param businessKeys 业务id - */ - @Override - @Transactional(rollbackFor = Exception.class) - public boolean deleteRunAndHisInstance(List businessKeys) { - try { - // 1.删除运行中流程实例 - List actHiProcinsts = actHiProcinstService.selectByBusinessKeyIn(businessKeys); - if (CollUtil.isEmpty(actHiProcinsts)) { - log.warn("当前业务ID:{}查询到流程实例为空!", businessKeys); - return false; - } - List processInstanceIds = StreamUtils.toList(actHiProcinsts, ActHiProcinst::getId); - List list = QueryUtils.taskQuery(processInstanceIds).list(); - List subTasks = StreamUtils.filter(list, e -> StringUtils.isNotBlank(e.getParentTaskId())); - if (CollUtil.isNotEmpty(subTasks)) { - subTasks.forEach(e -> taskService.deleteTask(e.getId())); - } - runtimeService.bulkDeleteProcessInstances(processInstanceIds, LoginHelper.getUserId() + "删除了当前流程申请"); - // 2.删除历史记录 - List historicProcessInstanceList = QueryUtils.hisInstanceQuery(new HashSet<>(processInstanceIds)).list(); - if (ObjectUtil.isNotEmpty(historicProcessInstanceList)) { - historyService.bulkDeleteHistoricProcessInstances(processInstanceIds); - } - wfTaskBackNodeService.deleteByInstanceIds(processInstanceIds); - return true; - } catch (Exception e) { - log.error(e.getMessage(), e); - throw new ServiceException(e.getMessage()); - } - } - - /** - * 已完成的实例 删除程实例,删除历史记录,删除业务与流程关联信息 - * - * @param businessKeys 业务id - */ - @Override - @Transactional(rollbackFor = Exception.class) - public boolean deleteFinishAndHisInstance(List businessKeys) { - try { - List actHiProcinsts = actHiProcinstService.selectByBusinessKeyIn(businessKeys); - if (CollUtil.isEmpty(actHiProcinsts)) { - log.warn("当前业务ID:{}查询到流程实例为空!", businessKeys); - return false; - } - List processInstanceIds = StreamUtils.toList(actHiProcinsts, ActHiProcinst::getId); - historyService.bulkDeleteHistoricProcessInstances(processInstanceIds); - wfTaskBackNodeService.deleteByInstanceIds(processInstanceIds); - return true; - } catch (Exception e) { - log.error(e.getMessage(), e); - throw new ServiceException(e.getMessage()); - } - } - - /** - * 撤销流程申请 - * - * @param businessKey 业务id - */ - @Override - @Transactional(rollbackFor = Exception.class) - public boolean cancelProcessApply(String businessKey) { - try { - ProcessInstance processInstance = QueryUtils.businessKeyQuery(businessKey) - .startedBy(String.valueOf(LoginHelper.getUserId())).singleResult(); - if (ObjectUtil.isNull(processInstance)) { - throw new ServiceException("您不是流程发起人,撤销失败!"); - } - if (processInstance.isSuspended()) { - throw new ServiceException(FlowConstant.MESSAGE_SUSPENDED); - } - String processInstanceId = processInstance.getId(); - BusinessStatusEnum.checkCancelStatus(processInstance.getBusinessStatus()); - List taskList = QueryUtils.taskQuery(processInstanceId).list(); - for (Task task : taskList) { - taskService.setAssignee(task.getId(), null); - taskService.addComment(task.getId(), processInstanceId, TaskStatusEnum.CANCEL.getStatus(), LoginHelper.getLoginUser().getNickname() + ":撤销申请"); - } - HistoricTaskInstance historicTaskInstance = QueryUtils.hisTaskInstanceQuery(processInstanceId).finished().orderByHistoricTaskInstanceEndTime().asc().list().get(0); - List nodeIds = StreamUtils.toList(taskList, Task::getTaskDefinitionKey); - runtimeService.createChangeActivityStateBuilder() - .processInstanceId(processInstanceId) - .moveActivityIdsToSingleActivityId(nodeIds, historicTaskInstance.getTaskDefinitionKey()).changeState(); - Task task = QueryUtils.taskQuery(processInstanceId).list().get(0); - taskService.setAssignee(task.getId(), historicTaskInstance.getAssignee()); - //获取并行网关执行后保留的执行实例数据 - ExecutionChildByExecutionIdCmd childByExecutionIdCmd = new ExecutionChildByExecutionIdCmd(task.getExecutionId()); - List executionEntities = managementService.executeCommand(childByExecutionIdCmd); - //删除流程实例垃圾数据 - for (ExecutionEntity executionEntity : executionEntities) { - DeleteExecutionCmd deleteExecutionCmd = new DeleteExecutionCmd(executionEntity.getId()); - managementService.executeCommand(deleteExecutionCmd); - } - runtimeService.updateBusinessStatus(processInstanceId, BusinessStatusEnum.CANCEL.getStatus()); - //流程作废监听 - flowProcessEventHandler.processHandler(processInstance.getProcessDefinitionKey(), - processInstance.getBusinessKey(), BusinessStatusEnum.CANCEL.getStatus(), false); - return true; - } catch (Exception e) { - log.error("撤销失败:" + e.getMessage(), e); - throw new ServiceException("撤销失败:" + e.getMessage()); - } - } - - /** - * 分页查询当前登录人单据 - * - * @param bo 参数 - */ - @Override - public TableDataInfo getPageByCurrent(ProcessInstanceBo bo, PageQuery pageQuery) { - List list = new ArrayList<>(); - HistoricProcessInstanceQuery query = QueryUtils.hisInstanceQuery(); - query.startedBy(String.valueOf(LoginHelper.getUserId())); - if (StringUtils.isNotBlank(bo.getName())) { - query.processInstanceNameLikeIgnoreCase("%" + bo.getName() + "%"); - } - if (StringUtils.isNotBlank(bo.getKey())) { - query.processDefinitionKey(bo.getKey()); - } - if (StringUtils.isNotBlank(bo.getBusinessKey())) { - query.processInstanceBusinessKey(bo.getBusinessKey()); - } - if (StringUtils.isNotBlank(bo.getCategoryCode())) { - query.processDefinitionCategory(bo.getCategoryCode()); - } - query.orderByProcessInstanceStartTime().desc(); - List historicProcessInstanceList = query.listPage(pageQuery.getFirstNum(), pageQuery.getPageSize()); - List taskVoList = new ArrayList<>(); - if (CollUtil.isNotEmpty(historicProcessInstanceList)) { - List processInstanceIds = StreamUtils.toList(historicProcessInstanceList, HistoricProcessInstance::getId); - List taskList = QueryUtils.taskQuery(processInstanceIds).list(); - for (Task task : taskList) { - taskVoList.add(BeanUtil.toBean(task, TaskVo.class)); - } - } - for (HistoricProcessInstance processInstance : historicProcessInstanceList) { - ProcessInstanceVo processInstanceVo = BeanUtil.toBean(processInstance, ProcessInstanceVo.class); - processInstanceVo.setBusinessStatusName(BusinessStatusEnum.findByStatus(processInstance.getBusinessStatus())); - if (CollUtil.isNotEmpty(taskVoList)) { - List collect = StreamUtils.filter(taskVoList, e -> e.getProcessInstanceId().equals(processInstance.getId())); - processInstanceVo.setTaskVoList(CollUtil.isNotEmpty(collect) ? collect : Collections.emptyList()); - } - list.add(processInstanceVo); - } - if (CollUtil.isNotEmpty(list)) { - List processDefinitionIds = StreamUtils.toList(list, ProcessInstanceVo::getProcessDefinitionId); - List wfNodeConfigVoList = wfNodeConfigService.selectByDefIds(processDefinitionIds); - for (ProcessInstanceVo processInstanceVo : list) { - if (CollUtil.isNotEmpty(wfNodeConfigVoList)) { - wfNodeConfigVoList.stream().filter(e -> e.getDefinitionId().equals(processInstanceVo.getProcessDefinitionId()) && FlowConstant.TRUE.equals(e.getApplyUserTask())).findFirst().ifPresent(processInstanceVo::setWfNodeConfigVo); - } - } - } - long count = query.count(); - TableDataInfo build = TableDataInfo.build(); - build.setRows(list); - build.setTotal(count); - return build; - } - - /** - * 任务催办(给当前任务办理人发送站内信,邮件,短信等) - * - * @param taskUrgingBo 任务催办 - */ - @Override - @Transactional(rollbackFor = Exception.class) - public boolean taskUrging(TaskUrgingBo taskUrgingBo) { - try { - ProcessInstance processInstance = QueryUtils.instanceQuery(taskUrgingBo.getProcessInstanceId()).singleResult(); - if (processInstance == null) { - throw new ServiceException("任务已结束!"); - } - String message = taskUrgingBo.getMessage(); - if (StringUtils.isBlank(message)) { - message = "您的【" + processInstance.getName() + "】单据还未审批,请您及时处理。"; - } - List list = QueryUtils.taskQuery(taskUrgingBo.getProcessInstanceId()).list(); - WorkflowUtils.sendMessage(list, processInstance.getName(), taskUrgingBo.getMessageType(), message, userService); - } catch (ServiceException e) { - throw new ServiceException(e.getMessage()); - } - return true; - } -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActTaskServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActTaskServiceImpl.java deleted file mode 100644 index d9a674a78..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActTaskServiceImpl.java +++ /dev/null @@ -1,861 +0,0 @@ -package org.dromara.workflow.service.impl; - -import cn.hutool.core.bean.BeanUtil; -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.core.util.StrUtil; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.dromara.common.core.domain.dto.RoleDTO; -import org.dromara.common.core.domain.dto.UserDTO; -import org.dromara.common.core.exception.ServiceException; -import org.dromara.common.core.service.OssService; -import org.dromara.common.core.service.UserService; -import org.dromara.common.core.utils.StreamUtils; -import org.dromara.common.core.utils.StringUtils; -import org.dromara.common.mybatis.core.page.PageQuery; -import org.dromara.common.mybatis.core.page.TableDataInfo; -import org.dromara.common.satoken.utils.LoginHelper; -import org.dromara.common.tenant.helper.TenantHelper; -import org.dromara.workflow.common.constant.FlowConstant; -import org.dromara.common.core.enums.BusinessStatusEnum; -import org.dromara.workflow.common.enums.TaskStatusEnum; -import org.dromara.workflow.domain.ActHiTaskinst; -import org.dromara.workflow.domain.WfTaskBackNode; -import org.dromara.workflow.domain.bo.*; -import org.dromara.workflow.domain.vo.*; -import org.dromara.workflow.flowable.cmd.*; -import org.dromara.workflow.flowable.handler.FlowProcessEventHandler; -import org.dromara.workflow.mapper.ActHiTaskinstMapper; -import org.dromara.workflow.mapper.ActTaskMapper; -import org.dromara.workflow.service.IActTaskService; -import org.dromara.workflow.service.IWfDefinitionConfigService; -import org.dromara.workflow.service.IWfNodeConfigService; -import org.dromara.workflow.service.IWfTaskBackNodeService; -import org.dromara.workflow.utils.ModelUtils; -import org.dromara.workflow.utils.QueryUtils; -import org.dromara.workflow.utils.WorkflowUtils; -import org.flowable.common.engine.api.FlowableObjectNotFoundException; -import org.flowable.common.engine.impl.identity.Authentication; -import org.flowable.engine.*; -import org.flowable.engine.history.HistoricProcessInstance; -import org.flowable.engine.history.HistoricProcessInstanceQuery; -import org.flowable.engine.impl.bpmn.behavior.ParallelMultiInstanceBehavior; -import org.flowable.engine.impl.bpmn.behavior.SequentialMultiInstanceBehavior; -import org.flowable.engine.impl.persistence.entity.ExecutionEntity; -import org.flowable.engine.runtime.ProcessInstance; -import org.flowable.identitylink.api.history.HistoricIdentityLink; -import org.flowable.task.api.Task; -import org.flowable.task.api.TaskQuery; -import org.flowable.task.api.history.HistoricTaskInstance; -import org.flowable.task.service.impl.persistence.entity.TaskEntity; -import org.flowable.variable.api.persistence.entity.VariableInstance; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.scheduling.annotation.Async; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.util.*; -import java.util.stream.Collectors; - -import static org.dromara.workflow.common.constant.FlowConstant.*; - -/** - * 任务 服务层实现 - * - * @author may - */ -@Slf4j -@RequiredArgsConstructor -@Service -public class ActTaskServiceImpl implements IActTaskService { - - @Autowired(required = false) - private RuntimeService runtimeService; - @Autowired(required = false) - private TaskService taskService; - @Autowired(required = false) - private HistoryService historyService; - @Autowired(required = false) - private IdentityService identityService; - @Autowired(required = false) - private ManagementService managementService; - private final ActTaskMapper actTaskMapper; - private final IWfTaskBackNodeService wfTaskBackNodeService; - private final ActHiTaskinstMapper actHiTaskinstMapper; - private final IWfNodeConfigService wfNodeConfigService; - private final IWfDefinitionConfigService wfDefinitionConfigService; - private final FlowProcessEventHandler flowProcessEventHandler; - private final UserService userService; - private final OssService ossService; - - /** - * 启动任务 - * - * @param startProcessBo 启动流程参数 - */ - @Override - @Transactional(rollbackFor = Exception.class) - public Map startWorkFlow(StartProcessBo startProcessBo) { - Map map = new HashMap<>(); - if (StringUtils.isBlank(startProcessBo.getBusinessKey())) { - throw new ServiceException("启动工作流时必须包含业务ID"); - } - // 判断当前业务是否启动过流程 - HistoricProcessInstanceQuery query = QueryUtils.hisInstanceQuery(); - HistoricProcessInstance historicProcessInstance = query.processInstanceBusinessKey(startProcessBo.getBusinessKey()).singleResult(); - if (ObjectUtil.isNotEmpty(historicProcessInstance)) { - BusinessStatusEnum.checkStartStatus(historicProcessInstance.getBusinessStatus()); - } - List taskResult = QueryUtils.taskQuery().processInstanceBusinessKey(startProcessBo.getBusinessKey()).list(); - if (CollUtil.isNotEmpty(taskResult)) { - if (CollUtil.isNotEmpty(startProcessBo.getVariables())) { - taskService.setVariables(taskResult.get(0).getId(), startProcessBo.getVariables()); - } - map.put(PROCESS_INSTANCE_ID, taskResult.get(0).getProcessInstanceId()); - map.put("taskId", taskResult.get(0).getId()); - return map; - } - WfDefinitionConfigVo wfDefinitionConfigVo = wfDefinitionConfigService.getByTableNameLastVersion(startProcessBo.getTableName()); - if (wfDefinitionConfigVo == null) { - throw new ServiceException("请到流程定义绑定业务表名与流程KEY!"); - } - // 设置启动人 - identityService.setAuthenticatedUserId(String.valueOf(LoginHelper.getUserId())); - Authentication.setAuthenticatedUserId(String.valueOf(LoginHelper.getUserId())); - // 启动流程实例(提交申请) - Map variables = startProcessBo.getVariables(); - // 启动跳过表达式 - variables.put(FLOWABLE_SKIP_EXPRESSION_ENABLED, true); - // 流程发起人 - variables.put(INITIATOR, (String.valueOf(LoginHelper.getUserId()))); - ProcessInstance pi; - try { - if (TenantHelper.isEnable()) { - pi = runtimeService.startProcessInstanceByKeyAndTenantId(wfDefinitionConfigVo.getProcessKey(), startProcessBo.getBusinessKey(), variables, TenantHelper.getTenantId()); - } else { - pi = runtimeService.startProcessInstanceByKey(wfDefinitionConfigVo.getProcessKey(), startProcessBo.getBusinessKey(), variables); - } - } catch (FlowableObjectNotFoundException e) { - throw new ServiceException("找不到当前【" + wfDefinitionConfigVo.getProcessKey() + "】流程定义!"); - } - // 将流程定义名称 作为 流程实例名称 - runtimeService.setProcessInstanceName(pi.getProcessInstanceId(), pi.getProcessDefinitionName()); - // 申请人执行流程 - List taskList = QueryUtils.taskQuery(pi.getId()).list(); - if (taskList.size() > 1) { - throw new ServiceException("请检查流程第一个环节是否为申请人!"); - } - - runtimeService.updateBusinessStatus(pi.getProcessInstanceId(), BusinessStatusEnum.DRAFT.getStatus()); - taskService.setAssignee(taskList.get(0).getId(), LoginHelper.getUserId().toString()); - taskService.setVariable(taskList.get(0).getId(), PROCESS_INSTANCE_ID, pi.getProcessInstanceId()); - taskService.setVariable(taskList.get(0).getId(), BUSINESS_KEY, pi.getBusinessKey()); - map.put("processInstanceId", pi.getProcessInstanceId()); - map.put("taskId", taskList.get(0).getId()); - return map; - } - - /** - * 办理任务 - * - * @param completeTaskBo 办理任务参数 - */ - @Override - @Transactional(rollbackFor = Exception.class) - public boolean completeTask(CompleteTaskBo completeTaskBo) { - try { - String userId = String.valueOf(LoginHelper.getUserId()); - Task task = WorkflowUtils.getTaskByCurrentUser(completeTaskBo.getTaskId()); - if (task == null) { - throw new ServiceException(FlowConstant.MESSAGE_CURRENT_TASK_IS_NULL); - } - if (task.isSuspended()) { - throw new ServiceException(FlowConstant.MESSAGE_SUSPENDED); - } - ProcessInstance processInstance = QueryUtils.instanceQuery(task.getProcessInstanceId()).singleResult(); - //办理委托任务 - if (ObjectUtil.isNotEmpty(task.getDelegationState()) && FlowConstant.PENDING.equals(task.getDelegationState().name())) { - taskService.resolveTask(completeTaskBo.getTaskId()); - TaskEntity newTask = WorkflowUtils.createNewTask(task); - taskService.addComment(newTask.getId(), task.getProcessInstanceId(), TaskStatusEnum.PASS.getStatus(), StringUtils.isNotBlank(completeTaskBo.getMessage()) ? completeTaskBo.getMessage() : StrUtil.EMPTY); - taskService.complete(newTask.getId()); - return true; - } - //附件上传 - AttachmentCmd attachmentCmd = new AttachmentCmd(completeTaskBo.getFileId(), task.getId(), task.getProcessInstanceId(), ossService); - managementService.executeCommand(attachmentCmd); - String businessStatus = WorkflowUtils.getBusinessStatus(processInstance.getBusinessKey()); - //流程提交监听 - if (BusinessStatusEnum.DRAFT.getStatus().equals(businessStatus) || BusinessStatusEnum.BACK.getStatus().equals(businessStatus) || BusinessStatusEnum.CANCEL.getStatus().equals(businessStatus)) { - flowProcessEventHandler.processHandler(processInstance.getProcessDefinitionKey(), processInstance.getBusinessKey(), businessStatus, true); - } - runtimeService.updateBusinessStatus(task.getProcessInstanceId(), BusinessStatusEnum.WAITING.getStatus()); - //办理监听 - flowProcessEventHandler.processTaskHandler(processInstance.getProcessDefinitionKey(), task.getTaskDefinitionKey(), - task.getId(), processInstance.getBusinessKey()); - //办理意见 - taskService.addComment(completeTaskBo.getTaskId(), task.getProcessInstanceId(), TaskStatusEnum.PASS.getStatus(), StringUtils.isBlank(completeTaskBo.getMessage()) ? "同意" : completeTaskBo.getMessage()); - //办理任务 - taskService.setAssignee(task.getId(), userId); - if (CollUtil.isNotEmpty(completeTaskBo.getVariables())) { - taskService.complete(completeTaskBo.getTaskId(), completeTaskBo.getVariables()); - } else { - taskService.complete(completeTaskBo.getTaskId()); - } - //记录执行过的流程任务节点 - wfTaskBackNodeService.recordExecuteNode(task); - ProcessInstance pi = QueryUtils.instanceQuery(task.getProcessInstanceId()).singleResult(); - if (pi == null) { - UpdateBusinessStatusCmd updateBusinessStatusCmd = new UpdateBusinessStatusCmd(task.getProcessInstanceId(), BusinessStatusEnum.FINISH.getStatus()); - managementService.executeCommand(updateBusinessStatusCmd); - flowProcessEventHandler.processHandler(processInstance.getProcessDefinitionKey(), processInstance.getBusinessKey(), - BusinessStatusEnum.FINISH.getStatus(), false); - } else { - List list = QueryUtils.taskQuery(task.getProcessInstanceId()).list(); - for (Task t : list) { - if (ModelUtils.isUserTask(t.getProcessDefinitionId(), t.getTaskDefinitionKey())) { - List links = historyService.getHistoricIdentityLinksForTask(t.getId()); - if (CollUtil.isEmpty(links) && StringUtils.isBlank(t.getAssignee())) { - throw new ServiceException("下一节点【" + t.getName() + "】没有办理人!"); - } - } - } - - if (CollUtil.isNotEmpty(list) && CollUtil.isNotEmpty(completeTaskBo.getWfCopyList())) { - TaskEntity newTask = WorkflowUtils.createNewTask(task); - taskService.addComment(newTask.getId(), task.getProcessInstanceId(), TaskStatusEnum.COPY.getStatus(), LoginHelper.getLoginUser().getNickname() + "【抄送】给" + String.join(",", StreamUtils.toList(completeTaskBo.getWfCopyList(), WfCopy::getUserName))); - taskService.complete(newTask.getId()); - List taskList = QueryUtils.taskQuery(task.getProcessInstanceId()).list(); - WorkflowUtils.createCopyTask(taskList, StreamUtils.toList(completeTaskBo.getWfCopyList(), WfCopy::getUserId)); - } - sendMessage(list, processInstance.getName(), completeTaskBo.getMessageType(), null); - } - return true; - } catch (Exception e) { - log.error(e.getMessage(), e); - throw new ServiceException(e.getMessage()); - } - } - - /** - * 发送消息 - * - * @param list 任务 - * @param name 流程名称 - * @param messageType 消息类型 - * @param message 消息内容,为空则发送默认配置的消息内容 - */ - @Async - public void sendMessage(List list, String name, List messageType, String message) { - WorkflowUtils.sendMessage(list, name, messageType, message, userService); - } - - /** - * 查询当前用户的待办任务 - * - * @param taskBo 参数 - */ - @Override - public TableDataInfo getPageByTaskWait(TaskBo taskBo, PageQuery pageQuery) { - QueryWrapper queryWrapper = new QueryWrapper<>(); - List roles = LoginHelper.getLoginUser().getRoles(); - List roleIds = StreamUtils.toList(roles, e -> String.valueOf(e.getRoleId())); - String userId = String.valueOf(LoginHelper.getUserId()); - queryWrapper.eq("t.business_status_", BusinessStatusEnum.WAITING.getStatus()); - queryWrapper.eq(TenantHelper.isEnable(), "t.tenant_id_", TenantHelper.getTenantId()); - String ids = StreamUtils.join(roleIds, x -> "'" + x + "'"); - queryWrapper.and(w1 -> w1.eq("t.assignee_", userId).or(w2 -> w2.isNull("t.assignee_").apply("exists ( select LINK.ID_ from ACT_RU_IDENTITYLINK LINK where LINK.TASK_ID_ = t.ID_ and LINK.TYPE_ = 'candidate' and (LINK.USER_ID_ = {0} or ( LINK.GROUP_ID_ IN (" + ids + ") ) ))", userId))); - if (StringUtils.isNotBlank(taskBo.getName())) { - queryWrapper.like("t.name_", taskBo.getName()); - } - if (StringUtils.isNotBlank(taskBo.getProcessDefinitionName())) { - queryWrapper.like("t.processDefinitionName", taskBo.getProcessDefinitionName()); - } - if (StringUtils.isNotBlank(taskBo.getProcessDefinitionKey())) { - queryWrapper.eq("t.processDefinitionKey", taskBo.getProcessDefinitionKey()); - } - queryWrapper.orderByDesc("t.CREATE_TIME_"); - Page page = actTaskMapper.getTaskWaitByPage(pageQuery.build(), queryWrapper); - - List taskList = page.getRecords(); - if (CollUtil.isNotEmpty(taskList)) { - List processDefinitionIds = StreamUtils.toList(taskList, TaskVo::getProcessDefinitionId); - List wfNodeConfigVoList = wfNodeConfigService.selectByDefIds(processDefinitionIds); - for (TaskVo task : taskList) { - task.setBusinessStatusName(BusinessStatusEnum.findByStatus(task.getBusinessStatus())); - task.setParticipantVo(WorkflowUtils.getCurrentTaskParticipant(task.getId(), userService)); - task.setMultiInstance(WorkflowUtils.isMultiInstance(task.getProcessDefinitionId(), task.getTaskDefinitionKey()) != null); - if (CollUtil.isNotEmpty(wfNodeConfigVoList)) { - wfNodeConfigVoList.stream().filter(e -> e.getDefinitionId().equals(task.getProcessDefinitionId()) && FlowConstant.TRUE.equals(e.getApplyUserTask())).findFirst().ifPresent(task::setWfNodeConfigVo); - wfNodeConfigVoList.stream().filter(e -> e.getDefinitionId().equals(task.getProcessDefinitionId()) && e.getNodeId().equals(task.getTaskDefinitionKey()) && FlowConstant.FALSE.equals(e.getApplyUserTask())).findFirst().ifPresent(task::setWfNodeConfigVo); - } - } - } - return TableDataInfo.build(page); - } - - /** - * 查询当前租户所有待办任务 - * - * @param taskBo 参数 - */ - @Override - public TableDataInfo getPageByAllTaskWait(TaskBo taskBo, PageQuery pageQuery) { - TaskQuery query = QueryUtils.taskQuery(); - if (StringUtils.isNotBlank(taskBo.getName())) { - query.taskNameLike("%" + taskBo.getName() + "%"); - } - if (StringUtils.isNotBlank(taskBo.getProcessDefinitionName())) { - query.processDefinitionNameLike("%" + taskBo.getProcessDefinitionName() + "%"); - } - if (StringUtils.isNotBlank(taskBo.getProcessDefinitionKey())) { - query.processDefinitionKey(taskBo.getProcessDefinitionKey()); - } - query.orderByTaskCreateTime().desc(); - List taskList = query.listPage(pageQuery.getFirstNum(), pageQuery.getPageSize()); - List processInstanceList = null; - if (CollUtil.isNotEmpty(taskList)) { - Set processInstanceIds = StreamUtils.toSet(taskList, Task::getProcessInstanceId); - processInstanceList = QueryUtils.instanceQuery(processInstanceIds).list(); - } - List list = new ArrayList<>(); - if (CollUtil.isNotEmpty(taskList)) { - List processDefinitionIds = StreamUtils.toList(taskList, Task::getProcessDefinitionId); - List wfNodeConfigVoList = wfNodeConfigService.selectByDefIds(processDefinitionIds); - for (Task task : taskList) { - TaskVo taskVo = BeanUtil.toBean(task, TaskVo.class); - if (CollUtil.isNotEmpty(processInstanceList)) { - processInstanceList.stream().filter(e -> e.getId().equals(task.getProcessInstanceId())).findFirst().ifPresent(e -> { - taskVo.setBusinessStatus(e.getBusinessStatus()); - taskVo.setBusinessStatusName(BusinessStatusEnum.findByStatus(taskVo.getBusinessStatus())); - taskVo.setProcessDefinitionKey(e.getProcessDefinitionKey()); - taskVo.setProcessDefinitionName(e.getProcessDefinitionName()); - taskVo.setProcessDefinitionVersion(e.getProcessDefinitionVersion()); - taskVo.setBusinessKey(e.getBusinessKey()); - }); - } - taskVo.setAssignee(StringUtils.isNotBlank(task.getAssignee()) ? Long.valueOf(task.getAssignee()) : null); - taskVo.setParticipantVo(WorkflowUtils.getCurrentTaskParticipant(task.getId(), userService)); - taskVo.setMultiInstance(WorkflowUtils.isMultiInstance(task.getProcessDefinitionId(), task.getTaskDefinitionKey()) != null); - if (CollUtil.isNotEmpty(wfNodeConfigVoList)) { - wfNodeConfigVoList.stream().filter(e -> e.getDefinitionId().equals(task.getProcessDefinitionId()) && FlowConstant.TRUE.equals(e.getApplyUserTask())).findFirst().ifPresent(taskVo::setWfNodeConfigVo); - wfNodeConfigVoList.stream().filter(e -> e.getDefinitionId().equals(task.getProcessDefinitionId()) && e.getNodeId().equals(task.getTaskDefinitionKey()) && FlowConstant.FALSE.equals(e.getApplyUserTask())).findFirst().ifPresent(taskVo::setWfNodeConfigVo); - } - list.add(taskVo); - } - } - long count = query.count(); - TableDataInfo build = TableDataInfo.build(); - build.setRows(list); - build.setTotal(count); - return build; - } - - /** - * 查询当前用户的已办任务 - * - * @param taskBo 参数 - */ - @Override - public TableDataInfo getPageByTaskFinish(TaskBo taskBo, PageQuery pageQuery) { - String userId = String.valueOf(LoginHelper.getUserId()); - QueryWrapper queryWrapper = new QueryWrapper<>(); - queryWrapper.like(StringUtils.isNotBlank(taskBo.getName()), "t.name_", taskBo.getName()); - queryWrapper.like(StringUtils.isNotBlank(taskBo.getProcessDefinitionName()), "t.processDefinitionName", taskBo.getProcessDefinitionName()); - queryWrapper.eq(StringUtils.isNotBlank(taskBo.getProcessDefinitionKey()), "t.processDefinitionKey", taskBo.getProcessDefinitionKey()); - queryWrapper.eq("t.assignee_", userId); - queryWrapper.orderByDesc("t.START_TIME_"); - Page page = actTaskMapper.getTaskFinishByPage(pageQuery.build(), queryWrapper); - - List taskList = page.getRecords(); - if (CollUtil.isNotEmpty(taskList)) { - List processDefinitionIds = StreamUtils.toList(taskList, TaskVo::getProcessDefinitionId); - List wfNodeConfigVoList = wfNodeConfigService.selectByDefIds(processDefinitionIds); - for (TaskVo task : taskList) { - task.setBusinessStatusName(BusinessStatusEnum.findByStatus(task.getBusinessStatus())); - if (CollUtil.isNotEmpty(wfNodeConfigVoList)) { - wfNodeConfigVoList.stream().filter(e -> e.getDefinitionId().equals(task.getProcessDefinitionId()) && FlowConstant.TRUE.equals(e.getApplyUserTask())).findFirst().ifPresent(task::setWfNodeConfigVo); - wfNodeConfigVoList.stream().filter(e -> e.getDefinitionId().equals(task.getProcessDefinitionId()) && e.getNodeId().equals(task.getTaskDefinitionKey()) && FlowConstant.FALSE.equals(e.getApplyUserTask())).findFirst().ifPresent(task::setWfNodeConfigVo); - } - } - } - return TableDataInfo.build(page); - } - - /** - * 查询当前用户的抄送 - * - * @param taskBo 参数 - */ - @Override - public TableDataInfo getPageByTaskCopy(TaskBo taskBo, PageQuery pageQuery) { - QueryWrapper queryWrapper = new QueryWrapper<>(); - String userId = String.valueOf(LoginHelper.getUserId()); - if (StringUtils.isNotBlank(taskBo.getName())) { - queryWrapper.like("t.name_", taskBo.getName()); - } - if (StringUtils.isNotBlank(taskBo.getProcessDefinitionName())) { - queryWrapper.like("t.processDefinitionName", taskBo.getProcessDefinitionName()); - } - if (StringUtils.isNotBlank(taskBo.getProcessDefinitionKey())) { - queryWrapper.eq("t.processDefinitionKey", taskBo.getProcessDefinitionKey()); - } - queryWrapper.eq("t.assignee_", userId); - queryWrapper.orderByDesc("t.START_TIME_"); - Page page = actTaskMapper.getTaskCopyByPage(pageQuery.build(), queryWrapper); - - List taskList = page.getRecords(); - if (CollUtil.isNotEmpty(taskList)) { - List processDefinitionIds = StreamUtils.toList(taskList, TaskVo::getProcessDefinitionId); - List wfNodeConfigVoList = wfNodeConfigService.selectByDefIds(processDefinitionIds); - for (TaskVo task : taskList) { - task.setBusinessStatusName(BusinessStatusEnum.findByStatus(task.getBusinessStatus())); - if (CollUtil.isNotEmpty(wfNodeConfigVoList)) { - wfNodeConfigVoList.stream().filter(e -> e.getDefinitionId().equals(task.getProcessDefinitionId()) && FlowConstant.TRUE.equals(e.getApplyUserTask())).findFirst().ifPresent(task::setWfNodeConfigVo); - wfNodeConfigVoList.stream().filter(e -> e.getDefinitionId().equals(task.getProcessDefinitionId()) && e.getNodeId().equals(task.getTaskDefinitionKey()) && FlowConstant.FALSE.equals(e.getApplyUserTask())).findFirst().ifPresent(task::setWfNodeConfigVo); - } - } - } - return TableDataInfo.build(page); - } - - /** - * 查询当前租户所有已办任务 - * - * @param taskBo 参数 - */ - @Override - public TableDataInfo getPageByAllTaskFinish(TaskBo taskBo, PageQuery pageQuery) { - QueryWrapper queryWrapper = new QueryWrapper<>(); - queryWrapper.like(StringUtils.isNotBlank(taskBo.getName()), "t.name_", taskBo.getName()); - queryWrapper.like(StringUtils.isNotBlank(taskBo.getProcessDefinitionName()), "t.processDefinitionName", taskBo.getProcessDefinitionName()); - queryWrapper.eq(StringUtils.isNotBlank(taskBo.getProcessDefinitionKey()), "t.processDefinitionKey", taskBo.getProcessDefinitionKey()); - Page page = actTaskMapper.getTaskFinishByPage(pageQuery.build(), queryWrapper); - - List taskList = page.getRecords(); - if (CollUtil.isNotEmpty(taskList)) { - List processDefinitionIds = StreamUtils.toList(taskList, TaskVo::getProcessDefinitionId); - List wfNodeConfigVoList = wfNodeConfigService.selectByDefIds(processDefinitionIds); - for (TaskVo task : taskList) { - task.setBusinessStatusName(BusinessStatusEnum.findByStatus(task.getBusinessStatus())); - if (CollUtil.isNotEmpty(wfNodeConfigVoList)) { - wfNodeConfigVoList.stream().filter(e -> e.getDefinitionId().equals(task.getProcessDefinitionId()) && FlowConstant.TRUE.equals(e.getApplyUserTask())).findFirst().ifPresent(task::setWfNodeConfigVo); - wfNodeConfigVoList.stream().filter(e -> e.getDefinitionId().equals(task.getProcessDefinitionId()) && e.getNodeId().equals(task.getTaskDefinitionKey()) && FlowConstant.FALSE.equals(e.getApplyUserTask())).findFirst().ifPresent(task::setWfNodeConfigVo); - } - } - } - return TableDataInfo.build(page); - } - - /** - * 委派任务 - * - * @param delegateBo 参数 - */ - @Override - @Transactional(rollbackFor = Exception.class) - public boolean delegateTask(DelegateBo delegateBo) { - Task task = WorkflowUtils.getTaskByCurrentUser(delegateBo.getTaskId()); - - if (ObjectUtil.isEmpty(task)) { - throw new ServiceException(FlowConstant.MESSAGE_CURRENT_TASK_IS_NULL); - } - if (task.isSuspended()) { - throw new ServiceException(FlowConstant.MESSAGE_SUSPENDED); - } - try { - TaskEntity newTask = WorkflowUtils.createNewTask(task); - taskService.addComment(newTask.getId(), task.getProcessInstanceId(), TaskStatusEnum.PENDING.getStatus(), "【" + LoginHelper.getLoginUser().getNickname() + "】委派给【" + delegateBo.getNickName() + "】"); - //委托任务 - taskService.delegateTask(delegateBo.getTaskId(), delegateBo.getUserId()); - //办理生成的任务记录 - taskService.complete(newTask.getId()); - return true; - } catch (Exception e) { - log.error(e.getMessage(), e); - throw new ServiceException(e.getMessage()); - } - } - - /** - * 终止任务 - * - * @param terminationBo 参数 - */ - @Override - @Transactional(rollbackFor = Exception.class) - public boolean terminationTask(TerminationBo terminationBo) { - TaskQuery query = QueryUtils.taskQuery(); - Task task = query.taskId(terminationBo.getTaskId()).singleResult(); - - if (ObjectUtil.isEmpty(task)) { - throw new ServiceException(FlowConstant.MESSAGE_CURRENT_TASK_IS_NULL); - } - if (task.isSuspended()) { - throw new ServiceException(FlowConstant.MESSAGE_SUSPENDED); - } - HistoricProcessInstance historicProcessInstance = QueryUtils.hisInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult(); - BusinessStatusEnum.checkInvalidStatus(historicProcessInstance.getBusinessStatus()); - try { - if (StringUtils.isBlank(terminationBo.getComment())) { - terminationBo.setComment(LoginHelper.getLoginUser().getNickname() + "终止了申请"); - } else { - terminationBo.setComment(LoginHelper.getLoginUser().getNickname() + "终止了申请:" + terminationBo.getComment()); - } - taskService.addComment(task.getId(), task.getProcessInstanceId(), TaskStatusEnum.TERMINATION.getStatus(), terminationBo.getComment()); - List list = QueryUtils.taskQuery(task.getProcessInstanceId()).list(); - if (CollUtil.isNotEmpty(list)) { - List subTasks = StreamUtils.filter(list, e -> StringUtils.isNotBlank(e.getParentTaskId())); - if (CollUtil.isNotEmpty(subTasks)) { - subTasks.forEach(e -> taskService.deleteTask(e.getId())); - } - runtimeService.updateBusinessStatus(task.getProcessInstanceId(), BusinessStatusEnum.TERMINATION.getStatus()); - runtimeService.deleteProcessInstance(task.getProcessInstanceId(), StrUtil.EMPTY); - } - //流程终止监听 - flowProcessEventHandler.processHandler(historicProcessInstance.getProcessDefinitionKey(), - historicProcessInstance.getBusinessKey(), BusinessStatusEnum.TERMINATION.getStatus(), false); - return true; - } catch (Exception e) { - throw new ServiceException(e.getMessage()); - } - } - - /** - * 转办任务 - * - * @param transmitBo 参数 - */ - @Override - public boolean transferTask(TransmitBo transmitBo) { - Task task = WorkflowUtils.getTaskByCurrentUser(transmitBo.getTaskId()); - if (ObjectUtil.isEmpty(task)) { - throw new ServiceException(FlowConstant.MESSAGE_CURRENT_TASK_IS_NULL); - } - if (task.isSuspended()) { - throw new ServiceException(FlowConstant.MESSAGE_SUSPENDED); - } - try { - TaskEntity newTask = WorkflowUtils.createNewTask(task); - taskService.addComment(newTask.getId(), task.getProcessInstanceId(), TaskStatusEnum.TRANSFER.getStatus(), StringUtils.isNotBlank(transmitBo.getComment()) ? transmitBo.getComment() : LoginHelper.getUsername() + "转办了任务"); - taskService.complete(newTask.getId()); - taskService.setAssignee(task.getId(), transmitBo.getUserId()); - return true; - } catch (Exception e) { - log.error(e.getMessage(), e); - throw new ServiceException(e.getMessage()); - } - } - - /** - * 会签任务加签 - * - * @param addMultiBo 参数 - */ - @Override - public boolean addMultiInstanceExecution(AddMultiBo addMultiBo) { - TaskQuery taskQuery = QueryUtils.taskQuery(); - taskQuery.taskId(addMultiBo.getTaskId()); - if (!LoginHelper.isSuperAdmin() && !LoginHelper.isTenantAdmin()) { - taskQuery.taskCandidateOrAssigned(String.valueOf(LoginHelper.getUserId())); - } - Task task = taskQuery.singleResult(); - if (ObjectUtil.isEmpty(task)) { - throw new ServiceException(FlowConstant.MESSAGE_CURRENT_TASK_IS_NULL); - } - if (task.isSuspended()) { - throw new ServiceException(FlowConstant.MESSAGE_SUSPENDED); - } - String taskDefinitionKey = task.getTaskDefinitionKey(); - String processInstanceId = task.getProcessInstanceId(); - String processDefinitionId = task.getProcessDefinitionId(); - - try { - MultiInstanceVo multiInstanceVo = WorkflowUtils.isMultiInstance(processDefinitionId, taskDefinitionKey); - if (multiInstanceVo == null) { - throw new ServiceException("当前环节不是会签节点"); - } - if (multiInstanceVo.getType() instanceof ParallelMultiInstanceBehavior) { - for (Long assignee : addMultiBo.getAssignees()) { - runtimeService.addMultiInstanceExecution(taskDefinitionKey, processInstanceId, Collections.singletonMap(multiInstanceVo.getAssignee(), assignee)); - } - } else if (multiInstanceVo.getType() instanceof SequentialMultiInstanceBehavior) { - AddSequenceMultiInstanceCmd addSequenceMultiInstanceCmd = new AddSequenceMultiInstanceCmd(task.getExecutionId(), multiInstanceVo.getAssigneeList(), addMultiBo.getAssignees()); - managementService.executeCommand(addSequenceMultiInstanceCmd); - } - List assigneeNames = addMultiBo.getAssigneeNames(); - String username = LoginHelper.getUsername(); - TaskEntity newTask = WorkflowUtils.createNewTask(task); - taskService.addComment(newTask.getId(), processInstanceId, TaskStatusEnum.SIGN.getStatus(), username + "加签【" + String.join(StringUtils.SEPARATOR, assigneeNames) + "】"); - taskService.complete(newTask.getId()); - return true; - } catch (Exception e) { - log.error(e.getMessage(), e); - throw new ServiceException(e.getMessage()); - } - } - - /** - * 会签任务减签 - * - * @param deleteMultiBo 参数 - */ - @Override - public boolean deleteMultiInstanceExecution(DeleteMultiBo deleteMultiBo) { - TaskQuery taskQuery = QueryUtils.taskQuery(); - taskQuery.taskId(deleteMultiBo.getTaskId()); - if (!LoginHelper.isSuperAdmin() && !LoginHelper.isTenantAdmin()) { - taskQuery.taskCandidateOrAssigned(String.valueOf(LoginHelper.getUserId())); - } - Task task = taskQuery.singleResult(); - if (ObjectUtil.isEmpty(task)) { - throw new ServiceException(FlowConstant.MESSAGE_CURRENT_TASK_IS_NULL); - } - if (task.isSuspended()) { - throw new ServiceException(FlowConstant.MESSAGE_SUSPENDED); - } - String taskDefinitionKey = task.getTaskDefinitionKey(); - String processInstanceId = task.getProcessInstanceId(); - String processDefinitionId = task.getProcessDefinitionId(); - try { - MultiInstanceVo multiInstanceVo = WorkflowUtils.isMultiInstance(processDefinitionId, taskDefinitionKey); - if (multiInstanceVo == null) { - throw new ServiceException("当前环节不是会签节点"); - } - if (multiInstanceVo.getType() instanceof ParallelMultiInstanceBehavior) { - for (String executionId : deleteMultiBo.getExecutionIds()) { - runtimeService.deleteMultiInstanceExecution(executionId, false); - } - for (String taskId : deleteMultiBo.getTaskIds()) { - historyService.deleteHistoricTaskInstance(taskId); - } - } else if (multiInstanceVo.getType() instanceof SequentialMultiInstanceBehavior) { - DeleteSequenceMultiInstanceCmd deleteSequenceMultiInstanceCmd = new DeleteSequenceMultiInstanceCmd(task.getAssignee(), task.getExecutionId(), multiInstanceVo.getAssigneeList(), deleteMultiBo.getAssigneeIds()); - managementService.executeCommand(deleteSequenceMultiInstanceCmd); - } - List assigneeNames = deleteMultiBo.getAssigneeNames(); - String username = LoginHelper.getUsername(); - TaskEntity newTask = WorkflowUtils.createNewTask(task); - taskService.addComment(newTask.getId(), processInstanceId, TaskStatusEnum.SIGN_OFF.getStatus(), username + "减签【" + String.join(StringUtils.SEPARATOR, assigneeNames) + "】"); - taskService.complete(newTask.getId()); - return true; - } catch (Exception e) { - log.error(e.getMessage(), e); - throw new ServiceException(e.getMessage()); - } - } - - /** - * 驳回审批 - * - * @param backProcessBo 参数 - */ - @Override - @Transactional(rollbackFor = Exception.class) - public String backProcess(BackProcessBo backProcessBo) { - String userId = String.valueOf(LoginHelper.getUserId()); - Task task = WorkflowUtils.getTaskByCurrentUser(backProcessBo.getTaskId()); - - if (ObjectUtil.isEmpty(task)) { - throw new ServiceException(FlowConstant.MESSAGE_CURRENT_TASK_IS_NULL); - } - if (task.isSuspended()) { - throw new ServiceException(FlowConstant.MESSAGE_SUSPENDED); - } - try { - String processInstanceId = task.getProcessInstanceId(); - ProcessInstance processInstance = QueryUtils.instanceQuery(task.getProcessInstanceId()).singleResult(); - //获取并行网关执行后保留的执行实例数据 - ExecutionChildByExecutionIdCmd childByExecutionIdCmd = new ExecutionChildByExecutionIdCmd(task.getExecutionId()); - List executionEntities = managementService.executeCommand(childByExecutionIdCmd); - //校验单据 - BusinessStatusEnum.checkBackStatus(processInstance.getBusinessStatus()); - //判断是否有多个任务 - List taskList = QueryUtils.taskQuery(processInstanceId).list(); - String backTaskDefinitionKey = backProcessBo.getTargetActivityId(); - taskService.addComment(task.getId(), processInstanceId, TaskStatusEnum.BACK.getStatus(), StringUtils.isNotBlank(backProcessBo.getMessage()) ? backProcessBo.getMessage() : "退回"); - if (taskList.size() > 1) { - //当前多个任务驳回到单个节点 - runtimeService.createChangeActivityStateBuilder().processInstanceId(processInstanceId).moveActivityIdsToSingleActivityId(taskList.stream().map(Task::getTaskDefinitionKey).distinct().collect(Collectors.toList()), backTaskDefinitionKey).changeState(); - ActHiTaskinst actHiTaskinst = new ActHiTaskinst(); - actHiTaskinst.setAssignee(userId); - actHiTaskinst.setId(task.getId()); - actHiTaskinstMapper.updateById(actHiTaskinst); - } else { - //当前单个节点驳回单个节点 - runtimeService.createChangeActivityStateBuilder().processInstanceId(processInstanceId).moveActivityIdTo(task.getTaskDefinitionKey(), backTaskDefinitionKey).changeState(); - } - //删除并行环节未办理记录 - MultiInstanceVo multiInstance = WorkflowUtils.isMultiInstance(task.getProcessDefinitionId(), task.getTaskDefinitionKey()); - if (multiInstance == null && taskList.size() > 1) { - List tasks = StreamUtils.filter(taskList, e -> !e.getTaskDefinitionKey().equals(task.getTaskDefinitionKey())); - if (CollUtil.isNotEmpty(tasks)) { - actHiTaskinstMapper.deleteByIds(StreamUtils.toList(tasks, Task::getId)); - } - } - - - List instanceList = QueryUtils.hisTaskInstanceQuery(processInstanceId).finished().orderByHistoricTaskInstanceEndTime().desc().list(); - List list = QueryUtils.taskQuery(processInstanceId).list(); - for (Task t : list) { - instanceList.stream().filter(e -> e.getTaskDefinitionKey().equals(t.getTaskDefinitionKey())).findFirst().ifPresent(e -> { - taskService.setAssignee(t.getId(), e.getAssignee()); - }); - } - //发送消息 - String message = "您的【" + processInstance.getName() + "】单据已经被驳回,请您注意查收。"; - sendMessage(list, processInstance.getName(), backProcessBo.getMessageType(), message); - //删除流程实例垃圾数据 - for (ExecutionEntity executionEntity : executionEntities) { - DeleteExecutionCmd deleteExecutionCmd = new DeleteExecutionCmd(executionEntity.getId()); - managementService.executeCommand(deleteExecutionCmd); - } - - WfTaskBackNode wfTaskBackNode = wfTaskBackNodeService.getListByInstanceIdAndNodeId(task.getProcessInstanceId(), backProcessBo.getTargetActivityId()); - if (ObjectUtil.isNotNull(wfTaskBackNode) && wfTaskBackNode.getOrderNo() == 0) { - runtimeService.updateBusinessStatus(processInstanceId, BusinessStatusEnum.BACK.getStatus()); - flowProcessEventHandler.processHandler(processInstance.getProcessDefinitionKey(), - processInstance.getBusinessKey(), BusinessStatusEnum.BACK.getStatus(), false); - } - //删除驳回后的流程节点 - wfTaskBackNodeService.deleteBackTaskNode(processInstanceId, backProcessBo.getTargetActivityId()); - } catch (Exception e) { - log.error(e.getMessage(), e); - throw new ServiceException(e.getMessage()); - } - return task.getProcessInstanceId(); - } - - /** - * 修改任务办理人 - * - * @param taskIds 任务id - * @param userId 办理人id - */ - @Override - @Transactional(rollbackFor = Exception.class) - public boolean updateAssignee(String[] taskIds, String userId) { - try { - List list = QueryUtils.taskQuery().taskIds(Arrays.asList(taskIds)).list(); - for (Task task : list) { - taskService.setAssignee(task.getId(), userId); - } - } catch (Exception e) { - log.error("修改失败:" + e.getMessage(), e); - throw new ServiceException("修改失败:" + e.getMessage()); - } - return true; - } - - /** - * 查询流程变量 - * - * @param taskId 任务id - */ - @Override - public List getInstanceVariable(String taskId) { - List variableVoList = new ArrayList<>(); - Map variableInstances = taskService.getVariableInstances(taskId); - if (CollUtil.isNotEmpty(variableInstances)) { - for (Map.Entry entry : variableInstances.entrySet()) { - VariableVo variableVo = new VariableVo(); - variableVo.setKey(entry.getKey()); - variableVo.setValue(entry.getValue().getValue().toString()); - variableVoList.add(variableVo); - } - } - return variableVoList; - } - - /** - * 查询工作流任务用户选择加签人员 - * - * @param taskId 任务id - * @return - */ - @Override - @SuppressWarnings("unchecked") - public String getTaskUserIdsByAddMultiInstance(String taskId) { - Task task = QueryUtils.taskQuery().taskId(taskId).singleResult(); - if (task == null) { - throw new ServiceException("任务不存在"); - } - MultiInstanceVo multiInstance = WorkflowUtils.isMultiInstance(task.getProcessDefinitionId(), task.getTaskDefinitionKey()); - if (multiInstance == null) { - return ""; - } - List userIds; - if (multiInstance.getType() instanceof SequentialMultiInstanceBehavior) { - userIds = (List) runtimeService.getVariable(task.getExecutionId(), multiInstance.getAssigneeList()); - } else { - List list = QueryUtils.taskQuery(task.getProcessInstanceId()).list(); - userIds = StreamUtils.toList(list, e -> Long.valueOf(e.getAssignee())); - } - return StringUtils.join(userIds, StringUtils.SEPARATOR); - } - - /** - * 查询工作流选择减签人员 - * - * @param taskId 任务id 任务id - */ - @Override - @SuppressWarnings("unchecked") - public List getListByDeleteMultiInstance(String taskId) { - Task task = QueryUtils.taskQuery().taskId(taskId).singleResult(); - List taskList = QueryUtils.taskQuery(task.getProcessInstanceId()).list(); - MultiInstanceVo multiInstance = WorkflowUtils.isMultiInstance(task.getProcessDefinitionId(), task.getTaskDefinitionKey()); - List taskListVo = new ArrayList<>(); - if (multiInstance == null) { - return List.of(); - } - List assigneeList = new ArrayList<>(); - if (multiInstance.getType() instanceof SequentialMultiInstanceBehavior) { - List variable = (List) runtimeService.getVariable(task.getExecutionId(), multiInstance.getAssigneeList()); - for (Object o : variable) { - assigneeList.add(Long.valueOf(o.toString())); - } - } - - if (multiInstance.getType() instanceof SequentialMultiInstanceBehavior) { - List userIds = StreamUtils.filter(assigneeList, e -> !String.valueOf(e).equals(task.getAssignee())); - List userList = userService.selectListByIds(userIds); - for (Long userId : userIds) { - TaskVo taskVo = new TaskVo(); - taskVo.setId("串行会签"); - taskVo.setExecutionId("串行会签"); - taskVo.setProcessInstanceId(task.getProcessInstanceId()); - taskVo.setName(task.getName()); - taskVo.setAssignee(userId); - if (CollUtil.isNotEmpty(userList)) { - userList.stream().filter(u -> u.getUserId().toString().equals(userId.toString())).findFirst().ifPresent(u -> taskVo.setAssigneeName(u.getNickName())); - } - taskListVo.add(taskVo); - } - return taskListVo; - } else if (multiInstance.getType() instanceof ParallelMultiInstanceBehavior) { - List tasks = StreamUtils.filter(taskList, e -> StringUtils.isBlank(e.getParentTaskId()) && !e.getExecutionId().equals(task.getExecutionId()) && e.getTaskDefinitionKey().equals(task.getTaskDefinitionKey())); - if (CollUtil.isNotEmpty(tasks)) { - List userIds = StreamUtils.toList(tasks, e -> Long.valueOf(e.getAssignee())); - List userList = userService.selectListByIds(userIds); - for (Task t : tasks) { - TaskVo taskVo = new TaskVo(); - taskVo.setId(t.getId()); - taskVo.setExecutionId(t.getExecutionId()); - taskVo.setProcessInstanceId(t.getProcessInstanceId()); - taskVo.setName(t.getName()); - taskVo.setAssignee(Long.valueOf(t.getAssignee())); - if (CollUtil.isNotEmpty(userList)) { - userList.stream().filter(u -> u.getUserId().toString().equals(t.getAssignee())).findFirst().ifPresent(e -> taskVo.setAssigneeName(e.getNickName())); - } - taskListVo.add(taskVo); - } - return taskListVo; - } - } - return List.of(); - } -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/CategoryNameTranslationImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/CategoryNameTranslationImpl.java new file mode 100644 index 000000000..4adbadaf7 --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/CategoryNameTranslationImpl.java @@ -0,0 +1,31 @@ +package org.dromara.workflow.service.impl; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.dromara.common.translation.annotation.TranslationType; +import org.dromara.common.translation.core.TranslationInterface; +import org.dromara.workflow.common.constant.FlowConstant; +import org.dromara.workflow.service.IFlwCategoryService; +import org.springframework.stereotype.Service; + +/** + * 流程分类名称翻译实现 + * + * @author AprilWind + */ +@Slf4j +@RequiredArgsConstructor +@Service +@TranslationType(type = FlowConstant.CATEGORY_ID_TO_NAME) +public class CategoryNameTranslationImpl implements TranslationInterface { + + private final IFlwCategoryService flwCategoryService; + + @Override + public String translation(Object key, String other) { + if (key instanceof String categoryId) { + return flwCategoryService.selectCategoryNameById(categoryId); + } + return null; + } +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwCategoryServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwCategoryServiceImpl.java new file mode 100644 index 000000000..0a5c0bb54 --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwCategoryServiceImpl.java @@ -0,0 +1,267 @@ +package org.dromara.workflow.service.impl; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.lang.tree.Tree; +import cn.hutool.core.util.ObjectUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import lombok.RequiredArgsConstructor; +import org.dromara.common.core.constant.SystemConstants; +import org.dromara.common.core.exception.ServiceException; +import org.dromara.common.core.utils.*; +import org.dromara.common.mybatis.helper.DataBaseHelper; +import org.dromara.common.satoken.utils.LoginHelper; +import org.dromara.warm.flow.core.service.DefService; +import org.dromara.warm.flow.orm.entity.FlowDefinition; +import org.dromara.workflow.common.constant.FlowConstant; +import org.dromara.workflow.domain.FlowCategory; +import org.dromara.workflow.domain.bo.FlowCategoryBo; +import org.dromara.workflow.domain.vo.FlowCategoryVo; +import org.dromara.workflow.mapper.FlwCategoryMapper; +import org.dromara.workflow.service.IFlwCategoryService; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; + +/** + * 流程分类Service业务层处理 + * + * @author may + */ +@RequiredArgsConstructor +@Service +public class FlwCategoryServiceImpl implements IFlwCategoryService { + + private final FlwCategoryMapper baseMapper; + private final DefService defService; + + /** + * 查询流程分类 + * + * @param categoryId 主键 + * @return 流程分类 + */ + @Override + public FlowCategoryVo queryById(Long categoryId) { + FlowCategoryVo category = baseMapper.selectVoById(categoryId); + if (ObjectUtil.isNull(category)) { + return null; + } + FlowCategoryVo parentCategory = baseMapper.selectVoOne(new LambdaQueryWrapper() + .select(FlowCategory::getCategoryName).eq(FlowCategory::getCategoryId, category.getParentId())); + category.setParentName(ObjectUtils.notNullGetter(parentCategory, FlowCategoryVo::getCategoryName)); + return category; + } + + /** + * 根据流程分类ID查询流程分类名称 + * + * @param categoryId 流程分类ID + * @return 流程分类名称 + */ + @Cacheable(cacheNames = FlowConstant.FLOW_CATEGORY_NAME, key = "#categoryId") + @Override + public String selectCategoryNameById(String categoryId) { + if (StringUtils.isBlank(categoryId)) { + return null; + } + FlowCategory category = baseMapper.selectOne(new LambdaQueryWrapper() + .select(FlowCategory::getCategoryName).eq(FlowCategory::getCategoryId, categoryId)); + return ObjectUtils.notNullGetter(category, FlowCategory::getCategoryName); + } + + /** + * 查询符合条件的流程分类列表 + * + * @param bo 查询条件 + * @return 流程分类列表 + */ + @Override + public List queryList(FlowCategoryBo bo) { + LambdaQueryWrapper lqw = buildQueryWrapper(bo); + return baseMapper.selectVoList(lqw); + } + + /** + * 查询流程分类树结构信息 + * + * @param category 流程分类信息 + * @return 流程分类树信息集合 + */ + @Override + public List> selectCategoryTreeList(FlowCategoryBo category) { + LambdaQueryWrapper lqw = buildQueryWrapper(category); + List categorys = baseMapper.selectVoList(lqw); + if (CollUtil.isEmpty(categorys)) { + return CollUtil.newArrayList(); + } + // 获取当前列表中每一个节点的parentId,然后在列表中查找是否有id与其parentId对应,若无对应,则表明此时节点列表中,该节点在当前列表中属于顶级节点 + List> treeList = CollUtil.newArrayList(); + for (FlowCategoryVo d : categorys) { + Long parentId = d.getParentId(); + FlowCategoryVo categoryVo = StreamUtils.findFirst(categorys, it -> it.getCategoryId().longValue() == parentId); + if (ObjectUtil.isNull(categoryVo)) { + List> trees = TreeBuildUtils.build(categorys, parentId, (dept, tree) -> + tree.setId(dept.getCategoryId()) + .setParentId(dept.getParentId()) + .setName(dept.getCategoryName()) + .setWeight(dept.getOrderNum())); + Tree tree = StreamUtils.findFirst(trees, it -> it.getId().longValue() == d.getCategoryId()); + treeList.add(tree); + } + } + return treeList; + } + + /** + * 校验流程分类是否有数据权限 + * + * @param categoryId 流程分类ID + */ + @Override + public void checkCategoryDataScope(Long categoryId) { + if (ObjectUtil.isNull(categoryId)) { + return; + } + if (LoginHelper.isSuperAdmin()) { + return; + } + if (baseMapper.countCategoryById(categoryId) == 0) { + throw new ServiceException("没有权限访问流程分类数据!"); + } + } + + /** + * 校验流程分类名称是否唯一 + * + * @param category 流程分类信息 + * @return 结果 + */ + @Override + public boolean checkCategoryNameUnique(FlowCategoryBo category) { + boolean exist = baseMapper.exists(new LambdaQueryWrapper() + .eq(FlowCategory::getCategoryName, category.getCategoryName()) + .eq(FlowCategory::getParentId, category.getParentId()) + .ne(ObjectUtil.isNotNull(category.getCategoryId()), FlowCategory::getCategoryId, category.getCategoryId())); + return !exist; + } + + /** + * 查询流程分类是否存在流程定义 + * + * @param categoryId 流程分类ID + * @return 结果 true 存在 false 不存在 + */ + @Override + public boolean checkCategoryExistDefinition(Long categoryId) { + FlowDefinition definition = new FlowDefinition(); + definition.setCategory(categoryId.toString()); + return defService.exists(definition); + } + + /** + * 是否存在流程分类子节点 + * + * @param categoryId 流程分类ID + * @return 结果 + */ + @Override + public boolean hasChildByCategoryId(Long categoryId) { + return baseMapper.exists(new LambdaQueryWrapper() + .eq(FlowCategory::getParentId, categoryId)); + } + + private LambdaQueryWrapper buildQueryWrapper(FlowCategoryBo bo) { + LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); + lqw.eq(FlowCategory::getDelFlag, SystemConstants.NORMAL); + lqw.eq(ObjectUtil.isNotNull(bo.getCategoryId()), FlowCategory::getCategoryId, bo.getCategoryId()); + lqw.eq(ObjectUtil.isNotNull(bo.getParentId()), FlowCategory::getParentId, bo.getParentId()); + lqw.like(StringUtils.isNotBlank(bo.getCategoryName()), FlowCategory::getCategoryName, bo.getCategoryName()); + lqw.orderByAsc(FlowCategory::getAncestors); + lqw.orderByAsc(FlowCategory::getParentId); + lqw.orderByAsc(FlowCategory::getOrderNum); + lqw.orderByAsc(FlowCategory::getCategoryId); + return lqw; + } + + /** + * 新增流程分类 + * + * @param bo 流程分类 + * @return 是否新增成功 + */ + @Override + public int insertByBo(FlowCategoryBo bo) { + FlowCategory info = baseMapper.selectById(bo.getParentId()); + FlowCategory category = MapstructUtils.convert(bo, FlowCategory.class); + category.setAncestors(info.getAncestors() + StringUtils.SEPARATOR + category.getParentId()); + return baseMapper.insert(category); + } + + /** + * 修改流程分类 + * + * @param bo 流程分类 + * @return 是否修改成功 + */ + @CacheEvict(cacheNames = FlowConstant.FLOW_CATEGORY_NAME, key = "#bo.categoryId") + @Override + public int updateByBo(FlowCategoryBo bo) { + FlowCategory category = MapstructUtils.convert(bo, FlowCategory.class); + FlowCategory oldCategory = baseMapper.selectById(category.getCategoryId()); + if (ObjectUtil.isNull(oldCategory)) { + throw new ServiceException("流程分类不存在,无法修改"); + } + if (!oldCategory.getParentId().equals(category.getParentId())) { + // 如果是新父流程分类 则校验是否具有新父流程分类权限 避免越权 + this.checkCategoryDataScope(category.getParentId()); + FlowCategory newParentCategory = baseMapper.selectById(category.getParentId()); + if (ObjectUtil.isNotNull(newParentCategory)) { + String newAncestors = newParentCategory.getAncestors() + StringUtils.SEPARATOR + newParentCategory.getCategoryId(); + String oldAncestors = oldCategory.getAncestors(); + category.setAncestors(newAncestors); + updateCategoryChildren(category.getCategoryId(), newAncestors, oldAncestors); + } + } else { + category.setAncestors(oldCategory.getAncestors()); + } + return baseMapper.updateById(category); + } + + /** + * 修改子元素关系 + * + * @param categoryId 被修改的流程分类ID + * @param newAncestors 新的父ID集合 + * @param oldAncestors 旧的父ID集合 + */ + private void updateCategoryChildren(Long categoryId, String newAncestors, String oldAncestors) { + List children = baseMapper.selectList(new LambdaQueryWrapper() + .apply(DataBaseHelper.findInSet(categoryId, "ancestors"))); + List list = new ArrayList<>(); + for (FlowCategory child : children) { + FlowCategory category = new FlowCategory(); + category.setCategoryId(child.getCategoryId()); + category.setAncestors(child.getAncestors().replaceFirst(oldAncestors, newAncestors)); + list.add(category); + } + if (CollUtil.isNotEmpty(list)) { + baseMapper.updateBatchById(list); + } + } + + /** + * 删除流程分类信息 + * + * @param categoryId 主键 + * @return 是否删除成功 + */ + @CacheEvict(cacheNames = FlowConstant.FLOW_CATEGORY_NAME, key = "#categoryId") + @Override + public int deleteWithValidById(Long categoryId) { + return baseMapper.deleteById(categoryId); + } +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwDefinitionServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwDefinitionServiceImpl.java new file mode 100644 index 000000000..baec223fe --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwDefinitionServiceImpl.java @@ -0,0 +1,275 @@ +package org.dromara.workflow.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.convert.Convert; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.dom4j.Document; +import org.dom4j.io.OutputFormat; +import org.dom4j.io.XMLWriter; +import org.dromara.common.core.exception.ServiceException; +import org.dromara.common.core.utils.StreamUtils; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.mybatis.core.page.PageQuery; +import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.warm.flow.core.dto.FlowCombine; +import org.dromara.warm.flow.core.entity.Definition; +import org.dromara.warm.flow.core.enums.NodeType; +import org.dromara.warm.flow.core.enums.PublishStatus; +import org.dromara.warm.flow.core.service.DefService; +import org.dromara.warm.flow.orm.entity.FlowDefinition; +import org.dromara.warm.flow.orm.entity.FlowHisTask; +import org.dromara.warm.flow.orm.entity.FlowNode; +import org.dromara.warm.flow.orm.entity.FlowSkip; +import org.dromara.warm.flow.orm.mapper.FlowDefinitionMapper; +import org.dromara.warm.flow.orm.mapper.FlowHisTaskMapper; +import org.dromara.warm.flow.orm.mapper.FlowNodeMapper; +import org.dromara.warm.flow.orm.mapper.FlowSkipMapper; +import org.dromara.workflow.common.constant.FlowConstant; +import org.dromara.workflow.domain.FlowCategory; +import org.dromara.workflow.domain.vo.FlowDefinitionVo; +import org.dromara.workflow.mapper.FlwCategoryMapper; +import org.dromara.workflow.service.IFlwDefinitionService; +import org.dromara.workflow.utils.WorkflowUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static org.dromara.common.core.constant.TenantConstants.DEFAULT_TENANT_ID; + +/** + * 流程定义 服务层实现 + * + * @author may + */ +@Slf4j +@RequiredArgsConstructor +@Service +public class FlwDefinitionServiceImpl implements IFlwDefinitionService { + + private final DefService defService; + private final FlowDefinitionMapper flowDefinitionMapper; + private final FlowHisTaskMapper flowHisTaskMapper; + private final FlwCategoryMapper flwCategoryMapper; + private final FlowNodeMapper flowNodeMapper; + private final FlowSkipMapper flowSkipMapper; + + /** + * 查询流程定义列表 + * + * @param flowDefinition 流程定义信息 + * @param pageQuery 分页 + * @return 返回分页列表 + */ + @Override + public TableDataInfo queryList(FlowDefinition flowDefinition, PageQuery pageQuery) { + LambdaQueryWrapper wrapper = buildQueryWrapper(flowDefinition); + wrapper.eq(FlowDefinition::getIsPublish, PublishStatus.PUBLISHED.getKey()); + Page page = flowDefinitionMapper.selectPage(pageQuery.build(), wrapper); + TableDataInfo build = TableDataInfo.build(); + build.setRows(BeanUtil.copyToList(page.getRecords(), FlowDefinitionVo.class)); + build.setTotal(page.getTotal()); + return build; + } + + /** + * 查询未发布的流程定义列表 + * + * @param flowDefinition 流程定义信息 + * @param pageQuery 分页 + * @return 返回分页列表 + */ + @Override + public TableDataInfo unPublishList(FlowDefinition flowDefinition, PageQuery pageQuery) { + LambdaQueryWrapper wrapper = buildQueryWrapper(flowDefinition); + wrapper.in(FlowDefinition::getIsPublish, Arrays.asList(PublishStatus.UNPUBLISHED.getKey(), PublishStatus.EXPIRED.getKey())); + Page page = flowDefinitionMapper.selectPage(pageQuery.build(), wrapper); + TableDataInfo build = TableDataInfo.build(); + build.setRows(BeanUtil.copyToList(page.getRecords(), FlowDefinitionVo.class)); + build.setTotal(page.getTotal()); + return build; + } + + private LambdaQueryWrapper buildQueryWrapper(FlowDefinition flowDefinition) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(); + wrapper.like(StringUtils.isNotBlank(flowDefinition.getFlowCode()), FlowDefinition::getFlowCode, flowDefinition.getFlowCode()); + wrapper.like(StringUtils.isNotBlank(flowDefinition.getFlowName()), FlowDefinition::getFlowName, flowDefinition.getFlowName()); + if (StringUtils.isNotBlank(flowDefinition.getCategory())) { + List categoryIds = flwCategoryMapper.selectCategoryIdsByParentId(Convert.toLong(flowDefinition.getCategory())); + wrapper.in(FlowDefinition::getCategory, categoryIds); + } + wrapper.orderByDesc(FlowDefinition::getCreateTime); + return wrapper; + } + + /** + * 发布流程定义 + * + * @param id 流程定义id + */ + @Override + public boolean publish(Long id) { + List flowNodes = flowNodeMapper.selectList(new LambdaQueryWrapper().eq(FlowNode::getDefinitionId, id)); + List errorMsg = new ArrayList<>(); + if (CollUtil.isNotEmpty(flowNodes)) { + for (FlowNode flowNode : flowNodes) { + String applyNodeCode = WorkflowUtils.applyNodeCode(id); + if (StringUtils.isBlank(flowNode.getPermissionFlag()) && !applyNodeCode.equals(flowNode.getNodeCode()) && NodeType.BETWEEN.getKey().equals(flowNode.getNodeType())) { + errorMsg.add(flowNode.getNodeName()); + } + } + if (CollUtil.isNotEmpty(errorMsg)) { + throw new ServiceException("节点【" + StringUtils.join(errorMsg, ",") + "】未配置办理人!"); + } + } + return defService.publish(id); + } + + /** + * 导入流程定义 + * + * @param file 文件 + */ + @Override + public boolean importXml(MultipartFile file, String category) { + try { + FlowCombine combine = defService.readXml(file.getInputStream()); + // 流程定义 + Definition definition = combine.getDefinition(); + definition.setCategory(category); + defService.importFlow(combine); + } catch (Exception e) { + log.error("导入流程定义错误: {}", e.getMessage(), e); + throw new RuntimeException(e); + } + return true; + } + + /** + * 导出流程定义 + * + * @param id 流程定义id + * @param response 响应 + * @throws IOException 异常 + */ + @Override + public void exportDef(Long id, HttpServletResponse response) throws IOException { + Document document = defService.exportXml(id); + // 设置生成xml的格式 + OutputFormat of = OutputFormat.createPrettyPrint(); + // 设置编码格式 + of.setEncoding("UTF-8"); + of.setIndent(true); + of.setIndent(" "); + of.setNewlines(true); + + // 创建一个xml文档编辑器 + XMLWriter writer = new XMLWriter(response.getOutputStream(), of); + writer.setEscapeText(false); + response.reset(); + response.setCharacterEncoding("UTF-8"); + response.setContentType("application/x-msdownload"); + response.setHeader("Content-Disposition", "attachment;"); + writer.write(document); + writer.close(); + } + + /** + * 删除流程定义 + * + * @param ids 流程定义id + */ + @Override + @Transactional(rollbackFor = Exception.class) + public boolean removeDef(List ids) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(); + wrapper.in(FlowHisTask::getDefinitionId, ids); + List flowHisTasks = flowHisTaskMapper.selectList(wrapper); + if (CollUtil.isNotEmpty(flowHisTasks)) { + List flowDefinitions = flowDefinitionMapper.selectByIds(StreamUtils.toList(flowHisTasks, FlowHisTask::getDefinitionId)); + if (CollUtil.isNotEmpty(flowDefinitions)) { + String join = StreamUtils.join(flowDefinitions, FlowDefinition::getFlowCode); + log.error("流程定义【{}】已被使用不可被删除!", join); + throw new ServiceException("流程定义【" + join + "】已被使用不可被删除!"); + } + } + try { + defService.removeDef(ids); + } catch (Exception e) { + log.error("Error removing flow definitions: {}", e.getMessage(), e); + throw new RuntimeException("Failed to remove flow definitions", e); + } + return true; + } + + /** + * 新增租户流程定义 + * + * @param tenantId 租户id + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void syncDef(String tenantId) { + List flowDefinitions = flowDefinitionMapper.selectList(new LambdaQueryWrapper().eq(FlowDefinition::getTenantId, DEFAULT_TENANT_ID)); + if (CollUtil.isEmpty(flowDefinitions)) { + return; + } + FlowCategory flowCategory = flwCategoryMapper.selectOne(new LambdaQueryWrapper() + .eq(FlowCategory::getTenantId, DEFAULT_TENANT_ID).eq(FlowCategory::getCategoryId, FlowConstant.FLOW_CATEGORY_ID)); + flowCategory.setCategoryId(null); + flowCategory.setTenantId(tenantId); + flwCategoryMapper.insert(flowCategory); + List defIds = StreamUtils.toList(flowDefinitions, FlowDefinition::getId); + List flowNodes = flowNodeMapper.selectList(new LambdaQueryWrapper().in(FlowNode::getDefinitionId, defIds)); + List flowSkips = flowSkipMapper.selectList(new LambdaQueryWrapper().in(FlowSkip::getDefinitionId, defIds)); + for (FlowDefinition definition : flowDefinitions) { + FlowDefinition flowDefinition = BeanUtil.toBean(definition, FlowDefinition.class); + flowDefinition.setId(null); + flowDefinition.setTenantId(tenantId); + flowDefinition.setIsPublish(0); + flowDefinition.setCategory(String.valueOf(flowCategory.getCategoryId())); + int insert = flowDefinitionMapper.insert(flowDefinition); + if (insert <= 0) { + log.info("同步流程定义【{}】失败!", definition.getFlowCode()); + continue; + } + log.info("同步流程定义【{}】成功!", definition.getFlowCode()); + Long definitionId = flowDefinition.getId(); + if (CollUtil.isNotEmpty(flowNodes)) { + List nodes = StreamUtils.filter(flowNodes, node -> node.getDefinitionId().equals(definition.getId())); + if (CollUtil.isNotEmpty(nodes)) { + List flowNodeList = BeanUtil.copyToList(nodes, FlowNode.class); + flowNodeList.forEach(e -> { + e.setId(null); + e.setDefinitionId(definitionId); + e.setTenantId(tenantId); + e.setPermissionFlag(null); + }); + flowNodeMapper.insertOrUpdate(flowNodeList); + } + } + if (CollUtil.isNotEmpty(flowSkips)) { + List skips = StreamUtils.filter(flowSkips, skip -> skip.getDefinitionId().equals(definition.getId())); + if (CollUtil.isNotEmpty(skips)) { + List flowSkipList = BeanUtil.copyToList(skips, FlowSkip.class); + flowSkipList.forEach(e -> { + e.setId(null); + e.setDefinitionId(definitionId); + e.setTenantId(tenantId); + }); + flowSkipMapper.insertOrUpdate(flowSkipList); + } + } + } + } +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwInstanceServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwInstanceServiceImpl.java new file mode 100644 index 000000000..c053e6d4a --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwInstanceServiceImpl.java @@ -0,0 +1,455 @@ +package org.dromara.workflow.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.convert.Convert; +import cn.hutool.core.util.ObjectUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.dromara.common.core.domain.dto.UserDTO; +import org.dromara.common.core.enums.BusinessStatusEnum; +import org.dromara.common.core.exception.ServiceException; +import org.dromara.common.core.utils.StreamUtils; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.mybatis.core.page.PageQuery; +import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.common.satoken.utils.LoginHelper; +import org.dromara.warm.flow.core.FlowFactory; +import org.dromara.warm.flow.core.constant.ExceptionCons; +import org.dromara.warm.flow.core.dto.FlowParams; +import org.dromara.warm.flow.core.entity.Definition; +import org.dromara.warm.flow.core.entity.Instance; +import org.dromara.warm.flow.core.entity.Task; +import org.dromara.warm.flow.core.enums.NodeType; +import org.dromara.warm.flow.core.service.DefService; +import org.dromara.warm.flow.core.service.InsService; +import org.dromara.warm.flow.core.service.TaskService; +import org.dromara.warm.flow.orm.entity.FlowHisTask; +import org.dromara.warm.flow.orm.entity.FlowInstance; +import org.dromara.warm.flow.orm.entity.FlowTask; +import org.dromara.warm.flow.orm.mapper.FlowHisTaskMapper; +import org.dromara.warm.flow.orm.mapper.FlowInstanceMapper; +import org.dromara.workflow.common.enums.TaskStatusEnum; +import org.dromara.workflow.domain.bo.FlowCancelBo; +import org.dromara.workflow.domain.bo.FlowInstanceBo; +import org.dromara.workflow.domain.bo.FlowInvalidBo; +import org.dromara.workflow.domain.vo.FlowHisTaskVo; +import org.dromara.workflow.domain.vo.FlowInstanceVo; +import org.dromara.workflow.domain.vo.FlowVariableVo; +import org.dromara.workflow.handler.FlowProcessEventHandler; +import org.dromara.workflow.mapper.FlwCategoryMapper; +import org.dromara.workflow.mapper.FlwInstanceMapper; +import org.dromara.workflow.service.IFlwInstanceService; +import org.dromara.workflow.service.IFlwTaskService; +import org.dromara.workflow.utils.WorkflowUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.io.IOException; +import java.util.*; +import java.util.stream.Collectors; + +/** + * 流程实例 服务层实现 + * + * @author may + */ +@Slf4j +@RequiredArgsConstructor +@Service +public class FlwInstanceServiceImpl implements IFlwInstanceService { + + private final InsService insService; + private final DefService defService; + private final FlowHisTaskMapper flowHisTaskMapper; + private final FlowInstanceMapper flowInstanceMapper; + private final FlwInstanceMapper flwInstanceMapper; + private final TaskService taskService; + private final IFlwTaskService flwTaskService; + private final FlowProcessEventHandler flowProcessEventHandler; + private final FlwCategoryMapper flwCategoryMapper; + + /** + * 分页查询正在运行的流程实例 + * + * @param flowInstanceBo 流程实例 + * @param pageQuery 分页 + */ + @Override + public TableDataInfo selectRunningInstanceList(FlowInstanceBo flowInstanceBo, PageQuery pageQuery) { + QueryWrapper queryWrapper = buildQueryWrapper(flowInstanceBo); + queryWrapper.in("fi.flow_status", BusinessStatusEnum.runningStatus()); + Page page = flwInstanceMapper.selectInstanceList(pageQuery.build(), queryWrapper); + return TableDataInfo.build(page); + } + + /** + * 分页查询已结束的流程实例 + * + * @param flowInstanceBo 流程实例 + * @param pageQuery 分页 + */ + @Override + public TableDataInfo selectFinishInstanceList(FlowInstanceBo flowInstanceBo, PageQuery pageQuery) { + QueryWrapper queryWrapper = buildQueryWrapper(flowInstanceBo); + queryWrapper.in("fi.flow_status", BusinessStatusEnum.finishStatus()); + Page page = flwInstanceMapper.selectInstanceList(pageQuery.build(), queryWrapper); + return TableDataInfo.build(page); + } + + /** + * 根据业务id查询流程实例详细信息 + * + * @param businessId 业务id + * @return 结果 + */ + @Override + public FlowInstanceVo queryByBusinessId(Long businessId) { + FlowInstance instance = this.selectInstByBusinessId(String.valueOf(businessId)); + FlowInstanceVo instanceVo = BeanUtil.toBean(instance, FlowInstanceVo.class); + Definition definition = defService.getById(instanceVo.getDefinitionId()); + instanceVo.setFlowName(definition.getFlowName()); + instanceVo.setFlowCode(definition.getFlowCode()); + instanceVo.setVersion(definition.getVersion()); + instanceVo.setFormCustom(definition.getFormCustom()); + instanceVo.setFormPath(definition.getFormPath()); + instanceVo.setCategory(definition.getCategory()); + return instanceVo; + } + + /** + * 通用查询条件 + * + * @param flowInstanceBo 查询条件 + * @return 查询条件构造方法 + */ + private QueryWrapper buildQueryWrapper(FlowInstanceBo flowInstanceBo) { + QueryWrapper queryWrapper = Wrappers.query(); + queryWrapper.like(StringUtils.isNotBlank(flowInstanceBo.getNodeName()), "fi.node_name", flowInstanceBo.getNodeName()); + queryWrapper.like(StringUtils.isNotBlank(flowInstanceBo.getFlowName()), "fd.flow_name", flowInstanceBo.getFlowName()); + queryWrapper.like(StringUtils.isNotBlank(flowInstanceBo.getFlowCode()), "fd.flow_code", flowInstanceBo.getFlowCode()); + if (StringUtils.isNotBlank(flowInstanceBo.getCategory())) { + List categoryIds = flwCategoryMapper.selectCategoryIdsByParentId(Convert.toLong(flowInstanceBo.getCategory())); + queryWrapper.in("fd.category", categoryIds); + } + queryWrapper.eq(StringUtils.isNotBlank(flowInstanceBo.getBusinessId()), "fi.business_id", flowInstanceBo.getBusinessId()); + queryWrapper.in(CollUtil.isNotEmpty(flowInstanceBo.getCreateByIds()), "fi.create_by", flowInstanceBo.getCreateByIds()); + queryWrapper.eq("fi.del_flag", "0"); + queryWrapper.orderByDesc("fi.create_time"); + return queryWrapper; + } + + /** + * 根据业务id查询流程实例 + * + * @param businessId 业务id + */ + @Override + public FlowInstance selectInstByBusinessId(String businessId) { + return flowInstanceMapper.selectOne(new LambdaQueryWrapper().eq(FlowInstance::getBusinessId, businessId)); + } + + /** + * 按照实例id查询流程实例 + * + * @param instanceId 实例id + */ + @Override + public FlowInstance selectInstById(Long instanceId) { + return flowInstanceMapper.selectById(instanceId); + } + + /** + * 按照实例id查询流程实例 + * + * @param instanceIds 实例id + */ + @Override + public List selectInstListByIdList(List instanceIds) { + return flowInstanceMapper.selectByIds(instanceIds); + } + + /** + * 按照业务id删除流程实例 + * + * @param businessIds 业务id + */ + @Override + @Transactional(rollbackFor = Exception.class) + public boolean deleteByBusinessIds(List businessIds) { + List flowInstances = flowInstanceMapper.selectList(new LambdaQueryWrapper().in(FlowInstance::getBusinessId, businessIds)); + if (CollUtil.isEmpty(flowInstances)) { + log.warn("未找到对应的流程实例信息,无法执行删除操作。"); + return false; + } + return insService.remove(StreamUtils.toList(flowInstances, FlowInstance::getId)); + } + + /** + * 按照实例id删除流程实例 + * + * @param instanceIds 实例id + */ + @Override + @Transactional(rollbackFor = Exception.class) + public boolean deleteByInstanceIds(List instanceIds) { + // 获取实例信息 + List instances = insService.getByIds(instanceIds); + if (CollUtil.isEmpty(instances)) { + log.warn("未找到对应的流程实例信息,无法执行删除操作。"); + return false; + } + // 获取定义信息 + Map definitionMap = defService.getByIds( + StreamUtils.toList(instances, Instance::getDefinitionId) + ).stream().collect(Collectors.toMap(Definition::getId, definition -> definition)); + + // 逐一触发删除事件 + instances.forEach(instance -> { + Definition definition = definitionMap.get(instance.getDefinitionId()); + if (ObjectUtil.isNull(definition)) { + log.warn("实例 ID: {} 对应的流程定义信息未找到,跳过删除事件触发。", instance.getId()); + return; + } + flowProcessEventHandler.processDeleteHandler(definition.getFlowCode(), instance.getBusinessId()); + }); + + // 删除实例 + return insService.remove(instanceIds); + } + + /** + * 撤销流程 + * + * @param bo 参数 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public boolean cancelProcessApply(FlowCancelBo bo) { + try { + Instance instance = selectInstByBusinessId(bo.getBusinessId()); + if (instance == null) { + throw new ServiceException(ExceptionCons.NOT_FOUNT_INSTANCE); + } + Definition definition = defService.getById(instance.getDefinitionId()); + if (definition == null) { + throw new ServiceException(ExceptionCons.NOT_FOUNT_DEF); + } + String message = bo.getMessage(); + BusinessStatusEnum.checkCancelStatus(instance.getFlowStatus()); + String applyNodeCode = WorkflowUtils.applyNodeCode(definition.getId()); + //撤销 + WorkflowUtils.backTask(message, instance.getId(), applyNodeCode, BusinessStatusEnum.CANCEL.getStatus(), BusinessStatusEnum.CANCEL.getStatus()); + //判断或签节点是否有多个,只保留一个 + List currentTaskList = taskService.list(FlowFactory.newTask().setInstanceId(instance.getId())); + if (CollUtil.isNotEmpty(currentTaskList)) { + if (currentTaskList.size() > 1) { + currentTaskList.remove(0); + WorkflowUtils.deleteRunTask(StreamUtils.toList(currentTaskList, Task::getId)); + } + } + + } catch (Exception e) { + log.error("撤销失败: {}", e.getMessage(), e); + throw new ServiceException(e.getMessage()); + } + return true; + } + + /** + * 获取当前登陆人发起的流程实例 + * + * @param instanceBo 流程实例 + * @param pageQuery 分页 + */ + @Override + public TableDataInfo selectCurrentInstanceList(FlowInstanceBo instanceBo, PageQuery pageQuery) { + QueryWrapper queryWrapper = buildQueryWrapper(instanceBo); + queryWrapper.eq("fi.create_by", LoginHelper.getUserIdStr()); + Page page = flwInstanceMapper.selectInstanceList(pageQuery.build(), queryWrapper); + return TableDataInfo.build(page); + } + + /** + * 获取流程图,流程记录 + * + * @param businessId 业务id + */ + @Override + public Map flowImage(String businessId) { + Map map = new HashMap<>(16); + FlowInstance flowInstance = this.selectInstByBusinessId(businessId); + if (flowInstance == null) { + throw new ServiceException(ExceptionCons.NOT_FOUNT_INSTANCE); + } + //运行中的任务 + List list = new ArrayList<>(); + List flowTaskList = flwTaskService.selectByInstId(flowInstance.getId()); + if (CollUtil.isNotEmpty(flowTaskList)) { + List flowHisTaskVos = BeanUtil.copyToList(flowTaskList, FlowHisTaskVo.class); + for (FlowHisTaskVo flowHisTaskVo : flowHisTaskVos) { + flowHisTaskVo.setFlowStatus(TaskStatusEnum.WAITING.getStatus()); + flowHisTaskVo.setUpdateTime(null); + flowHisTaskVo.setRunDuration(null); + List allUser = flwTaskService.currentTaskAllUser(flowHisTaskVo.getId()); + if (CollUtil.isNotEmpty(allUser)) { + String join = StreamUtils.join(allUser, e -> String.valueOf(e.getUserId())); + flowHisTaskVo.setApprover(join); + } + if (BusinessStatusEnum.isDraftOrCancelOrBack(flowInstance.getFlowStatus())) { + flowHisTaskVo.setApprover(LoginHelper.getUserIdStr()); + flowHisTaskVo.setApproveName(LoginHelper.getLoginUser().getNickname()); + } + } + list.addAll(flowHisTaskVos); + } + //历史任务 + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(); + wrapper.eq(FlowHisTask::getInstanceId, flowInstance.getId()); + wrapper.eq(FlowHisTask::getNodeType, NodeType.BETWEEN.getKey()); + wrapper.orderByDesc(FlowHisTask::getCreateTime).orderByDesc(FlowHisTask::getUpdateTime); + List flowHisTasks = flowHisTaskMapper.selectList(wrapper); + if (CollUtil.isNotEmpty(flowHisTasks)) { + list.addAll(BeanUtil.copyToList(flowHisTasks, FlowHisTaskVo.class)); + } + + map.put("list", list); + try { + String flowChart = defService.flowChart(flowInstance.getId()); + map.put("image", flowChart); + } catch (IOException e) { + throw new RuntimeException(e); + } + return map; + } + + /** + * 按照实例id更新状态 + * + * @param instanceId 实例id + * @param status 状态 + */ + @Override + public void updateStatus(Long instanceId, String status) { + LambdaUpdateWrapper wrapper = new LambdaUpdateWrapper<>(); + wrapper.set(FlowInstance::getFlowStatus, status); + wrapper.eq(FlowInstance::getId, instanceId); + flowInstanceMapper.update(wrapper); + } + + /** + * 获取流程变量 + * + * @param instanceId 实例id + */ + @Override + public Map instanceVariable(String instanceId) { + Map map = new HashMap<>(); + FlowInstance flowInstance = flowInstanceMapper.selectById(instanceId); + Map variableMap = flowInstance.getVariableMap(); + List list = new ArrayList<>(); + if (CollUtil.isNotEmpty(variableMap)) { + for (Map.Entry entry : variableMap.entrySet()) { + FlowVariableVo flowVariableVo = new FlowVariableVo(); + flowVariableVo.setKey(entry.getKey()); + flowVariableVo.setValue(entry.getValue().toString()); + list.add(flowVariableVo); + } + } + map.put("variableList", list); + map.put("variable", flowInstance.getVariable()); + return map; + } + + /** + * 设置流程变量 + * + * @param instanceId 实例id + * @param variable 流程变量 + */ + @Override + public void setVariable(Long instanceId, Map variable) { + Instance instance = insService.getById(instanceId); + if (instance != null) { + taskService.mergeVariable(instance, variable); + } + } + + /** + * 按任务id查询实例 + * + * @param taskId 任务id + */ + @Override + public FlowInstance selectByTaskId(Long taskId) { + Task task = taskService.getById(taskId); + if (task == null) { + FlowHisTask flowHisTask = flwTaskService.selectHisTaskById(taskId); + if (flowHisTask != null) { + return this.selectInstById(flowHisTask.getInstanceId()); + } + } else { + return this.selectInstById(task.getInstanceId()); + } + return null; + } + + /** + * 按任务id查询实例 + * + * @param taskIdList 任务id + */ + @Override + public List selectByTaskIdList(List taskIdList) { + if (CollUtil.isEmpty(taskIdList)) { + return Collections.emptyList(); + } + Set instanceIds = new HashSet<>(); + List flowTaskList = flwTaskService.selectByIdList(taskIdList); + for (FlowTask flowTask : flowTaskList) { + instanceIds.add(flowTask.getInstanceId()); + } + List flowHisTaskList = flwTaskService.selectHisTaskByIdList(taskIdList); + for (FlowHisTask flowHisTask : flowHisTaskList) { + instanceIds.add(flowHisTask.getInstanceId()); + } + if (!instanceIds.isEmpty()) { + return this.selectInstListByIdList(new ArrayList<>(instanceIds)); + } + return Collections.emptyList(); + } + + /** + * 作废流程 + * + * @param bo 参数 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public boolean processInvalid(FlowInvalidBo bo) { + try { + Instance instance = insService.getById(bo.getId()); + if (instance != null) { + BusinessStatusEnum.checkInvalidStatus(instance.getFlowStatus()); + } + List flowTaskList = flwTaskService.selectByInstId(bo.getId()); + for (FlowTask flowTask : flowTaskList) { + FlowParams flowParams = new FlowParams(); + flowParams.message(bo.getComment()); + flowParams.flowStatus(BusinessStatusEnum.INVALID.getStatus()) + .hisStatus(TaskStatusEnum.INVALID.getStatus()); + flowParams.ignore(true); + taskService.termination(flowTask.getId(), flowParams); + } + return true; + } catch (Exception e) { + log.error(e.getMessage(), e); + throw new ServiceException(e.getMessage()); + } + } +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskAssigneeServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskAssigneeServiceImpl.java new file mode 100644 index 000000000..28c1e8b04 --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskAssigneeServiceImpl.java @@ -0,0 +1,158 @@ +package org.dromara.workflow.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.util.StrUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.dromara.common.core.domain.dto.DeptDTO; +import org.dromara.common.core.domain.dto.TaskAssigneeDTO; +import org.dromara.common.core.domain.dto.UserDTO; +import org.dromara.common.core.domain.model.TaskAssigneeBody; +import org.dromara.common.core.enums.FormatsType; +import org.dromara.common.core.exception.ServiceException; +import org.dromara.common.core.service.DeptService; +import org.dromara.common.core.service.TaskAssigneeService; +import org.dromara.common.core.service.UserService; +import org.dromara.common.core.utils.DateUtils; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.warm.flow.ui.dto.HandlerFunDto; +import org.dromara.warm.flow.ui.dto.HandlerQuery; +import org.dromara.warm.flow.ui.dto.TreeFunDto; +import org.dromara.warm.flow.ui.service.HandlerSelectService; +import org.dromara.warm.flow.ui.vo.HandlerSelectVo; +import org.dromara.workflow.common.enums.TaskAssigneeEnum; +import org.dromara.workflow.service.IFlwTaskAssigneeService; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +/** + * 流程设计器-获取办理人权限设置列表 + * + * @author AprilWind + */ +@Slf4j +@RequiredArgsConstructor +@Service +public class FlwTaskAssigneeServiceImpl implements IFlwTaskAssigneeService, HandlerSelectService { + + private static final String DEFAULT_GROUP_NAME = "默认分组"; + private final TaskAssigneeService taskAssigneeService; + private final UserService userService; + private final DeptService deptService; + + /** + * 获取办理人权限设置列表tabs页签 + * + * @return tabs页签 + */ + @Override + public List getHandlerType() { + return TaskAssigneeEnum.getAssigneeTypeList(); + } + + /** + * 获取办理列表, 同时构建左侧部门树状结构 + * + * @param query 查询条件 + * @return HandlerSelectVo + */ + @Override + public HandlerSelectVo getHandlerSelect(HandlerQuery query) { + // 获取任务办理类型 + TaskAssigneeEnum type = TaskAssigneeEnum.fromDesc(query.getHandlerType()); + // 转换查询条件为 TaskAssigneeBody + TaskAssigneeBody taskQuery = BeanUtil.toBean(query, TaskAssigneeBody.class); + + // 统一查询并构建业务数据 + TaskAssigneeDTO dto = fetchTaskAssigneeData(type, taskQuery); + List depts = fetchDeptData(type); + + return getHandlerSelectVo(buildHandlerData(dto, type), buildDeptTree(depts)); + } + + /** + * 根据任务办理类型查询对应的数据 + */ + private TaskAssigneeDTO fetchTaskAssigneeData(TaskAssigneeEnum type, TaskAssigneeBody taskQuery) { + return switch (type) { + case USER -> taskAssigneeService.selectUsersByTaskAssigneeList(taskQuery); + case ROLE -> taskAssigneeService.selectRolesByTaskAssigneeList(taskQuery); + case DEPT -> taskAssigneeService.selectDeptsByTaskAssigneeList(taskQuery); + case POST -> taskAssigneeService.selectPostsByTaskAssigneeList(taskQuery); + default -> throw new ServiceException("Unsupported handler type"); + }; + } + + /** + * 根据任务办理类型获取部门数据 + */ + private List fetchDeptData(TaskAssigneeEnum type) { + if (type == TaskAssigneeEnum.USER || type == TaskAssigneeEnum.DEPT || type == TaskAssigneeEnum.POST) { + return deptService.selectDeptsByList(); + } + return new ArrayList<>(); + } + + /** + * 构建部门树状结构 + */ + private TreeFunDto buildDeptTree(List depts) { + return new TreeFunDto<>(depts) + .setId(dept -> String.valueOf(dept.getDeptId())) + .setName(DeptDTO::getDeptName) + .setParentId(dept -> String.valueOf(dept.getParentId())); + } + + /** + * 构建任务办理人数据 + */ + private HandlerFunDto buildHandlerData(TaskAssigneeDTO dto, TaskAssigneeEnum type) { + return new HandlerFunDto<>(dto.getList(), dto.getTotal()) + .setStorageId(assignee -> type.getCode() + assignee.getStorageId()) + .setHandlerCode(assignee -> StringUtils.blankToDefault(assignee.getHandlerCode(), "无")) + .setHandlerName(assignee -> StringUtils.blankToDefault(assignee.getHandlerName(), "无")) + .setGroupName(assignee -> StringUtils.defaultIfBlank( + Optional.ofNullable(assignee.getGroupName()) + .map(deptService::selectDeptNameByIds) + .orElse(DEFAULT_GROUP_NAME), DEFAULT_GROUP_NAME)) + .setCreateTime(assignee -> DateUtils.parseDateToStr(FormatsType.YYYY_MM_DD_HH_MM_SS, assignee.getCreateTime())); + } + + /** + * 根据存储标识符(storageId)解析分配类型和ID,并获取对应的用户列表 + * + * @param storageId 包含分配类型和ID的字符串(例如 "user:123" 或 "role:456") + * @return 与分配类型和ID匹配的用户列表,如果格式无效则返回空列表 + */ + @Override + public List fetchUsersByStorageId(String storageId) { + String[] parts = storageId.split(StrUtil.COLON, 2); + if (parts.length < 2) { + return getUsersByType(TaskAssigneeEnum.USER, List.of(Long.valueOf(parts[0]))); + } + return getUsersByType(TaskAssigneeEnum.fromCode(parts[0] + StrUtil.COLON), List.of(Long.valueOf(parts[1]))); + } + + /** + * 根据指定的任务分配类型(TaskAssigneeEnum)和 ID 列表,获取对应的用户信息列表 + * + * @param type 任务分配类型,表示用户、角色、部门或其他(TaskAssigneeEnum 枚举值) + * @param ids 与指定分配类型关联的 ID 列表(例如用户ID、角色ID、部门ID等) + * @return 返回包含用户信息的列表。如果类型为用户(USER),则通过用户ID列表查询; + * 如果类型为角色(ROLE),则通过角色ID列表查询; + * 如果类型为部门(DEPT),则通过部门ID列表查询; + * 如果类型为岗位(POST)或无法识别的类型,则返回空列表 + */ + private List getUsersByType(TaskAssigneeEnum type, List ids) { + return switch (type) { + case USER -> userService.selectListByIds(ids); + case ROLE -> userService.selectUsersByRoleIds(ids); + case DEPT -> userService.selectUsersByDeptIds(ids); + case POST -> userService.selectUsersByPostIds(ids); + }; + } + +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskServiceImpl.java new file mode 100644 index 000000000..fca38fbac --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskServiceImpl.java @@ -0,0 +1,669 @@ +package org.dromara.workflow.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.convert.Convert; +import cn.hutool.core.util.ObjectUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.dromara.common.core.domain.dto.UserDTO; +import org.dromara.common.core.enums.BusinessStatusEnum; +import org.dromara.common.core.exception.ServiceException; +import org.dromara.common.core.service.UserService; +import org.dromara.common.core.utils.SpringUtils; +import org.dromara.common.core.utils.StreamUtils; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.core.utils.ValidatorUtils; +import org.dromara.common.core.validate.AddGroup; +import org.dromara.common.core.validate.EditGroup; +import org.dromara.common.mybatis.core.page.PageQuery; +import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.common.satoken.utils.LoginHelper; +import org.dromara.warm.flow.core.dto.FlowParams; +import org.dromara.warm.flow.core.entity.*; +import org.dromara.warm.flow.core.enums.NodeType; +import org.dromara.warm.flow.core.enums.SkipType; +import org.dromara.warm.flow.core.service.*; +import org.dromara.warm.flow.orm.entity.*; +import org.dromara.warm.flow.orm.mapper.FlowHisTaskMapper; +import org.dromara.warm.flow.orm.mapper.FlowInstanceMapper; +import org.dromara.warm.flow.orm.mapper.FlowNodeMapper; +import org.dromara.warm.flow.orm.mapper.FlowTaskMapper; +import org.dromara.workflow.common.enums.TaskAssigneeType; +import org.dromara.workflow.common.enums.TaskStatusEnum; +import org.dromara.workflow.domain.bo.*; +import org.dromara.workflow.domain.vo.FlowHisTaskVo; +import org.dromara.workflow.domain.vo.FlowTaskVo; +import org.dromara.workflow.handler.FlowProcessEventHandler; +import org.dromara.workflow.handler.WorkflowPermissionHandler; +import org.dromara.workflow.mapper.FlwCategoryMapper; +import org.dromara.workflow.mapper.FlwTaskMapper; +import org.dromara.workflow.service.IFlwTaskService; +import org.dromara.workflow.utils.WorkflowUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.math.BigDecimal; +import java.util.*; +import java.util.stream.Collectors; + +import static org.dromara.workflow.common.constant.FlowConstant.*; + +/** + * 任务 服务层实现 + * + * @author may + */ +@Slf4j +@RequiredArgsConstructor +@Service +public class FlwTaskServiceImpl implements IFlwTaskService { + + private final TaskService taskService; + private final InsService insService; + private final FlowInstanceMapper flowInstanceMapper; + private final FlwTaskMapper flwTaskMapper; + private final UserService userService; + private final FlowTaskMapper flowTaskMapper; + private final FlowHisTaskMapper flowHisTaskMapper; + private final FlowProcessEventHandler flowProcessEventHandler; + private final DefService defService; + private final HisTaskService hisTaskService; + private final IdentifierGenerator identifierGenerator; + private final NodeService nodeService; + private final FlowNodeMapper flowNodeMapper; + private final FlwCategoryMapper flwCategoryMapper; + + /** + * 启动任务 + * + * @param startProcessBo 启动流程参数 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public Map startWorkFlow(StartProcessBo startProcessBo) { + String businessId = startProcessBo.getBusinessId(); + if (StringUtils.isBlank(businessId)) { + throw new ServiceException("启动工作流时必须包含业务ID"); + } + // 启动流程实例(提交申请) + Map variables = startProcessBo.getVariables(); + // 流程发起人 + variables.put(INITIATOR, LoginHelper.getUserIdStr()); + // 业务id + variables.put(BUSINESS_ID, businessId); + FlowInstance flowInstance = flowInstanceMapper.selectOne(new LambdaQueryWrapper<>(FlowInstance.class) + .eq(FlowInstance::getBusinessId, businessId)); + if (ObjectUtil.isNotNull(flowInstance)) { + BusinessStatusEnum.checkStartStatus(flowInstance.getFlowStatus()); + List taskList = taskService.list(new FlowTask().setInstanceId(flowInstance.getId())); + return Map.of(PROCESS_INSTANCE_ID, taskList.get(0).getInstanceId(), TASK_ID, taskList.get(0).getId()); + } + FlowParams flowParams = new FlowParams(); + flowParams.flowCode(startProcessBo.getFlowCode()); + flowParams.variable(startProcessBo.getVariables()); + flowParams.flowStatus(BusinessStatusEnum.DRAFT.getStatus()); + Instance instance; + try { + instance = insService.start(businessId, flowParams); + } catch (Exception e) { + throw new ServiceException(e.getMessage()); + } + // 申请人执行流程 + List taskList = taskService.list(new FlowTask().setInstanceId(instance.getId())); + if (taskList.size() > 1) { + throw new ServiceException("请检查流程第一个环节是否为申请人!"); + } + return Map.of(PROCESS_INSTANCE_ID, instance.getId(), TASK_ID, taskList.get(0).getId()); + } + + /** + * 办理任务 + * + * @param completeTaskBo 办理任务参数 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public boolean completeTask(CompleteTaskBo completeTaskBo) { + try { + // 获取任务ID并查询对应的流程任务和实例信息 + Long taskId = completeTaskBo.getTaskId(); + List messageType = completeTaskBo.getMessageType(); + String notice = completeTaskBo.getNotice(); + // 获取抄送人 + List flowCopyList = completeTaskBo.getFlowCopyList(); + FlowTask flowTask = flowTaskMapper.selectById(taskId); + Instance ins = insService.getById(flowTask.getInstanceId()); + // 获取流程定义信息 + Definition definition = defService.getById(flowTask.getDefinitionId()); + // 检查流程状态是否为草稿、已撤销或已退回状态,若是则执行流程提交监听 + if (BusinessStatusEnum.isDraftOrCancelOrBack(ins.getFlowStatus())) { + flowProcessEventHandler.processHandler(definition.getFlowCode(), ins.getBusinessId(), ins.getFlowStatus(), true); + } + // 构建流程参数,包括变量、跳转类型、消息、处理人、权限等信息 + FlowParams flowParams = new FlowParams(); + flowParams.variable(completeTaskBo.getVariables()); + flowParams.skipType(SkipType.PASS.getKey()); + flowParams.message(completeTaskBo.getMessage()); + flowParams.flowStatus(BusinessStatusEnum.WAITING.getStatus()).hisStatus(TaskStatusEnum.PASS.getStatus()); + + flowParams.hisTaskExt(completeTaskBo.getFileId()); + // 执行任务跳转,并根据返回的处理人设置下一步处理人 + Instance instance = taskService.skip(taskId, flowParams); + this.setHandler(instance, flowTask, flowCopyList); + // 消息通知 + WorkflowUtils.sendMessage(definition.getFlowName(), ins.getId(), messageType, notice); + return true; + } catch (Exception e) { + log.error(e.getMessage(), e); + throw new ServiceException(e.getMessage()); + } + } + + /** + * 设置办理人 + * + * @param instance 实例 + * @param task (当前任务)未办理的任务 + * @param flowCopyList 抄送人 + */ + private void setHandler(Instance instance, FlowTask task, List flowCopyList) { + if (ObjectUtil.isNull(instance)) { + return; + } + // 添加抄送人 + this.setCopy(task, flowCopyList); + // 根据流程实例ID查询所有关联的任务 + List flowTasks = this.selectByInstId(instance.getId()); + List userList = new ArrayList<>(); + // 遍历任务列表,处理每个任务的办理人 + for (FlowTask flowTask : flowTasks) { + // 获取与当前任务关联的用户列表 + List associatedUsers = WorkflowUtils.getFlowUserService().getByAssociateds(Collections.singletonList(flowTask.getId())); + if (CollUtil.isNotEmpty(associatedUsers)) { + userList.addAll(WorkflowUtils.buildUser(associatedUsers, flowTask.getId())); + } + } + // 批量删除现有任务的办理人记录 + if (CollUtil.isNotEmpty(flowTasks)) { + WorkflowUtils.getFlowUserService().deleteByTaskIds(StreamUtils.toList(flowTasks, FlowTask::getId)); + } + // 确保要保存的 userList 不为空 + if (CollUtil.isNotEmpty(userList)) { + WorkflowUtils.getFlowUserService().saveBatch(userList); + } + } + + /** + * 添加抄送人 + * + * @param task 任务信息 + * @param flowCopyList 抄送人 + */ + public void setCopy(FlowTask task, List flowCopyList) { + if (CollUtil.isEmpty(flowCopyList)) { + return; + } + // 添加抄送人记录 + FlowHisTask flowHisTask = flowHisTaskMapper.selectList(new LambdaQueryWrapper<>(FlowHisTask.class).eq(FlowHisTask::getTaskId, task.getId())).get(0); + FlowNode flowNode = new FlowNode(); + flowNode.setNodeCode(flowHisTask.getTargetNodeCode()); + flowNode.setNodeName(flowHisTask.getTargetNodeName()); + //生成新的任务id + long taskId = identifierGenerator.nextId(null).longValue(); + task.setId(taskId); + task.setNodeName("【抄送】" + task.getNodeName()); + Date updateTime = new Date(flowHisTask.getUpdateTime().getTime() - 1000); + FlowParams flowParams = FlowParams.build(); + flowParams.skipType(SkipType.NONE.getKey()); + flowParams.hisStatus(TaskStatusEnum.COPY.getStatus()); + flowParams.message("【抄送给】" + StreamUtils.join(flowCopyList, FlowCopyBo::getUserName)); + HisTask hisTask = hisTaskService.setSkipHisTask(task, flowNode, flowParams); + hisTask.setCreateTime(updateTime); + hisTask.setUpdateTime(updateTime); + hisTaskService.save(hisTask); + List userList = flowCopyList.stream() + .map(flowCopy -> { + FlowUser flowUser = new FlowUser(); + flowUser.setType(TaskAssigneeType.COPY.getCode()); + flowUser.setProcessedBy(String.valueOf(flowCopy.getUserId())); + flowUser.setAssociated(taskId); + return flowUser; + }).collect(Collectors.toList()); + // 批量保存抄送人员 + WorkflowUtils.getFlowUserService().saveBatch(userList); + } + + /** + * 查询当前用户的待办任务 + * + * @param flowTaskBo 参数 + * @param pageQuery 分页 + */ + @Override + public TableDataInfo pageByTaskWait(FlowTaskBo flowTaskBo, PageQuery pageQuery) { + QueryWrapper queryWrapper = buildQueryWrapper(flowTaskBo); + queryWrapper.eq("t.node_type", NodeType.BETWEEN.getKey()); + queryWrapper.in("t.processed_by", SpringUtils.getBean(WorkflowPermissionHandler.class).permissions()); + queryWrapper.in("t.flow_status", BusinessStatusEnum.WAITING.getStatus()); + Page page = this.getFlowTaskVoPage(pageQuery, queryWrapper); + return TableDataInfo.build(page); + } + + /** + * 查询当前用户的已办任务 + * + * @param flowTaskBo 参数 + * @param pageQuery 分页 + */ + @Override + public TableDataInfo pageByTaskFinish(FlowTaskBo flowTaskBo, PageQuery pageQuery) { + QueryWrapper queryWrapper = buildQueryWrapper(flowTaskBo); + queryWrapper.eq("t.node_type", NodeType.BETWEEN.getKey()); + queryWrapper.in("t.approver", LoginHelper.getUserIdStr()); + queryWrapper.orderByDesc("t.create_time").orderByDesc("t.update_time"); + Page page = flwTaskMapper.getListFinishTask(pageQuery.build(), queryWrapper); + return TableDataInfo.build(page); + } + + /** + * 查询待办任务 + * + * @param flowTaskBo 参数 + * @param pageQuery 分页 + */ + @Override + public TableDataInfo pageByAllTaskWait(FlowTaskBo flowTaskBo, PageQuery pageQuery) { + QueryWrapper queryWrapper = buildQueryWrapper(flowTaskBo); + queryWrapper.eq("t.node_type", NodeType.BETWEEN.getKey()); + Page page = getFlowTaskVoPage(pageQuery, queryWrapper); + return TableDataInfo.build(page); + } + + private Page getFlowTaskVoPage(PageQuery pageQuery, QueryWrapper queryWrapper) { + Page page = flwTaskMapper.getListRunTask(pageQuery.build(), queryWrapper); + List records = page.getRecords(); + if (CollUtil.isNotEmpty(records)) { + List taskIds = StreamUtils.toList(records, FlowTaskVo::getId); + Map> listMap = currentTaskAllUser(taskIds); + records.forEach(t -> { + List userList = listMap.getOrDefault(t.getId(), Collections.emptyList()); + if (CollUtil.isNotEmpty(userList)) { + t.setAssigneeIds(StreamUtils.join(userList, e -> String.valueOf(e.getUserId()))); + t.setAssigneeNames(StreamUtils.join(userList, UserDTO::getNickName)); + } + }); + } + return page; + } + + /** + * 查询已办任务 + * + * @param flowTaskBo 参数 + * @param pageQuery 分页 + */ + @Override + public TableDataInfo pageByAllTaskFinish(FlowTaskBo flowTaskBo, PageQuery pageQuery) { + QueryWrapper queryWrapper = buildQueryWrapper(flowTaskBo); + Page page = flwTaskMapper.getListFinishTask(pageQuery.build(), queryWrapper); + return TableDataInfo.build(page); + } + + /** + * 查询当前用户的抄送 + * + * @param flowTaskBo 参数 + * @param pageQuery 分页 + */ + @Override + public TableDataInfo pageByTaskCopy(FlowTaskBo flowTaskBo, PageQuery pageQuery) { + QueryWrapper queryWrapper = buildQueryWrapper(flowTaskBo); + queryWrapper.in("t.processed_by", LoginHelper.getUserIdStr()); + Page page = flwTaskMapper.getTaskCopyByPage(pageQuery.build(), queryWrapper); + return TableDataInfo.build(page); + } + + private QueryWrapper buildQueryWrapper(FlowTaskBo flowTaskBo) { + QueryWrapper wrapper = Wrappers.query(); + wrapper.like(StringUtils.isNotBlank(flowTaskBo.getNodeName()), "t.node_name", flowTaskBo.getNodeName()); + wrapper.like(StringUtils.isNotBlank(flowTaskBo.getFlowName()), "t.flow_name", flowTaskBo.getFlowName()); + wrapper.like(StringUtils.isNotBlank(flowTaskBo.getFlowCode()), "t.flow_code", flowTaskBo.getFlowCode()); + wrapper.in(CollUtil.isNotEmpty(flowTaskBo.getCreateByIds()), "t.create_by", flowTaskBo.getCreateByIds()); + if (StringUtils.isNotBlank(flowTaskBo.getCategory())) { + List categoryIds = flwCategoryMapper.selectCategoryIdsByParentId(Convert.toLong(flowTaskBo.getCategory())); + wrapper.in("t.category", categoryIds); + } + wrapper.orderByDesc("t.create_time"); + return wrapper; + } + + /** + * 驳回任务 + * + * @param bo 参数 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public boolean backProcess(BackProcessBo bo) { + try { + Long taskId = bo.getTaskId(); + String notice = bo.getNotice(); + List messageType = bo.getMessageType(); + String message = bo.getMessage(); + FlowTask task = flowTaskMapper.selectById(taskId); + if (ObjectUtil.isNull(task)) { + throw new ServiceException("任务不存在!"); + } + Instance inst = insService.getById(task.getInstanceId()); + BusinessStatusEnum.checkBackStatus(inst.getFlowStatus()); + Long definitionId = task.getDefinitionId(); + Definition definition = defService.getById(definitionId); + String applyNodeCode = WorkflowUtils.applyNodeCode(definitionId); + FlowParams flowParams = FlowParams.build(); + flowParams.nodeCode(bo.getNodeCode()); + flowParams.message(message); + flowParams.skipType(SkipType.REJECT.getKey()); + flowParams.flowStatus(applyNodeCode.equals(bo.getNodeCode()) ? TaskStatusEnum.BACK.getStatus() : TaskStatusEnum.WAITING.getStatus()) + .hisStatus(TaskStatusEnum.BACK.getStatus()); + taskService.skip(task.getId(), flowParams); + + Instance instance = insService.getById(inst.getId()); + this.setHandler(instance, task, null); + // 消息通知 + WorkflowUtils.sendMessage(definition.getFlowName(), instance.getId(), messageType, notice); + return true; + } catch (Exception e) { + log.error(e.getMessage(), e); + throw new ServiceException(e.getMessage()); + } + } + + /** + * 获取可驳回的前置节点 + * + * @param definitionId 流程定义id + * @param nowNodeCode 当前节点 + */ + @Override + public List getBackTaskNode(Long definitionId, String nowNodeCode) { + List nodeCodes = nodeService.getByNodeCodes(Collections.singletonList(nowNodeCode), definitionId); + if (!CollUtil.isNotEmpty(nodeCodes)) { + return nodeCodes; + } + //判断是否配置了固定驳回节点 + Node node = nodeCodes.get(0); + if (StringUtils.isNotBlank(node.getAnyNodeSkip())) { + return nodeService.getByNodeCodes(Collections.singletonList(node.getAnyNodeSkip()), definitionId); + } + //获取可驳回的前置节点 + List nodes = nodeService.previousNodeList(definitionId, nowNodeCode); + if (CollUtil.isNotEmpty(nodes)) { + return StreamUtils.filter(nodes, e -> NodeType.BETWEEN.getKey().equals(e.getNodeType())); + } + return nodes; + } + + /** + * 终止任务 + * + * @param bo 参数 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public boolean terminationTask(FlowTerminationBo bo) { + try { + Long taskId = bo.getTaskId(); + Task task = taskService.getById(taskId); + if (task == null) { + throw new ServiceException("任务不存在!"); + } + Instance instance = insService.getById(task.getInstanceId()); + if (ObjectUtil.isNotNull(instance)) { + BusinessStatusEnum.checkInvalidStatus(instance.getFlowStatus()); + } + FlowParams flowParams = new FlowParams(); + flowParams.message(bo.getComment()); + flowParams.flowStatus(BusinessStatusEnum.TERMINATION.getStatus()) + .hisStatus(TaskStatusEnum.TERMINATION.getStatus()); + taskService.termination(taskId, flowParams); + return true; + } catch (Exception e) { + log.error(e.getMessage(), e); + throw new ServiceException(e.getMessage()); + } + } + + /** + * 按照任务id查询任务 + * + * @param taskIdList 任务id + */ + @Override + public List selectByIdList(List taskIdList) { + return flowTaskMapper.selectList(new LambdaQueryWrapper<>(FlowTask.class) + .in(FlowTask::getId, taskIdList)); + } + + /** + * 按照任务id查询任务 + * + * @param taskId 任务id + */ + @Override + public FlowTaskVo selectById(Long taskId) { + Task task = taskService.getById(taskId); + if (ObjectUtil.isNull(task)) { + return null; + } + FlowTaskVo flowTaskVo = BeanUtil.toBean(task, FlowTaskVo.class); + Instance instance = insService.getById(task.getInstanceId()); + Definition definition = defService.getById(task.getDefinitionId()); + flowTaskVo.setFlowStatus(instance.getFlowStatus()); + flowTaskVo.setVersion(definition.getVersion()); + flowTaskVo.setFlowCode(definition.getFlowCode()); + flowTaskVo.setFlowName(definition.getFlowName()); + flowTaskVo.setBusinessId(instance.getBusinessId()); + List nodeList = nodeService.getByNodeCodes(Collections.singletonList(flowTaskVo.getNodeCode()), instance.getDefinitionId()); + if (CollUtil.isNotEmpty(nodeList)) { + Node node = nodeList.get(0); + flowTaskVo.setNodeRatio(node.getNodeRatio()); + } + return flowTaskVo; + } + + /** + * 按照任务id查询任务 + * + * @param taskIdList 任务id + * @return 结果 + */ + @Override + public List selectHisTaskByIdList(List taskIdList) { + return flowHisTaskMapper.selectList(new LambdaQueryWrapper<>(FlowHisTask.class) + .in(FlowHisTask::getId, taskIdList)); + } + + /** + * 按照任务id查询任务 + * + * @param taskId 任务id + * @return 结果 + */ + @Override + public FlowHisTask selectHisTaskById(Long taskId) { + return flowHisTaskMapper.selectOne(new LambdaQueryWrapper<>(FlowHisTask.class) + .eq(FlowHisTask::getId, taskId)); + } + + /** + * 按照实例id查询任务 + * + * @param instanceIdList 流程实例id + */ + @Override + public List selectByInstIdList(List instanceIdList) { + return flowTaskMapper.selectList(new LambdaQueryWrapper<>(FlowTask.class) + .in(FlowTask::getInstanceId, instanceIdList)); + } + + /** + * 按照实例id查询任务 + * + * @param instanceId 流程实例id + */ + @Override + public List selectByInstId(Long instanceId) { + return flowTaskMapper.selectList(new LambdaQueryWrapper<>(FlowTask.class) + .eq(FlowTask::getInstanceId, instanceId)); + } + + /** + * 任务操作 + * + * @param bo 参数 + * @param taskOperation 操作类型,委派 delegateTask、转办 transferTask、加签 addSignature、减签 reductionSignature + */ + @Override + @Transactional(rollbackFor = Exception.class) + public boolean taskOperation(TaskOperationBo bo, String taskOperation) { + FlowParams flowParams = new FlowParams(); + flowParams.message(bo.getMessage()); + if (LoginHelper.isSuperAdmin() || LoginHelper.isTenantAdmin()) { + flowParams.ignore(true); + } + + // 根据操作类型构建 FlowParams + switch (taskOperation) { + case DELEGATE_TASK, TRANSFER_TASK -> { + ValidatorUtils.validate(bo, AddGroup.class); + flowParams.addHandlers(Collections.singletonList(bo.getUserId())); + } + case ADD_SIGNATURE -> { + ValidatorUtils.validate(bo, EditGroup.class); + flowParams.addHandlers(bo.getUserIds()); + } + case REDUCTION_SIGNATURE -> { + ValidatorUtils.validate(bo, EditGroup.class); + flowParams.reductionHandlers(bo.getUserIds()); + } + default -> { + log.error("Invalid operation type:{} ", taskOperation); + throw new ServiceException("Invalid operation type " + taskOperation); + } + } + + Long taskId = bo.getTaskId(); + FlowTaskVo flowTaskVo = selectById(taskId); + if ("addSignature".equals(taskOperation) || "reductionSignature".equals(taskOperation)) { + if (flowTaskVo.getNodeRatio().compareTo(BigDecimal.ZERO) == 0) { + throw new ServiceException(flowTaskVo.getNodeName() + "不是会签节点!"); + } + } + // 设置任务状态并执行对应的任务操作 + switch (taskOperation) { + //委派任务 + case DELEGATE_TASK -> { + flowParams.hisStatus(TaskStatusEnum.DEPUTE.getStatus()); + return taskService.depute(taskId, flowParams); + } + //转办任务 + case TRANSFER_TASK -> { + flowParams.hisStatus(TaskStatusEnum.TRANSFER.getStatus()); + return taskService.transfer(taskId, flowParams); + } + //加签,增加办理人 + case ADD_SIGNATURE -> { + flowParams.hisStatus(TaskStatusEnum.SIGN.getStatus()); + return taskService.addSignature(taskId, flowParams); + } + //减签,减少办理人 + case REDUCTION_SIGNATURE -> { + flowParams.hisStatus(TaskStatusEnum.SIGN_OFF.getStatus()); + return taskService.reductionSignature(taskId, flowParams); + } + default -> { + log.error("Invalid operation type:{} ", taskOperation); + throw new ServiceException("Invalid operation type " + taskOperation); + } + } + } + + /** + * 修改任务办理人(此方法将会批量修改所有任务的办理人) + * + * @param taskIdList 任务id + * @param userId 用户id + */ + @Override + @Transactional(rollbackFor = Exception.class) + public boolean updateAssignee(List taskIdList, String userId) { + if (CollUtil.isEmpty(taskIdList)) { + return false; + } + try { + List flowTasks = this.selectByIdList(taskIdList); + // 批量删除现有任务的办理人记录 + if (CollUtil.isNotEmpty(flowTasks)) { + WorkflowUtils.getFlowUserService().deleteByTaskIds(StreamUtils.toList(flowTasks, FlowTask::getId)); + List userList = flowTasks.stream() + .map(flowTask -> { + FlowUser flowUser = new FlowUser(); + flowUser.setType(TaskAssigneeType.APPROVER.getCode()); + flowUser.setProcessedBy(userId); + flowUser.setAssociated(flowTask.getId()); + return flowUser; + }) + .collect(Collectors.toList()); + if (CollUtil.isNotEmpty(userList)) { + WorkflowUtils.getFlowUserService().saveBatch(userList); + } + } + } catch (Exception e) { + log.error(e.getMessage(), e); + throw new ServiceException(e.getMessage()); + } + return true; + } + + /** + * 获取任务所有办理人 + * + * @param taskIdList 任务id + */ + @Override + public Map> currentTaskAllUser(List taskIdList) { + Map> map = new HashMap<>(); + // 获取与当前任务关联的用户列表 + List associatedUsers = WorkflowUtils.getFlowUserService().getByAssociateds(taskIdList); + Map> listMap = StreamUtils.groupByKey(associatedUsers, User::getAssociated); + for (Map.Entry> entry : listMap.entrySet()) { + List value = entry.getValue(); + if (CollUtil.isNotEmpty(value)) { + List userDTOS = userService.selectListByIds(StreamUtils.toList(value, e -> Long.valueOf(e.getProcessedBy()))); + map.put(entry.getKey(), userDTOS); + } + } + return map; + } + + /** + * 获取当前任务的所有办理人 + * + * @param taskId 任务id + */ + @Override + public List currentTaskAllUser(Long taskId) { + // 获取与当前任务关联的用户列表 + List userList = WorkflowUtils.getFlowUserService().getByAssociateds(Collections.singletonList(taskId)); + if (CollUtil.isEmpty(userList)) { + return Collections.emptyList(); + } + return userService.selectListByIds(StreamUtils.toList(userList, e -> Long.valueOf(e.getProcessedBy()))); + } +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/TestLeaveServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/TestLeaveServiceImpl.java index f81c85f7c..499d64b6e 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/TestLeaveServiceImpl.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/TestLeaveServiceImpl.java @@ -1,16 +1,18 @@ package org.dromara.workflow.service.impl; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.dromara.common.core.domain.event.ProcessDeleteEvent; import org.dromara.common.core.domain.event.ProcessEvent; import org.dromara.common.core.domain.event.ProcessTaskEvent; import org.dromara.common.core.enums.BusinessStatusEnum; import org.dromara.common.core.service.WorkflowService; import org.dromara.common.core.utils.MapstructUtils; -import org.dromara.common.core.utils.StreamUtils; import org.dromara.common.core.utils.StringUtils; import org.dromara.common.mybatis.core.domain.BaseEntity; import org.dromara.common.mybatis.core.page.PageQuery; @@ -24,7 +26,6 @@ import org.springframework.context.event.EventListener; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.Collection; import java.util.List; /** @@ -82,6 +83,9 @@ public class TestLeaveServiceImpl implements ITestLeaveService { */ @Override public TestLeaveVo insertByBo(TestLeaveBo bo) { + long day = DateUtil.betweenDay(bo.getStartDate(), bo.getEndDate(), true); + // 截止日期也算一天 + bo.setLeaveDays((int) day + 1); TestLeave add = MapstructUtils.convert(bo, TestLeave.class); if (StringUtils.isBlank(add.getStatus())) { add.setStatus(BusinessStatusEnum.DRAFT.getStatus()); @@ -108,23 +112,22 @@ public class TestLeaveServiceImpl implements ITestLeaveService { */ @Override @Transactional(rollbackFor = Exception.class) - public Boolean deleteWithValidByIds(Collection ids) { - List idList = StreamUtils.toList(ids, String::valueOf); - workflowService.deleteRunAndHisInstance(idList); + public Boolean deleteWithValidByIds(List ids) { + workflowService.deleteInstance(ids); return baseMapper.deleteByIds(ids) > 0; } /** - * 总体流程监听(例如: 提交 退回 撤销 终止 作废等) - * 正常使用只需#processEvent.key=='leave1' + * 总体流程监听(例如: 草稿,撤销,退回,作废,终止,已完成等) + * 正常使用只需#processEvent.flowCode=='leave1' * 示例为了方便则使用startsWith匹配了全部示例key * * @param processEvent 参数 */ - @EventListener(condition = "#processEvent.key.startsWith('leave')") + @EventListener(condition = "#processEvent.flowCode.startsWith('leave')") public void processHandler(ProcessEvent processEvent) { log.info("当前任务执行了{}", processEvent.toString()); - TestLeave testLeave = baseMapper.selectById(Long.valueOf(processEvent.getBusinessKey())); + TestLeave testLeave = baseMapper.selectById(Long.valueOf(processEvent.getBusinessId())); testLeave.setStatus(processEvent.getStatus()); if (processEvent.isSubmit()) { testLeave.setStatus(BusinessStatusEnum.WAITING.getStatus()); @@ -134,24 +137,37 @@ public class TestLeaveServiceImpl implements ITestLeaveService { /** * 执行办理任务监听 - * 示例:也可通过 @EventListener(condition = "#processTaskEvent.key=='leave1'")进行判断 + * 示例:也可通过 @EventListener(condition = "#processTaskEvent.flowCode=='leave1'")进行判断 * 在方法中判断流程节点key - * if ("xxx".equals(processTaskEvent.getTaskDefinitionKey())) { + * if ("xxx".equals(processTaskEvent.getNodeCode())) { * //执行业务逻辑 * } * * @param processTaskEvent 参数 */ - @EventListener(condition = "#processTaskEvent.key.startsWith('leave')") + @EventListener(condition = "#processTaskEvent.flowCode.startsWith('leave')") public void processTaskHandler(ProcessTaskEvent processTaskEvent) { - // 所有demo案例的申请人节点id - String[] ids = {"Activity_14633hx", "Activity_19b1i4j", "Activity_0uscrk3", - "Activity_0uscrk3", "Activity_0x6b71j", "Activity_0zy3g6j", "Activity_06a55t0"}; - if (StringUtils.equalsAny(processTaskEvent.getTaskDefinitionKey(), ids)) { - log.info("当前任务执行了{}", processTaskEvent.toString()); - TestLeave testLeave = baseMapper.selectById(Long.valueOf(processTaskEvent.getBusinessKey())); - testLeave.setStatus(BusinessStatusEnum.WAITING.getStatus()); - baseMapper.updateById(testLeave); - } + log.info("当前任务执行了{}", processTaskEvent.toString()); + TestLeave testLeave = baseMapper.selectById(Long.valueOf(processTaskEvent.getBusinessId())); + testLeave.setStatus(BusinessStatusEnum.WAITING.getStatus()); + baseMapper.updateById(testLeave); } + + /** + * 监听删除流程事件 + * 正常使用只需#processDeleteEvent.flowCode=='leave1' + * 示例为了方便则使用startsWith匹配了全部示例key + * + * @param processDeleteEvent 参数 + */ + @EventListener(condition = "#processDeleteEvent.flowCode.startsWith('leave')") + public void processDeleteHandler(ProcessDeleteEvent processDeleteEvent) { + log.info("监听删除流程事件,当前任务执行了{}", processDeleteEvent.toString()); + TestLeave testLeave = baseMapper.selectById(Long.valueOf(processDeleteEvent.getBusinessId())); + if (ObjectUtil.isNull(testLeave)) { + return; + } + baseMapper.deleteById(testLeave.getId()); + } + } diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WfCategoryServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WfCategoryServiceImpl.java deleted file mode 100644 index e5628232b..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WfCategoryServiceImpl.java +++ /dev/null @@ -1,130 +0,0 @@ -package org.dromara.workflow.service.impl; - -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.core.toolkit.Wrappers; -import lombok.RequiredArgsConstructor; -import org.dromara.common.core.utils.MapstructUtils; -import org.dromara.common.core.utils.StringUtils; -import org.dromara.workflow.domain.WfCategory; -import org.dromara.workflow.domain.bo.WfCategoryBo; -import org.dromara.workflow.domain.vo.WfCategoryVo; -import org.dromara.workflow.mapper.WfCategoryMapper; -import org.dromara.workflow.service.IWfCategoryService; -import org.dromara.workflow.utils.QueryUtils; -import org.flowable.engine.RepositoryService; -import org.flowable.engine.repository.Deployment; -import org.flowable.engine.repository.Model; -import org.flowable.engine.repository.ProcessDefinition; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.util.Collection; -import java.util.List; - -/** - * 流程分类Service业务层处理 - * - * @author may - * @date 2023-06-28 - */ -@RequiredArgsConstructor -@Service -public class WfCategoryServiceImpl implements IWfCategoryService { - - private final WfCategoryMapper baseMapper; - @Autowired(required = false) - private RepositoryService repositoryService; - - /** - * 查询流程分类 - */ - @Override - public WfCategoryVo queryById(Long id) { - return baseMapper.selectVoById(id); - } - - - /** - * 查询流程分类列表 - */ - @Override - public List queryList(WfCategoryBo bo) { - LambdaQueryWrapper lqw = buildQueryWrapper(bo); - return baseMapper.selectVoList(lqw); - } - - private LambdaQueryWrapper buildQueryWrapper(WfCategoryBo bo) { - LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); - lqw.like(StringUtils.isNotBlank(bo.getCategoryName()), WfCategory::getCategoryName, bo.getCategoryName()); - lqw.eq(StringUtils.isNotBlank(bo.getCategoryCode()), WfCategory::getCategoryCode, bo.getCategoryCode()); - return lqw; - } - - /** - * 新增流程分类 - */ - @Override - public Boolean insertByBo(WfCategoryBo bo) { - WfCategory add = MapstructUtils.convert(bo, WfCategory.class); - validEntityBeforeSave(add); - boolean flag = baseMapper.insert(add) > 0; - if (flag) { - bo.setId(add.getId()); - } - return flag; - } - - /** - * 修改流程分类 - */ - @Override - @Transactional(rollbackFor = Exception.class) - public Boolean updateByBo(WfCategoryBo bo) { - WfCategory update = MapstructUtils.convert(bo, WfCategory.class); - validEntityBeforeSave(update); - WfCategoryVo wfCategoryVo = baseMapper.selectVoById(bo.getId()); - List processDefinitionList = QueryUtils.definitionQuery().processDefinitionCategory(wfCategoryVo.getCategoryCode()).list(); - for (ProcessDefinition processDefinition : processDefinitionList) { - repositoryService.setProcessDefinitionCategory(processDefinition.getId(), bo.getCategoryCode()); - } - List deploymentList = QueryUtils.deploymentQuery().deploymentCategory(wfCategoryVo.getCategoryCode()).list(); - for (Deployment deployment : deploymentList) { - repositoryService.setDeploymentCategory(deployment.getId(), bo.getCategoryCode()); - } - List modelList = QueryUtils.modelQuery().modelCategory(wfCategoryVo.getCategoryCode()).list(); - for (Model model : modelList) { - model.setCategory(bo.getCategoryCode()); - repositoryService.saveModel(model); - } - return baseMapper.updateById(update) > 0; - } - - /** - * 保存前的数据校验 - */ - private void validEntityBeforeSave(WfCategory entity) { - //TODO 做一些数据校验,如唯一约束 - } - - /** - * 批量删除流程分类 - */ - @Override - public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) { - if (isValid) { - //TODO 做一些业务上的校验,判断是否需要校验 - } - return baseMapper.deleteByIds(ids) > 0; - } - - /** - * 按照类别编码查询 - * - * @param categoryCode 分类比吗 - */ - @Override - public WfCategory queryByCategoryCode(String categoryCode) { - return baseMapper.selectOne(new LambdaQueryWrapper().eq(WfCategory::getCategoryCode, categoryCode)); - } -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WfDefinitionConfigServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WfDefinitionConfigServiceImpl.java deleted file mode 100644 index b2ffb9ef9..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WfDefinitionConfigServiceImpl.java +++ /dev/null @@ -1,117 +0,0 @@ -package org.dromara.workflow.service.impl; - -import cn.hutool.core.collection.CollUtil; -import org.dromara.common.core.utils.MapstructUtils; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import lombok.RequiredArgsConstructor; -import org.dromara.workflow.domain.WfDefinitionConfig; -import org.dromara.workflow.domain.bo.WfDefinitionConfigBo; -import org.dromara.workflow.domain.vo.WfDefinitionConfigVo; -import org.dromara.workflow.service.IWfDefinitionConfigService; -import org.springframework.stereotype.Service; -import org.dromara.workflow.mapper.WfDefinitionConfigMapper; -import org.springframework.transaction.annotation.Transactional; - -import java.util.List; -import java.util.Collection; - -/** - * 流程定义配置Service业务层处理 - * - * @author may - * @date 2024-03-18 - */ -@RequiredArgsConstructor -@Service -public class WfDefinitionConfigServiceImpl implements IWfDefinitionConfigService { - - private final WfDefinitionConfigMapper baseMapper; - - /** - * 查询流程定义配置 - */ - @Override - public WfDefinitionConfigVo getByDefId(String definitionId) { - return baseMapper.selectVoOne(new LambdaQueryWrapper().eq(WfDefinitionConfig::getDefinitionId, definitionId)); - } - - /** - * 查询流程定义配置 - * - * @param tableName 表名 - * @return 结果 - */ - @Override - public WfDefinitionConfigVo getByTableNameLastVersion(String tableName) { - List wfDefinitionConfigVos = baseMapper.selectVoList( - new LambdaQueryWrapper().eq(WfDefinitionConfig::getTableName, tableName).orderByDesc(WfDefinitionConfig::getVersion)); - if (CollUtil.isNotEmpty(wfDefinitionConfigVos)) { - return wfDefinitionConfigVos.get(0); - } - return null; - } - - /** - * 查询流程定义配置 - * - * @param definitionId 流程定义id - * @param tableName 表名 - * @return 结果 - */ - @Override - public WfDefinitionConfigVo getByDefIdAndTableName(String definitionId, String tableName) { - return baseMapper.selectVoOne(new LambdaQueryWrapper() - .eq(WfDefinitionConfig::getDefinitionId, definitionId) - .eq(WfDefinitionConfig::getTableName, tableName)); - } - - /** - * 查询流程定义配置排除当前查询的流程定义 - * - * @param tableName 表名 - * @param definitionId 流程定义id - */ - @Override - public List getByTableNameNotDefId(String tableName, String definitionId) { - return baseMapper.selectVoList(new LambdaQueryWrapper() - .eq(WfDefinitionConfig::getTableName, tableName) - .ne(WfDefinitionConfig::getDefinitionId, definitionId)); - } - - /** - * 查询流程定义配置列表 - */ - @Override - public List queryList(List definitionIds) { - return baseMapper.selectVoList(new LambdaQueryWrapper().in(WfDefinitionConfig::getDefinitionId, definitionIds)); - } - - /** - * 新增流程定义配置 - */ - @Override - @Transactional(rollbackFor = Exception.class) - public Boolean saveOrUpdate(WfDefinitionConfigBo bo) { - WfDefinitionConfig add = MapstructUtils.convert(bo, WfDefinitionConfig.class); - baseMapper.delete(new LambdaQueryWrapper().eq(WfDefinitionConfig::getTableName, bo.getTableName())); - add.setTableName(add.getTableName().toLowerCase()); - boolean flag = baseMapper.insertOrUpdate(add); - if (flag) { - bo.setId(add.getId()); - } - return flag; - } - - /** - * 批量删除流程定义配置 - */ - @Override - public Boolean deleteByIds(Collection ids) { - return baseMapper.deleteByIds(ids) > 0; - } - - @Override - public Boolean deleteByDefIds(Collection ids) { - return baseMapper.delete(new LambdaQueryWrapper().in(WfDefinitionConfig::getDefinitionId, ids)) > 0; - } -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WfFormManageServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WfFormManageServiceImpl.java deleted file mode 100644 index 55e491178..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WfFormManageServiceImpl.java +++ /dev/null @@ -1,111 +0,0 @@ -package org.dromara.workflow.service.impl; - -import org.dromara.common.core.utils.MapstructUtils; -import org.dromara.common.core.utils.StringUtils; -import org.dromara.common.mybatis.core.page.TableDataInfo; -import org.dromara.common.mybatis.core.page.PageQuery; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.core.toolkit.Wrappers; -import lombok.RequiredArgsConstructor; -import org.dromara.workflow.common.enums.FormTypeEnum; -import org.springframework.stereotype.Service; -import org.dromara.workflow.domain.bo.WfFormManageBo; -import org.dromara.workflow.domain.vo.WfFormManageVo; -import org.dromara.workflow.domain.WfFormManage; -import org.dromara.workflow.mapper.WfFormManageMapper; -import org.dromara.workflow.service.IWfFormManageService; - -import java.util.List; -import java.util.Collection; - -/** - * 表单管理Service业务层处理 - * - * @author may - * @date 2024-03-29 - */ -@RequiredArgsConstructor -@Service -public class WfFormManageServiceImpl implements IWfFormManageService { - - private final WfFormManageMapper baseMapper; - - /** - * 查询表单管理 - */ - @Override - public WfFormManageVo queryById(Long id) { - return baseMapper.selectVoById(id); - } - - @Override - public List queryByIds(List ids) { - return baseMapper.selectVoByIds(ids); - } - - /** - * 查询表单管理列表 - */ - @Override - public TableDataInfo queryPageList(WfFormManageBo bo, PageQuery pageQuery) { - LambdaQueryWrapper lqw = buildQueryWrapper(bo); - Page result = baseMapper.selectVoPage(pageQuery.build(), lqw); - return TableDataInfo.build(result); - } - - @Override - public List selectList() { - List wfFormManageVos = baseMapper.selectVoList(new LambdaQueryWrapper().orderByDesc(WfFormManage::getUpdateTime)); - for (WfFormManageVo wfFormManageVo : wfFormManageVos) { - wfFormManageVo.setFormTypeName(FormTypeEnum.findByType(wfFormManageVo.getFormType())); - } - return wfFormManageVos; - } - - /** - * 查询表单管理列表 - */ - @Override - public List queryList(WfFormManageBo bo) { - LambdaQueryWrapper lqw = buildQueryWrapper(bo); - return baseMapper.selectVoList(lqw); - } - - private LambdaQueryWrapper buildQueryWrapper(WfFormManageBo bo) { - LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); - lqw.like(StringUtils.isNotBlank(bo.getFormName()), WfFormManage::getFormName, bo.getFormName()); - lqw.eq(StringUtils.isNotBlank(bo.getFormType()), WfFormManage::getFormType, bo.getFormType()); - return lqw; - } - - /** - * 新增表单管理 - */ - @Override - public Boolean insertByBo(WfFormManageBo bo) { - WfFormManage add = MapstructUtils.convert(bo, WfFormManage.class); - boolean flag = baseMapper.insert(add) > 0; - if (flag) { - bo.setId(add.getId()); - } - return flag; - } - - /** - * 修改表单管理 - */ - @Override - public Boolean updateByBo(WfFormManageBo bo) { - WfFormManage update = MapstructUtils.convert(bo, WfFormManage.class); - return baseMapper.updateById(update) > 0; - } - - /** - * 批量删除表单管理 - */ - @Override - public Boolean deleteByIds(Collection ids) { - return baseMapper.deleteByIds(ids) > 0; - } -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WfNodeConfigServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WfNodeConfigServiceImpl.java deleted file mode 100644 index 2f71482fa..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WfNodeConfigServiceImpl.java +++ /dev/null @@ -1,75 +0,0 @@ -package org.dromara.workflow.service.impl; - -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.util.ObjectUtil; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import lombok.RequiredArgsConstructor; -import org.dromara.common.core.utils.StreamUtils; -import org.dromara.workflow.domain.vo.WfFormManageVo; -import org.dromara.workflow.service.IWfFormManageService; -import org.springframework.stereotype.Service; -import org.dromara.workflow.domain.vo.WfNodeConfigVo; -import org.dromara.workflow.domain.WfNodeConfig; -import org.dromara.workflow.mapper.WfNodeConfigMapper; -import org.dromara.workflow.service.IWfNodeConfigService; - -import java.util.Collection; -import java.util.List; - -/** - * 节点配置Service业务层处理 - * - * @author may - * @date 2024-03-30 - */ -@RequiredArgsConstructor -@Service -public class WfNodeConfigServiceImpl implements IWfNodeConfigService { - - private final WfNodeConfigMapper baseMapper; - private final IWfFormManageService wfFormManageService; - - /** - * 查询节点配置 - */ - @Override - public WfNodeConfigVo queryById(Long id) { - return baseMapper.selectVoById(id); - } - - /** - * 保存节点配置 - */ - @Override - public Boolean saveOrUpdate(List list) { - return baseMapper.insertOrUpdateBatch(list); - } - - /** - * 批量删除节点配置 - */ - @Override - public Boolean deleteByIds(Collection ids) { - return baseMapper.deleteByIds(ids) > 0; - } - - - - @Override - public Boolean deleteByDefIds(Collection ids) { - return baseMapper.delete(new LambdaQueryWrapper().in(WfNodeConfig::getDefinitionId, ids)) > 0; - } - - @Override - public List selectByDefIds(Collection ids) { - List wfNodeConfigVos = baseMapper.selectVoList(new LambdaQueryWrapper().in(WfNodeConfig::getDefinitionId, ids)); - if (CollUtil.isNotEmpty(wfNodeConfigVos)) { - List formIds = StreamUtils.toList(wfNodeConfigVos, WfNodeConfigVo::getFormId); - List wfFormManageVos = wfFormManageService.queryByIds(formIds); - for (WfNodeConfigVo wfNodeConfigVo : wfNodeConfigVos) { - wfFormManageVos.stream().filter(e -> ObjectUtil.equals(e.getId(), wfNodeConfigVo.getFormId())).findFirst().ifPresent(wfNodeConfigVo::setWfFormManageVo); - } - } - return wfNodeConfigVos; - } -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WfTaskBackNodeServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WfTaskBackNodeServiceImpl.java deleted file mode 100644 index 6c255d3b0..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WfTaskBackNodeServiceImpl.java +++ /dev/null @@ -1,144 +0,0 @@ -package org.dromara.workflow.service.impl; - -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.util.ObjectUtil; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.dromara.common.core.exception.ServiceException; -import org.dromara.common.core.utils.StreamUtils; -import org.dromara.common.core.utils.StringUtils; -import org.dromara.common.satoken.utils.LoginHelper; -import org.dromara.workflow.domain.WfTaskBackNode; -import org.dromara.workflow.domain.vo.MultiInstanceVo; -import org.dromara.workflow.mapper.WfTaskBackNodeMapper; -import org.dromara.workflow.service.IWfTaskBackNodeService; -import org.dromara.workflow.utils.WorkflowUtils; -import org.flowable.task.api.Task; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.util.ArrayList; -import java.util.List; - -import static org.dromara.workflow.common.constant.FlowConstant.MULTI_INSTANCE; -import static org.dromara.workflow.common.constant.FlowConstant.USER_TASK; - - -/** - * 节点驳回记录Service业务层处理 - * - * @author may - * @date 2024-03-13 - */ -@Slf4j -@RequiredArgsConstructor -@Service -public class WfTaskBackNodeServiceImpl implements IWfTaskBackNodeService { - - private final WfTaskBackNodeMapper wfTaskBackNodeMapper; - - @Override - @Transactional(rollbackFor = Exception.class) - public void recordExecuteNode(Task task) { - List list = getListByInstanceId(task.getProcessInstanceId()); - WfTaskBackNode wfTaskBackNode = new WfTaskBackNode(); - wfTaskBackNode.setNodeId(task.getTaskDefinitionKey()); - wfTaskBackNode.setNodeName(task.getName()); - wfTaskBackNode.setInstanceId(task.getProcessInstanceId()); - wfTaskBackNode.setAssignee(String.valueOf(LoginHelper.getUserId())); - MultiInstanceVo multiInstance = WorkflowUtils.isMultiInstance(task.getProcessDefinitionId(), task.getTaskDefinitionKey()); - if (ObjectUtil.isNotEmpty(multiInstance)) { - wfTaskBackNode.setTaskType(MULTI_INSTANCE); - } else { - wfTaskBackNode.setTaskType(USER_TASK); - } - if (CollUtil.isEmpty(list)) { - wfTaskBackNode.setOrderNo(0); - wfTaskBackNodeMapper.insert(wfTaskBackNode); - } else { - WfTaskBackNode taskNode = StreamUtils.findFirst(list, e -> e.getNodeId().equals(wfTaskBackNode.getNodeId()) && e.getOrderNo() == 0); - if (ObjectUtil.isEmpty(taskNode)) { - wfTaskBackNode.setOrderNo(list.get(0).getOrderNo() + 1); - WfTaskBackNode node = getListByInstanceIdAndNodeId(wfTaskBackNode.getInstanceId(), wfTaskBackNode.getNodeId()); - if (ObjectUtil.isNotEmpty(node)) { - node.setAssignee(node.getAssignee() + StringUtils.SEPARATOR + LoginHelper.getUserId()); - wfTaskBackNodeMapper.updateById(node); - } else { - wfTaskBackNodeMapper.insert(wfTaskBackNode); - } - } - } - } - - @Override - public List getListByInstanceId(String processInstanceId) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(WfTaskBackNode::getInstanceId, processInstanceId); - wrapper.orderByDesc(WfTaskBackNode::getOrderNo); - return wfTaskBackNodeMapper.selectList(wrapper); - } - - @Override - public WfTaskBackNode getListByInstanceIdAndNodeId(String processInstanceId, String nodeId) { - LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); - queryWrapper.eq(WfTaskBackNode::getInstanceId, processInstanceId); - queryWrapper.eq(WfTaskBackNode::getNodeId, nodeId); - return wfTaskBackNodeMapper.selectOne(queryWrapper); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public boolean deleteBackTaskNode(String processInstanceId, String targetActivityId) { - try { - LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); - queryWrapper.eq(WfTaskBackNode::getInstanceId, processInstanceId); - queryWrapper.eq(WfTaskBackNode::getNodeId, targetActivityId); - WfTaskBackNode actTaskNode = wfTaskBackNodeMapper.selectOne(queryWrapper); - if (ObjectUtil.isNotNull(actTaskNode)) { - Integer orderNo = actTaskNode.getOrderNo(); - List taskNodeList = getListByInstanceId(processInstanceId); - List ids = new ArrayList<>(); - if (CollUtil.isNotEmpty(taskNodeList)) { - for (WfTaskBackNode taskNode : taskNodeList) { - if (taskNode.getOrderNo() >= orderNo) { - ids.add(taskNode.getId()); - } - } - } - if (CollUtil.isNotEmpty(ids)) { - wfTaskBackNodeMapper.deleteByIds(ids); - } - } - return true; - } catch (Exception e) { - log.error(e.getMessage(), e); - throw new ServiceException("删除失败"); - } - } - - @Override - @Transactional(rollbackFor = Exception.class) - public boolean deleteByInstanceId(String processInstanceId) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(WfTaskBackNode::getInstanceId, processInstanceId); - List list = wfTaskBackNodeMapper.selectList(wrapper); - int delete = wfTaskBackNodeMapper.delete(wrapper); - if (list.size() != delete) { - throw new ServiceException("删除失败"); - } - return true; - } - - @Override - public boolean deleteByInstanceIds(List processInstanceIds) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.in(WfTaskBackNode::getInstanceId, processInstanceIds); - List list = wfTaskBackNodeMapper.selectList(wrapper); - int delete = wfTaskBackNodeMapper.delete(wrapper); - if (list.size() != delete) { - throw new ServiceException("删除失败"); - } - return true; - } -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WorkflowServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WorkflowServiceImpl.java index b03658444..d00c90735 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WorkflowServiceImpl.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WorkflowServiceImpl.java @@ -1,14 +1,18 @@ package org.dromara.workflow.service.impl; -import cn.hutool.core.util.StrUtil; +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.util.ObjectUtil; import lombok.RequiredArgsConstructor; +import org.dromara.common.core.domain.dto.CompleteTaskDTO; +import org.dromara.common.core.domain.dto.StartProcessDTO; import org.dromara.common.core.service.WorkflowService; -import org.dromara.workflow.domain.ActHiProcinst; -import org.dromara.workflow.service.IActHiProcinstService; -import org.dromara.workflow.service.IActProcessInstanceService; -import org.dromara.workflow.utils.WorkflowUtils; -import org.flowable.engine.TaskService; -import org.springframework.beans.factory.annotation.Autowired; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.warm.flow.orm.entity.FlowInstance; +import org.dromara.workflow.domain.bo.CompleteTaskBo; +import org.dromara.workflow.domain.bo.StartProcessBo; +import org.dromara.workflow.service.IFlwDefinitionService; +import org.dromara.workflow.service.IFlwInstanceService; +import org.dromara.workflow.service.IFlwTaskService; import org.springframework.stereotype.Service; import java.util.List; @@ -23,19 +27,19 @@ import java.util.Map; @Service public class WorkflowServiceImpl implements WorkflowService { - @Autowired(required = false) - private TaskService taskService; - private final IActProcessInstanceService actProcessInstanceService; - private final IActHiProcinstService actHiProcinstService; + private final IFlwInstanceService flwInstanceService; + private final IFlwDefinitionService flwDefinitionService; + private final IFlwTaskService flwTaskService; + /** - * 运行中的实例 删除程实例,删除历史记录,删除业务与流程关联信息 + * 删除流程实例 * - * @param businessKeys 业务id + * @param businessIds 业务id * @return 结果 */ @Override - public boolean deleteRunAndHisInstance(List businessKeys) { - return actProcessInstanceService.deleteRunAndHisInstance(businessKeys); + public boolean deleteInstance(List businessIds) { + return flwInstanceService.deleteByBusinessIds(businessIds); } /** @@ -44,78 +48,72 @@ public class WorkflowServiceImpl implements WorkflowService { * @param taskId 任务id */ @Override - public String getBusinessStatusByTaskId(String taskId) { - return WorkflowUtils.getBusinessStatusByTaskId(taskId); + public String getBusinessStatusByTaskId(Long taskId) { + FlowInstance flowInstance = flwInstanceService.selectByTaskId(taskId); + return ObjectUtil.isNotNull(flowInstance) ? flowInstance.getFlowStatus() : StringUtils.EMPTY; } /** * 获取当前流程状态 * - * @param businessKey 业务id + * @param businessId 业务id */ @Override - public String getBusinessStatus(String businessKey) { - return WorkflowUtils.getBusinessStatus(businessKey); + public String getBusinessStatus(String businessId) { + FlowInstance flowInstance = flwInstanceService.selectInstByBusinessId(businessId); + return ObjectUtil.isNotNull(flowInstance) ? flowInstance.getFlowStatus() : StringUtils.EMPTY; } /** - * 设置流程变量(全局变量) + * 设置流程变量 * - * @param taskId 任务id - * @param variableName 变量名称 - * @param value 变量值 + * @param instanceId 流程实例id + * @param variables 流程变量 */ @Override - public void setVariable(String taskId, String variableName, Object value) { - taskService.setVariable(taskId, variableName, value); - } - - /** - * 设置流程变量(全局变量) - * - * @param taskId 任务id - * @param variables 流程变量 - */ - @Override - public void setVariables(String taskId, Map variables) { - taskService.setVariables(taskId, variables); - } - - /** - * 设置流程变量(本地变量,非全局变量) - * - * @param taskId 任务id - * @param variableName 变量名称 - * @param value 变量值 - */ - @Override - public void setVariableLocal(String taskId, String variableName, Object value) { - taskService.setVariableLocal(taskId, variableName, value); - } - - /** - * 设置流程变量(本地变量,非全局变量) - * - * @param taskId 任务id - * @param variables 流程变量 - */ - @Override - public void setVariablesLocal(String taskId, Map variables) { - taskService.setVariablesLocal(taskId, variables); + public void setVariable(Long instanceId, Map variables) { + flwInstanceService.setVariable(instanceId, variables); } /** * 按照业务id查询流程实例id * - * @param businessKey 业务id + * @param businessId 业务id * @return 结果 */ @Override - public String getInstanceIdByBusinessKey(String businessKey) { - ActHiProcinst actHiProcinst = actHiProcinstService.selectByBusinessKey(businessKey); - if (actHiProcinst == null) { - return StrUtil.EMPTY; - } - return actHiProcinst.getId(); + public Long getInstanceIdByBusinessId(String businessId) { + FlowInstance flowInstance = flwInstanceService.selectInstByBusinessId(businessId); + return ObjectUtil.isNotNull(flowInstance) ? flowInstance.getId() : null; + } + + /** + * 新增租户流程定义 + * + * @param tenantId 租户id + */ + @Override + public void syncDef(String tenantId) { + flwDefinitionService.syncDef(tenantId); + } + + /** + * 启动流程 + * + * @param startProcess 参数 + */ + @Override + public Map startWorkFlow(StartProcessDTO startProcess) { + return flwTaskService.startWorkFlow(BeanUtil.toBean(startProcess, StartProcessBo.class)); + } + + /** + * 办理任务 + * + * @param completeTask 参数 + */ + @Override + public boolean completeTask(CompleteTaskDTO completeTask) { + return flwTaskService.completeTask(BeanUtil.toBean(completeTask, CompleteTaskBo.class)); } } diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/utils/ModelUtils.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/utils/ModelUtils.java deleted file mode 100644 index 7c5377ed7..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/utils/ModelUtils.java +++ /dev/null @@ -1,289 +0,0 @@ -package org.dromara.workflow.utils; - -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.collection.CollectionUtil; -import cn.hutool.core.io.IoUtil; -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.core.util.StrUtil; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; -import org.dromara.common.core.utils.SpringUtils; -import org.dromara.common.core.utils.StreamUtils; -import org.dromara.common.core.utils.StringUtils; -import org.dromara.common.json.utils.JsonUtils; -import org.dromara.workflow.domain.vo.MultiInstanceVo; -import org.flowable.bpmn.converter.BpmnXMLConverter; -import org.flowable.bpmn.model.*; -import org.flowable.bpmn.model.Process; -import org.flowable.editor.language.json.converter.BpmnJsonConverter; -import org.flowable.engine.ProcessEngine; - -import javax.xml.stream.XMLInputFactory; -import javax.xml.stream.XMLStreamException; -import javax.xml.stream.XMLStreamReader; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.rmi.ServerException; -import java.util.*; -import java.util.stream.Collectors; - -/** - * 模型工具 - * - * @author may - */ -@NoArgsConstructor(access = AccessLevel.PRIVATE) -public class ModelUtils { - - private static final ProcessEngine PROCESS_ENGINE = SpringUtils.getBean(ProcessEngine.class); - - public static BpmnModel xmlToBpmnModel(String xml) throws IOException { - if (xml == null) { - throw new ServerException("xml不能为空"); - } - try { - InputStream inputStream = new ByteArrayInputStream(StrUtil.utf8Bytes(xml)); - XMLInputFactory factory = XMLInputFactory.newInstance(); - XMLStreamReader reader = factory.createXMLStreamReader(inputStream); - return new BpmnXMLConverter().convertToBpmnModel(reader); - } catch (XMLStreamException e) { - throw new ServerException(e.getMessage()); - } - } - - /** - * bpmnModel转为xml - * - * @param jsonBytes json - */ - public static byte[] bpmnJsonToXmlBytes(byte[] jsonBytes) throws IOException { - if (jsonBytes == null) { - return new byte[0]; - } - // 1. json字节码转成 BpmnModel 对象 - ObjectMapper objectMapper = JsonUtils.getObjectMapper(); - JsonNode jsonNode = objectMapper.readTree(jsonBytes); - BpmnModel bpmnModel = new BpmnJsonConverter().convertToBpmnModel(jsonNode); - - if (bpmnModel.getProcesses().isEmpty()) { - return new byte[0]; - } - // 2.将bpmnModel转为xml - return new BpmnXMLConverter().convertToXML(bpmnModel); - } - - /** - * xml转为bpmnModel - * - * @param xmlBytes xml - */ - public static BpmnModel xmlToBpmnModel(byte[] xmlBytes) throws XMLStreamException { - ByteArrayInputStream byteArrayInputStream = IoUtil.toStream(xmlBytes); - XMLInputFactory xif = XMLInputFactory.newInstance(); - XMLStreamReader xtr = xif.createXMLStreamReader(byteArrayInputStream); - return new BpmnXMLConverter().convertToBpmnModel(xtr); - } - - /** - * 校验模型 - * - * @param bpmnModel bpmn模型 - */ - public static void checkBpmnModel(BpmnModel bpmnModel) throws ServerException { - Collection flowElements = bpmnModel.getMainProcess().getFlowElements(); - - checkBpmnNode(flowElements, false); - - List subProcessList = flowElements.stream().filter(SubProcess.class::isInstance).map(SubProcess.class::cast).collect(Collectors.toList()); - if (!CollUtil.isEmpty(subProcessList)) { - for (SubProcess subProcess : subProcessList) { - Collection subProcessFlowElements = subProcess.getFlowElements(); - checkBpmnNode(subProcessFlowElements, true); - } - } - List multiInstanceVoList = new ArrayList<>(); - for (FlowElement flowElement : flowElements) { - if (flowElement instanceof UserTask && ObjectUtil.isNotEmpty(((UserTask) flowElement).getLoopCharacteristics()) && StringUtils.isNotBlank(((UserTask) flowElement).getLoopCharacteristics().getInputDataItem())) { - MultiInstanceVo multiInstanceVo = new MultiInstanceVo(); - multiInstanceVo.setAssigneeList(((UserTask) flowElement).getLoopCharacteristics().getInputDataItem()); - multiInstanceVoList.add(multiInstanceVo); - } - } - - if (CollectionUtil.isNotEmpty(multiInstanceVoList) && multiInstanceVoList.size() > 1) { - Map> assigneeListGroup = StreamUtils.groupByKey(multiInstanceVoList, MultiInstanceVo::getAssigneeList); - for (Map.Entry> entry : assigneeListGroup.entrySet()) { - List value = entry.getValue(); - if (CollectionUtil.isNotEmpty(value) && value.size() > 1) { - String key = entry.getKey(); - throw new ServerException("会签人员集合【" + key + "】重复,请重新设置集合KEY"); - } - } - } - } - - /** - * 校验bpmn节点是否合法 - * - * @param flowElements 节点集合 - * @param subtask 是否子流程 - */ - private static void checkBpmnNode(Collection flowElements, boolean subtask) throws ServerException { - - if (CollUtil.isEmpty(flowElements)) { - throw new ServerException(subtask ? "子流程必须存在节点" : "必须存在节点!"); - } - - List startEventList = flowElements.stream().filter(StartEvent.class::isInstance).map(StartEvent.class::cast).collect(Collectors.toList()); - if (CollUtil.isEmpty(startEventList)) { - throw new ServerException(subtask ? "子流程必须存在开始节点" : "必须存在开始节点!"); - } - - if (startEventList.size() > 1) { - throw new ServerException(subtask ? "子流程只能存在一个开始节点" : "只能存在一个开始节点!"); - } - - StartEvent startEvent = startEventList.get(0); - List outgoingFlows = startEvent.getOutgoingFlows(); - if (CollUtil.isEmpty(outgoingFlows)) { - throw new ServerException(subtask ? "子流程流程节点为空,请至少设计一条主线流程!" : "流程节点为空,请至少设计一条主线流程!"); - } - - FlowElement targetFlowElement = outgoingFlows.get(0).getTargetFlowElement(); - if (!(targetFlowElement instanceof UserTask) && !subtask) { - throw new ServerException("开始节点后第一个节点必须是用户任务!"); - } - //开始节点后第一个节点申请人节点 - if ((targetFlowElement instanceof UserTask) && !subtask) { - UserTask userTask = (UserTask) targetFlowElement; - if (StringUtils.isBlank(userTask.getFormKey())) { - throw new ServerException("申请人节点必须选择表单!"); - } - } - List endEventList = flowElements.stream().filter(EndEvent.class::isInstance).map(EndEvent.class::cast).collect(Collectors.toList()); - if (CollUtil.isEmpty(endEventList)) { - throw new ServerException(subtask ? "子流程必须存在结束节点!" : "必须存在结束节点!"); - } - } - - /** - * 获取流程全部用户节点 - * - * @param processDefinitionId 流程定义id - */ - public static List getUserTaskFlowElements(String processDefinitionId) { - BpmnModel bpmnModel = PROCESS_ENGINE.getRepositoryService().getBpmnModel(processDefinitionId); - List list = new ArrayList<>(); - List processes = bpmnModel.getProcesses(); - Collection flowElements = processes.get(0).getFlowElements(); - buildUserTaskFlowElements(flowElements, list); - return list; - } - - /** - * 递归获取所有节点 - * - * @param flowElements 节点信息 - * @param list 集合 - */ - private static void buildUserTaskFlowElements(Collection flowElements, List list) { - for (FlowElement flowElement : flowElements) { - if (flowElement instanceof SubProcess) { - Collection subFlowElements = ((SubProcess) flowElement).getFlowElements(); - buildUserTaskFlowElements(subFlowElements, list); - } else if (flowElement instanceof UserTask) { - list.add((UserTask) flowElement); - } - } - } - - /** - * 获取流程全部节点 - * - * @param processDefinitionId 流程定义id - */ - public static List getFlowElements(String processDefinitionId) { - BpmnModel bpmnModel = PROCESS_ENGINE.getRepositoryService().getBpmnModel(processDefinitionId); - List list = new ArrayList<>(); - List processes = bpmnModel.getProcesses(); - Collection flowElements = processes.get(0).getFlowElements(); - buildFlowElements(flowElements, list); - return list; - } - - /** - * 递归获取所有节点 - * - * @param flowElements 节点信息 - * @param list 集合 - */ - private static void buildFlowElements(Collection flowElements, List list) { - for (FlowElement flowElement : flowElements) { - list.add(flowElement); - if (flowElement instanceof SubProcess) { - Collection subFlowElements = ((SubProcess) flowElement).getFlowElements(); - buildFlowElements(subFlowElements, list); - } - } - } - - /** - * 获取全部扩展信息 - * - * @param processDefinitionId 流程定义id - */ - public static Map> getExtensionElements(String processDefinitionId) { - Map> map = new HashMap<>(); - List flowElements = getFlowElements(processDefinitionId); - for (FlowElement flowElement : flowElements) { - if (flowElement instanceof UserTask && CollUtil.isNotEmpty(flowElement.getExtensionElements())) { - map.putAll(flowElement.getExtensionElements()); - } - } - return map; - } - - /** - * 获取某个节点的扩展信息 - * - * @param processDefinitionId 流程定义id - * @param flowElementId 节点id - */ - public static Map> getExtensionElement(String processDefinitionId, String flowElementId) { - BpmnModel bpmnModel = PROCESS_ENGINE.getRepositoryService().getBpmnModel(processDefinitionId); - Process process = bpmnModel.getMainProcess(); - FlowElement flowElement = process.getFlowElement(flowElementId); - return flowElement.getExtensionElements(); - } - - /** - * 判断当前节点是否为用户任务 - * - * @param processDefinitionId 流程定义id - * @param taskDefinitionKey 流程定义id - */ - public static boolean isUserTask(String processDefinitionId, String taskDefinitionKey) { - BpmnModel bpmnModel = PROCESS_ENGINE.getRepositoryService().getBpmnModel(processDefinitionId); - FlowNode flowNode = (FlowNode) bpmnModel.getFlowElement(taskDefinitionKey); - return flowNode instanceof UserTask; - } - - /** - * 获取申请人节点 - * - * @param processDefinitionId 流程定义id - * @return 结果 - */ - public static UserTask getApplyUserTask(String processDefinitionId) { - BpmnModel bpmnModel = PROCESS_ENGINE.getRepositoryService().getBpmnModel(processDefinitionId); - Collection flowElements = bpmnModel.getMainProcess().getFlowElements(); - List startEventList = flowElements.stream().filter(StartEvent.class::isInstance).map(StartEvent.class::cast).collect(Collectors.toList()); - StartEvent startEvent = startEventList.get(0); - List outgoingFlows = startEvent.getOutgoingFlows(); - FlowElement targetFlowElement = outgoingFlows.get(0).getTargetFlowElement(); - return (UserTask) targetFlowElement; - } -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/utils/QueryUtils.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/utils/QueryUtils.java deleted file mode 100644 index df928dc72..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/utils/QueryUtils.java +++ /dev/null @@ -1,169 +0,0 @@ -package org.dromara.workflow.utils; - -import cn.hutool.core.bean.BeanUtil; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; -import org.dromara.common.core.utils.SpringUtils; -import org.dromara.common.tenant.helper.TenantHelper; -import org.dromara.workflow.domain.vo.TaskVo; -import org.flowable.engine.ProcessEngine; -import org.flowable.engine.history.HistoricActivityInstanceQuery; -import org.flowable.engine.history.HistoricProcessInstanceQuery; -import org.flowable.engine.repository.DeploymentQuery; -import org.flowable.engine.repository.ModelQuery; -import org.flowable.engine.repository.ProcessDefinitionQuery; -import org.flowable.engine.runtime.ProcessInstance; -import org.flowable.engine.runtime.ProcessInstanceQuery; -import org.flowable.task.api.Task; -import org.flowable.task.api.TaskQuery; -import org.flowable.task.api.history.HistoricTaskInstanceQuery; - -import java.util.Collection; -import java.util.List; -import java.util.Set; - -/** - * 查询工具 - * - * @author Lion Li - */ -@NoArgsConstructor(access = AccessLevel.PRIVATE) -public class QueryUtils { - - private static final ProcessEngine PROCESS_ENGINE = SpringUtils.getBean(ProcessEngine.class); - - public static ModelQuery modelQuery() { - ModelQuery query = PROCESS_ENGINE.getRepositoryService().createModelQuery(); - if (TenantHelper.isEnable()) { - query.modelTenantId(TenantHelper.getTenantId()); - } - return query; - } - - public static ProcessDefinitionQuery definitionQuery() { - ProcessDefinitionQuery query = PROCESS_ENGINE.getRepositoryService().createProcessDefinitionQuery(); - if (TenantHelper.isEnable()) { - query.processDefinitionTenantId(TenantHelper.getTenantId()); - } - return query; - } - - public static DeploymentQuery deploymentQuery() { - DeploymentQuery query = PROCESS_ENGINE.getRepositoryService().createDeploymentQuery(); - if (TenantHelper.isEnable()) { - query.deploymentTenantId(TenantHelper.getTenantId()); - } - return query; - } - - public static DeploymentQuery deploymentQuery(String deploymentId) { - return deploymentQuery().deploymentId(deploymentId); - } - - public static DeploymentQuery deploymentQuery(List deploymentIds) { - return deploymentQuery().deploymentIds(deploymentIds); - } - - public static HistoricTaskInstanceQuery hisTaskInstanceQuery() { - HistoricTaskInstanceQuery query = PROCESS_ENGINE.getHistoryService().createHistoricTaskInstanceQuery(); - if (TenantHelper.isEnable()) { - query.taskTenantId(TenantHelper.getTenantId()); - } - return query; - } - - public static HistoricTaskInstanceQuery hisTaskInstanceQuery(String processInstanceId) { - return hisTaskInstanceQuery().processInstanceId(processInstanceId); - } - - public static HistoricTaskInstanceQuery hisTaskBusinessKeyQuery(String businessKey) { - return hisTaskInstanceQuery().processInstanceBusinessKey(businessKey); - } - - public static ProcessInstanceQuery instanceQuery() { - ProcessInstanceQuery query = PROCESS_ENGINE.getRuntimeService().createProcessInstanceQuery(); - if (TenantHelper.isEnable()) { - query.processInstanceTenantId(TenantHelper.getTenantId()); - } - return query; - } - - public static ProcessInstanceQuery instanceQuery(String processInstanceId) { - return instanceQuery().processInstanceId(processInstanceId); - } - - public static ProcessInstanceQuery businessKeyQuery(String businessKey) { - return instanceQuery().processInstanceBusinessKey(businessKey); - } - - public static ProcessInstanceQuery instanceQuery(Set processInstanceIds) { - return instanceQuery().processInstanceIds(processInstanceIds); - } - - public static HistoricProcessInstanceQuery hisInstanceQuery() { - HistoricProcessInstanceQuery query = PROCESS_ENGINE.getHistoryService().createHistoricProcessInstanceQuery(); - if (TenantHelper.isEnable()) { - query.processInstanceTenantId(TenantHelper.getTenantId()); - } - return query; - } - - public static HistoricProcessInstanceQuery hisInstanceQuery(String processInstanceId) { - return hisInstanceQuery().processInstanceId(processInstanceId); - } - - public static HistoricProcessInstanceQuery hisBusinessKeyQuery(String businessKey) { - return hisInstanceQuery().processInstanceBusinessKey(businessKey); - } - - public static HistoricProcessInstanceQuery hisInstanceQuery(Set processInstanceIds) { - return hisInstanceQuery().processInstanceIds(processInstanceIds); - } - - public static HistoricActivityInstanceQuery hisActivityInstanceQuery() { - HistoricActivityInstanceQuery query = PROCESS_ENGINE.getHistoryService().createHistoricActivityInstanceQuery(); - if (TenantHelper.isEnable()) { - query.activityTenantId(TenantHelper.getTenantId()); - } - return query; - } - - public static HistoricActivityInstanceQuery hisActivityInstanceQuery(String processInstanceId) { - return hisActivityInstanceQuery().processInstanceId(processInstanceId); - } - - public static TaskQuery taskQuery() { - TaskQuery query = PROCESS_ENGINE.getTaskService().createTaskQuery(); - if (TenantHelper.isEnable()) { - query.taskTenantId(TenantHelper.getTenantId()); - } - return query; - } - - public static TaskQuery taskQuery(String processInstanceId) { - return taskQuery().processInstanceId(processInstanceId); - } - - public static TaskQuery taskQuery(Collection processInstanceIds) { - return taskQuery().processInstanceIdIn(processInstanceIds); - } - - /** - * 按照任务id查询当前任务 - * - * @param taskId 任务id - */ - public static TaskVo getTask(String taskId) { - Task task = PROCESS_ENGINE.getTaskService().createTaskQuery().taskId(taskId).singleResult(); - if (task == null) { - return null; - } - ProcessInstance processInstance = QueryUtils.instanceQuery(task.getProcessInstanceId()).singleResult(); - TaskVo taskVo = BeanUtil.toBean(task, TaskVo.class); - taskVo.setBusinessKey(processInstance.getBusinessKey()); - taskVo.setMultiInstance(WorkflowUtils.isMultiInstance(task.getProcessDefinitionId(), task.getTaskDefinitionKey()) != null); - String businessStatus = WorkflowUtils.getBusinessStatus(taskVo.getBusinessKey()); - taskVo.setBusinessStatus(businessStatus); - return taskVo; - } -} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/utils/WorkflowUtils.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/utils/WorkflowUtils.java index d7c44723b..0bf8f429b 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/utils/WorkflowUtils.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/utils/WorkflowUtils.java @@ -2,43 +2,42 @@ package org.dromara.workflow.utils; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; -import cn.hutool.core.util.StrUtil; -import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import lombok.AccessLevel; import lombok.NoArgsConstructor; -import org.dromara.common.core.domain.dto.RoleDTO; import org.dromara.common.core.domain.dto.UserDTO; -import org.dromara.common.core.service.UserService; import org.dromara.common.core.utils.SpringUtils; import org.dromara.common.core.utils.StreamUtils; import org.dromara.common.core.utils.StringUtils; import org.dromara.common.mail.utils.MailUtils; -import org.dromara.common.satoken.utils.LoginHelper; -import org.dromara.common.tenant.helper.TenantHelper; -import org.dromara.common.websocket.dto.WebSocketMessageDto; -import org.dromara.common.websocket.utils.WebSocketUtils; -import org.dromara.workflow.common.constant.FlowConstant; +import org.dromara.common.sse.dto.SseMessageDto; +import org.dromara.common.sse.utils.SseMessageUtils; +import org.dromara.warm.flow.core.constant.ExceptionCons; +import org.dromara.warm.flow.core.dto.FlowParams; +import org.dromara.warm.flow.core.entity.Node; +import org.dromara.warm.flow.core.entity.Task; +import org.dromara.warm.flow.core.entity.User; +import org.dromara.warm.flow.core.enums.NodeType; +import org.dromara.warm.flow.core.enums.SkipType; +import org.dromara.warm.flow.core.service.NodeService; +import org.dromara.warm.flow.core.service.TaskService; +import org.dromara.warm.flow.core.service.UserService; +import org.dromara.warm.flow.core.utils.AssertUtil; +import org.dromara.warm.flow.orm.entity.FlowNode; +import org.dromara.warm.flow.orm.entity.FlowTask; +import org.dromara.warm.flow.orm.entity.FlowUser; +import org.dromara.warm.flow.orm.mapper.FlowNodeMapper; +import org.dromara.warm.flow.orm.mapper.FlowTaskMapper; import org.dromara.workflow.common.enums.MessageTypeEnum; -import org.dromara.workflow.common.enums.TaskStatusEnum; -import org.dromara.workflow.domain.ActHiTaskinst; -import org.dromara.workflow.domain.vo.MultiInstanceVo; -import org.dromara.workflow.domain.vo.ParticipantVo; -import org.dromara.workflow.flowable.cmd.UpdateHiTaskInstCmd; -import org.dromara.workflow.mapper.ActHiTaskinstMapper; -import org.flowable.bpmn.model.BpmnModel; -import org.flowable.bpmn.model.FlowNode; -import org.flowable.common.engine.api.delegate.Expression; -import org.flowable.engine.ProcessEngine; -import org.flowable.engine.history.HistoricProcessInstance; -import org.flowable.engine.impl.bpmn.behavior.ParallelMultiInstanceBehavior; -import org.flowable.engine.impl.bpmn.behavior.SequentialMultiInstanceBehavior; -import org.flowable.identitylink.api.history.HistoricIdentityLink; -import org.flowable.task.api.Task; -import org.flowable.task.api.TaskQuery; -import org.flowable.task.api.history.HistoricTaskInstance; -import org.flowable.task.service.impl.persistence.entity.TaskEntity; +import org.dromara.workflow.service.IFlwTaskAssigneeService; +import org.dromara.workflow.service.IFlwTaskService; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; -import java.util.*; /** * 工作流工具 @@ -48,220 +47,84 @@ import java.util.*; @NoArgsConstructor(access = AccessLevel.PRIVATE) public class WorkflowUtils { - private static final ProcessEngine PROCESS_ENGINE = SpringUtils.getBean(ProcessEngine.class); - private static final ActHiTaskinstMapper ACT_HI_TASKINST_MAPPER = SpringUtils.getBean(ActHiTaskinstMapper.class); + private static final IFlwTaskAssigneeService TASK_ASSIGNEE_SERVICE = SpringUtils.getBean(IFlwTaskAssigneeService.class); + private static final IFlwTaskService FLW_TASK_SERVICE = SpringUtils.getBean(IFlwTaskService.class); + private static final FlowNodeMapper FLOW_NODE_MAPPER = SpringUtils.getBean(FlowNodeMapper.class); + private static final FlowTaskMapper FLOW_TASK_MAPPER = SpringUtils.getBean(FlowTaskMapper.class); + private static final UserService USER_SERVICE = SpringUtils.getBean(UserService.class); + private static final TaskService TASK_SERVICE = SpringUtils.getBean(TaskService.class); + private static final NodeService NODE_SERVICE = SpringUtils.getBean(NodeService.class); /** - * 创建一个新任务 - * - * @param currentTask 参数 + * 获取工作流用户service */ - public static TaskEntity createNewTask(Task currentTask) { - TaskEntity task = null; - if (ObjectUtil.isNotEmpty(currentTask)) { - task = (TaskEntity) PROCESS_ENGINE.getTaskService().newTask(); - task.setCategory(currentTask.getCategory()); - task.setDescription(currentTask.getDescription()); - task.setAssignee(currentTask.getAssignee()); - task.setName(currentTask.getName()); - task.setProcessDefinitionId(currentTask.getProcessDefinitionId()); - task.setProcessInstanceId(currentTask.getProcessInstanceId()); - task.setTaskDefinitionKey(currentTask.getTaskDefinitionKey()); - task.setPriority(currentTask.getPriority()); - task.setCreateTime(new Date()); - task.setTenantId(TenantHelper.getTenantId()); - PROCESS_ENGINE.getTaskService().saveTask(task); - } - if (ObjectUtil.isNotNull(task)) { - UpdateHiTaskInstCmd updateHiTaskInstCmd = new UpdateHiTaskInstCmd(Collections.singletonList(task.getId()), task.getProcessDefinitionId(), task.getProcessInstanceId()); - PROCESS_ENGINE.getManagementService().executeCommand(updateHiTaskInstCmd); - } - return task; + public static UserService getFlowUserService() { + return USER_SERVICE; } /** - * 抄送任务 + * 构建工作流用户 * - * @param parentTaskList 父级任务 - * @param userIds 人员id + * @param userList 办理用户 + * @param taskId 任务ID + * @return 用户 */ - public static void createCopyTask(List parentTaskList, List userIds) { - List list = new ArrayList<>(); - String tenantId = TenantHelper.getTenantId(); - for (Task parentTask : parentTaskList) { - for (Long userId : userIds) { - TaskEntity newTask = (TaskEntity) PROCESS_ENGINE.getTaskService().newTask(); - newTask.setParentTaskId(parentTask.getId()); - newTask.setAssignee(userId.toString()); - newTask.setName("【抄送】-" + parentTask.getName()); - newTask.setProcessDefinitionId(parentTask.getProcessDefinitionId()); - newTask.setProcessInstanceId(parentTask.getProcessInstanceId()); - newTask.setTaskDefinitionKey(parentTask.getTaskDefinitionKey()); - newTask.setTenantId(tenantId); - list.add(newTask); + public static Set buildUser(List userList, Long taskId) { + if (CollUtil.isEmpty(userList)) { + return Set.of(); + } + Set list = new HashSet<>(); + Set processedBySet = new HashSet<>(); + for (User user : userList) { + // 根据 processedBy 前缀判断处理人类型,分别获取用户列表 + List users = TASK_ASSIGNEE_SERVICE.fetchUsersByStorageId(user.getProcessedBy()); + // 转换为 FlowUser 并添加到结果集合 + if (CollUtil.isNotEmpty(users)) { + users.forEach(dto -> { + String processedBy = String.valueOf(dto.getUserId()); + if (!processedBySet.contains(processedBy)) { + FlowUser flowUser = new FlowUser(); + flowUser.setType(user.getType()); + flowUser.setProcessedBy(processedBy); + flowUser.setAssociated(taskId); + list.add(flowUser); + processedBySet.add(processedBy); + } + }); } } - PROCESS_ENGINE.getTaskService().bulkSaveTasks(list); - if (CollUtil.isNotEmpty(list) && CollUtil.isNotEmpty(parentTaskList)) { - String processInstanceId = parentTaskList.get(0).getProcessInstanceId(); - String processDefinitionId = parentTaskList.get(0).getProcessDefinitionId(); - List taskIds = StreamUtils.toList(list, Task::getId); - ActHiTaskinst actHiTaskinst = new ActHiTaskinst(); - actHiTaskinst.setProcDefId(processDefinitionId); - actHiTaskinst.setProcInstId(processInstanceId); - actHiTaskinst.setScopeType(TaskStatusEnum.COPY.getStatus()); - actHiTaskinst.setTenantId(tenantId); - LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); - updateWrapper.in(ActHiTaskinst::getId, taskIds); - ACT_HI_TASKINST_MAPPER.update(actHiTaskinst, updateWrapper); - for (Task task : list) { - PROCESS_ENGINE.getTaskService().addComment(task.getId(), task.getProcessInstanceId(), TaskStatusEnum.COPY.getStatus(), StrUtil.EMPTY); - } - } - } - - /** - * 获取当前任务参与者 - * - * @param taskId 任务id - */ - public static ParticipantVo getCurrentTaskParticipant(String taskId, UserService userService) { - ParticipantVo participantVo = new ParticipantVo(); - List linksForTask = PROCESS_ENGINE.getHistoryService().getHistoricIdentityLinksForTask(taskId); - Task task = QueryUtils.taskQuery().taskId(taskId).singleResult(); - if (task != null && CollUtil.isNotEmpty(linksForTask)) { - List groupList = StreamUtils.filter(linksForTask, e -> StringUtils.isNotBlank(e.getGroupId())); - if (CollUtil.isNotEmpty(groupList)) { - List groupIds = StreamUtils.toList(groupList, e -> Long.valueOf(e.getGroupId())); - List userIds = userService.selectUserIdsByRoleIds(groupIds); - if (CollUtil.isNotEmpty(userIds)) { - participantVo.setGroupIds(groupIds); - List userList = userService.selectListByIds(userIds); - if (CollUtil.isNotEmpty(userList)) { - List userIdList = StreamUtils.toList(userList, UserDTO::getUserId); - List nickNames = StreamUtils.toList(userList, UserDTO::getNickName); - participantVo.setCandidate(userIdList); - participantVo.setCandidateName(nickNames); - participantVo.setClaim(!StringUtils.isBlank(task.getAssignee())); - } - } - } else { - List candidateList = StreamUtils.filter(linksForTask, e -> FlowConstant.CANDIDATE.equals(e.getType())); - List userIdList = new ArrayList<>(); - for (HistoricIdentityLink historicIdentityLink : linksForTask) { - try { - userIdList.add(Long.valueOf(historicIdentityLink.getUserId())); - } catch (NumberFormatException ignored) { - - } - } - List userList = userService.selectListByIds(userIdList); - if (CollUtil.isNotEmpty(userList)) { - List userIds = StreamUtils.toList(userList, UserDTO::getUserId); - List nickNames = StreamUtils.toList(userList, UserDTO::getNickName); - participantVo.setCandidate(userIds); - participantVo.setCandidateName(nickNames); - // 判断当前任务是否具有多个办理人 - if (CollUtil.isNotEmpty(candidateList) && candidateList.size() > 1) { - // 如果 assignee 存在,则设置当前任务已经被认领 - participantVo.setClaim(StringUtils.isNotBlank(task.getAssignee())); - } - } - } - } - return participantVo; - } - - /** - * 判断当前节点是否为会签节点 - * - * @param processDefinitionId 流程定义id - * @param taskDefinitionKey 流程定义id - */ - public static MultiInstanceVo isMultiInstance(String processDefinitionId, String taskDefinitionKey) { - BpmnModel bpmnModel = PROCESS_ENGINE.getRepositoryService().getBpmnModel(processDefinitionId); - FlowNode flowNode = (FlowNode) bpmnModel.getFlowElement(taskDefinitionKey); - MultiInstanceVo multiInstanceVo = new MultiInstanceVo(); - //判断是否为并行会签节点 - if (flowNode.getBehavior() instanceof ParallelMultiInstanceBehavior behavior && behavior.getCollectionExpression() != null) { - Expression collectionExpression = behavior.getCollectionExpression(); - String assigneeList = collectionExpression.getExpressionText(); - String assignee = behavior.getCollectionElementVariable(); - multiInstanceVo.setType(behavior); - multiInstanceVo.setAssignee(assignee); - multiInstanceVo.setAssigneeList(assigneeList); - return multiInstanceVo; - //判断是否为串行会签节点 - } else if (flowNode.getBehavior() instanceof SequentialMultiInstanceBehavior behavior && behavior.getCollectionExpression() != null) { - Expression collectionExpression = behavior.getCollectionExpression(); - String assigneeList = collectionExpression.getExpressionText(); - String assignee = behavior.getCollectionElementVariable(); - multiInstanceVo.setType(behavior); - multiInstanceVo.setAssignee(assignee); - multiInstanceVo.setAssigneeList(assigneeList); - return multiInstanceVo; - } - return null; - } - - /** - * 获取当前流程状态 - * - * @param taskId 任务id - */ - public static String getBusinessStatusByTaskId(String taskId) { - HistoricTaskInstance historicTaskInstance = QueryUtils.hisTaskInstanceQuery().taskId(taskId).singleResult(); - HistoricProcessInstance historicProcessInstance = QueryUtils.hisInstanceQuery(historicTaskInstance.getProcessInstanceId()).singleResult(); - return historicProcessInstance.getBusinessStatus(); - } - - /** - * 获取当前流程状态 - * - * @param businessKey 业务id - */ - public static String getBusinessStatus(String businessKey) { - HistoricProcessInstance historicProcessInstance = QueryUtils.hisBusinessKeyQuery(businessKey).singleResult(); - return historicProcessInstance.getBusinessStatus(); + return list; } /** * 发送消息 * - * @param list 任务 - * @param name 流程名称 + * @param flowName 流程定义名称 * @param messageType 消息类型 * @param message 消息内容,为空则发送默认配置的消息内容 */ - public static void sendMessage(List list, String name, List messageType, String message, UserService userService) { - Set userIds = new HashSet<>(); + public static void sendMessage(String flowName, Long instId, List messageType, String message) { + List userList = new ArrayList<>(); + List list = FLW_TASK_SERVICE.selectByInstId(instId); if (StringUtils.isBlank(message)) { - message = "有新的【" + name + "】单据已经提交至您的待办,请您及时处理。"; + message = "有新的【" + flowName + "】单据已经提交至您,请您及时处理。"; } - for (Task t : list) { - ParticipantVo taskParticipant = WorkflowUtils.getCurrentTaskParticipant(t.getId(), userService); - if (CollUtil.isNotEmpty(taskParticipant.getGroupIds())) { - List userIdList = userService.selectUserIdsByRoleIds(taskParticipant.getGroupIds()); - if (CollUtil.isNotEmpty(userIdList)) { - userIds.addAll(userIdList); - } - } - List candidate = taskParticipant.getCandidate(); - if (CollUtil.isNotEmpty(candidate)) { - userIds.addAll(candidate); + for (Task task : list) { + List users = FLW_TASK_SERVICE.currentTaskAllUser(task.getId()); + if (CollUtil.isNotEmpty(users)) { + userList.addAll(users); } } - if (CollUtil.isNotEmpty(userIds)) { - List userList = userService.selectListByIds(new ArrayList<>(userIds)); + if (CollUtil.isNotEmpty(userList)) { for (String code : messageType) { MessageTypeEnum messageTypeEnum = MessageTypeEnum.getByCode(code); if (ObjectUtil.isNotEmpty(messageTypeEnum)) { switch (messageTypeEnum) { case SYSTEM_MESSAGE: - WebSocketMessageDto dto = new WebSocketMessageDto(); - dto.setSessionKeys(new ArrayList<>(userIds)); + SseMessageDto dto = new SseMessageDto(); + dto.setUserIds(StreamUtils.toList(userList, UserDTO::getUserId).stream().distinct().collect(Collectors.toList())); dto.setMessage(message); - WebSocketUtils.publishMessage(dto); + SseMessageUtils.publishMessage(dto); break; case EMAIL_MESSAGE: MailUtils.sendText(StreamUtils.join(userList, UserDTO::getEmail), "单据审批提醒", message); @@ -269,6 +132,8 @@ public class WorkflowUtils { case SMS_MESSAGE: //todo 短信发送 break; + default: + throw new IllegalStateException("Unexpected value: " + messageTypeEnum); } } } @@ -276,20 +141,66 @@ public class WorkflowUtils { } /** - * 根据任务id查询 当前用户的任务,检查 当前人员 是否是该 taskId 的办理人 + * 驳回 * - * @param taskId 任务id - * @return 结果 + * @param message 审批意见 + * @param instanceId 流程实例id + * @param targetNodeCode 目标节点 + * @param flowStatus 流程状态 + * @param flowHisStatus 节点操作状态 */ - public static Task getTaskByCurrentUser(String taskId) { - TaskQuery taskQuery = QueryUtils.taskQuery(); - taskQuery.taskId(taskId).taskCandidateOrAssigned(String.valueOf(LoginHelper.getUserId())); - - List roles = LoginHelper.getLoginUser().getRoles(); - if (CollUtil.isNotEmpty(roles)) { - List groupIds = StreamUtils.toList(roles, e -> String.valueOf(e.getRoleId())); - taskQuery.taskCandidateGroupIn(groupIds); + public static void backTask(String message, Long instanceId, String targetNodeCode, String flowStatus, String flowHisStatus) { + List list = FLW_TASK_SERVICE.selectByInstId(instanceId); + if (CollUtil.isNotEmpty(list)) { + List tasks = StreamUtils.filter(list, e -> e.getNodeCode().equals(targetNodeCode)); + if (list.size() == tasks.size()) { + return; + } } - return taskQuery.singleResult(); + for (FlowTask task : list) { + List userList = FLW_TASK_SERVICE.currentTaskAllUser(task.getId()); + FlowParams flowParams = FlowParams.build(); + flowParams.nodeCode(targetNodeCode); + flowParams.message(message); + flowParams.skipType(SkipType.PASS.getKey()); + flowParams.flowStatus(flowStatus).hisStatus(flowHisStatus); + flowParams.ignore(true); + //解决会签没权限问题 + if (CollUtil.isNotEmpty(userList)) { + flowParams.handler(userList.get(0).getUserId().toString()); + } + TASK_SERVICE.skip(task.getId(), flowParams); + } + //解决会签多人审批问题 + backTask(message, instanceId, targetNodeCode, flowStatus, flowHisStatus); + } + + /** + * 申请人节点编码 + * + * @param definitionId 流程定义id + * @return 申请人节点编码 + */ + public static String applyNodeCode(Long definitionId) { + //获取已发布的流程节点 + List flowNodes = FLOW_NODE_MAPPER.selectList(new LambdaQueryWrapper().eq(FlowNode::getDefinitionId, definitionId)); + AssertUtil.isTrue(CollUtil.isEmpty(flowNodes), ExceptionCons.NOT_PUBLISH_NODE); + Node startNode = flowNodes.stream().filter(t -> NodeType.isStart(t.getNodeType())).findFirst().orElse(null); + AssertUtil.isNull(startNode, ExceptionCons.LOST_START_NODE); + Node nextNode = NODE_SERVICE.getNextNode(definitionId, startNode.getNodeCode(), null, SkipType.NONE.getKey()); + return nextNode.getNodeCode(); + } + + /** + * 删除运行中的任务 + * + * @param taskIds 任务id + */ + public static void deleteRunTask(List taskIds) { + if (CollUtil.isEmpty(taskIds)) { + return; + } + USER_SERVICE.deleteByTaskIds(taskIds); + FLOW_TASK_MAPPER.deleteByIds(taskIds); } } diff --git a/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/ActHiProcinstMapper.xml b/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/ActHiProcinstMapper.xml deleted file mode 100644 index dd0578576..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/ActHiProcinstMapper.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/ActHiTaskinstMapper.xml b/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/ActHiTaskinstMapper.xml deleted file mode 100644 index 7e73b603f..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/ActHiTaskinstMapper.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/ActTaskMapper.xml b/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/ActTaskMapper.xml deleted file mode 100644 index 36419009a..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/ActTaskMapper.xml +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/FlwCategoryMapper.xml b/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/FlwCategoryMapper.xml new file mode 100644 index 000000000..e9918f1f2 --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/FlwCategoryMapper.xml @@ -0,0 +1,11 @@ + + + + + + + diff --git a/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/FlwInstanceMapper.xml b/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/FlwInstanceMapper.xml new file mode 100644 index 000000000..30e2267dc --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/FlwInstanceMapper.xml @@ -0,0 +1,36 @@ + + + + + + + + + diff --git a/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/FlwTaskMapper.xml b/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/FlwTaskMapper.xml new file mode 100644 index 000000000..73e4ec789 --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/FlwTaskMapper.xml @@ -0,0 +1,115 @@ + + + + + + + + + + + + + + diff --git a/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/WfCategoryMapper.xml b/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/WfCategoryMapper.xml deleted file mode 100644 index 4375cb2dd..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/WfCategoryMapper.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/WfDefinitionConfigMapper.xml b/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/WfDefinitionConfigMapper.xml deleted file mode 100644 index 8d579f705..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/WfDefinitionConfigMapper.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/WfFormManageMapper.xml b/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/WfFormManageMapper.xml deleted file mode 100644 index 59221f82d..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/WfFormManageMapper.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/WfNodeConfigMapper.xml b/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/WfNodeConfigMapper.xml deleted file mode 100644 index b65194f8b..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/WfNodeConfigMapper.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/WfTaskBackNodeMapper.xml b/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/WfTaskBackNodeMapper.xml deleted file mode 100644 index 4a9179b62..000000000 --- a/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/WfTaskBackNodeMapper.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/script/bpmn/leave1.xml b/script/bpmn/leave1.xml new file mode 100644 index 000000000..1013eb24e --- /dev/null +++ b/script/bpmn/leave1.xml @@ -0,0 +1,17 @@ + + + + + dd515cdd-59f6-446f-94ca-25ca062afb42 + + + 78fa8e5b-e809-44ed-978a-41092409ebcf + + + a8abf15f-b83e-428a-86cc-033555ea9bbe + + + 8b82b7d7-8660-455e-b880-d6d22ea3eb6d + + + diff --git a/script/bpmn/leave2.xml b/script/bpmn/leave2.xml new file mode 100644 index 000000000..38ec0a9d7 --- /dev/null +++ b/script/bpmn/leave2.xml @@ -0,0 +1,24 @@ + + + + + fdcae93b-b69c-498a-b231-09255e74bcbd + + + 7b8c7ead-7dc8-4951-a7f3-f0c41995909e + + + b3528155-dcb7-4445-bbdf-3d00e3499e86 + 5ed2362b-fc0c-4d52-831f-95208b830605 + + + c9fa6d7d-2a74-4e78-b947-0cad8a6af869 + + + 40aa65fd-0712-4d23-b6f7-d0432b920fd1 + + + + c9fa6d7d-2a74-4e78-b947-0cad8a6af869 + + diff --git a/script/bpmn/leave3.xml b/script/bpmn/leave3.xml new file mode 100644 index 000000000..ffb8d9505 --- /dev/null +++ b/script/bpmn/leave3.xml @@ -0,0 +1,27 @@ + + + + + b7bbb571-06de-455c-8083-f83c07bf0b99 + + + 84d7ed24-bb44-4ba1-bf1f-e6f5092d3f0a + + + 4b7743cd-940c-431b-926f-e7b614fbf1fe + 762cb975-37d8-4276-b6db-79a4c3606394 + + + b66b6563-f9fe-41cc-a782-f7837bb6f3d2 + + + 23e7429e-2b47-4431-b93e-40db7c431ce6 + + + f5ace37f-5a5e-4e64-a6f6-913ab9a71cd1 + + + + b66b6563-f9fe-41cc-a782-f7837bb6f3d2 + + diff --git a/script/bpmn/leave4.xml b/script/bpmn/leave4.xml new file mode 100644 index 000000000..2061d176f --- /dev/null +++ b/script/bpmn/leave4.xml @@ -0,0 +1,20 @@ + + + + + e90b98ef-35b4-410c-a663-bae8b7624b9f + + + 768b5b1a-6726-4d67-8853-4cc70d5b1045 + + + 2f9f2e21-9bcf-42a3-a07c-13037aad22d1 + + + 27461e01-3d9f-4530-8fe3-bd5ec7f9571f + + + b62b88c3-8d8d-4969-911e-2aaea219e7fc + + + diff --git a/script/bpmn/leave5.xml b/script/bpmn/leave5.xml new file mode 100644 index 000000000..d6c0117c0 --- /dev/null +++ b/script/bpmn/leave5.xml @@ -0,0 +1,27 @@ + + + + + e1b04e96-dc81-4858-a309-2fe945d2f374 + + + 3e743f4f-51ca-41d4-8e94-21f5dd9b59c9 + + + c80f273e-1f17-4bd8-9ad1-04a4a94ea862 + 1e3e8d3b-18ae-4d6c-a814-ce0d724adfa4 + + + 1a20169e-3d82-4926-a151-e2daad28de1b + + + 7a8f0473-e409-442e-a843-5c2b813d00e9 + + + 03c4d2bc-58b5-4408-a2e4-65afb046f169 + + + + 1a20169e-3d82-4926-a151-e2daad28de1b + + diff --git a/script/bpmn/模型.zip b/script/bpmn/模型.zip deleted file mode 100644 index 6f30952ab14f0b60dc64674e7eef083141856458..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8543 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 Date: Mon, 13 Jan 2025 14:26:31 +0800 Subject: [PATCH 142/175] =?UTF-8?q?Revert=20"fix=20=E4=BF=AE=E5=A4=8D=20sa?= =?UTF-8?q?token=20dao=E5=B1=82=E8=8E=B7=E5=8F=96timeout=E4=B8=BA=E7=A7=92?= =?UTF-8?q?=E5=AF=BC=E8=87=B4=E4=B8=A2=E5=A4=B1=E6=AF=AB=E7=A7=92=E8=BF=9B?= =?UTF-8?q?=E5=BA=A6=E9=97=AE=E9=A2=98(=E4=B8=B4=E6=97=B6=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=20=E7=AD=89satoken=E5=AE=98=E6=96=B9=E8=A7=A3?= =?UTF-8?q?=E5=86=B3)"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit e36e8f77581314541b27bcf43dd99bbc2c916255. --- .../common/satoken/core/dao/PlusSaTokenDao.java | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/core/dao/PlusSaTokenDao.java b/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/core/dao/PlusSaTokenDao.java index a2a152003..38e12c315 100644 --- a/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/core/dao/PlusSaTokenDao.java +++ b/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/core/dao/PlusSaTokenDao.java @@ -51,11 +51,7 @@ public class PlusSaTokenDao implements SaTokenDao { if (timeout == NEVER_EXPIRE) { RedisUtils.setCacheObject(key, value); } else { - if (RedisUtils.hasKey(key)) { - RedisUtils.setCacheObject(key, value, true); - } else { - RedisUtils.setCacheObject(key, value, Duration.ofSeconds(timeout)); - } + RedisUtils.setCacheObject(key, value, Duration.ofSeconds(timeout)); } CAFFEINE.invalidate(key); } @@ -118,11 +114,7 @@ public class PlusSaTokenDao implements SaTokenDao { if (timeout == NEVER_EXPIRE) { RedisUtils.setCacheObject(key, object); } else { - if (RedisUtils.hasKey(key)) { - RedisUtils.setCacheObject(key, object, true); - } else { - RedisUtils.setCacheObject(key, object, Duration.ofSeconds(timeout)); - } + RedisUtils.setCacheObject(key, object, Duration.ofSeconds(timeout)); } CAFFEINE.invalidate(key); } From a680310f80728e995fdeb7251b1f270ad02d48e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Mon, 13 Jan 2025 13:35:57 +0800 Subject: [PATCH 143/175] =?UTF-8?q?fix=20=E4=BF=AE=E5=A4=8D=20satoken=20da?= =?UTF-8?q?o=E5=B1=82=E8=8E=B7=E5=8F=96timeout=E4=B8=BA=E7=A7=92=E5=AF=BC?= =?UTF-8?q?=E8=87=B4=E4=B8=A2=E5=A4=B1=E6=AF=AB=E7=A7=92=E8=BF=9B=E5=BA=A6?= =?UTF-8?q?=E9=97=AE=E9=A2=98(=E4=B8=B4=E6=97=B6=E4=BF=AE=E5=A4=8D=20?= =?UTF-8?q?=E7=AD=89satoken=E5=AE=98=E6=96=B9=E8=A7=A3=E5=86=B3)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/satoken/core/dao/PlusSaTokenDao.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/core/dao/PlusSaTokenDao.java b/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/core/dao/PlusSaTokenDao.java index 38e12c315..a2a152003 100644 --- a/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/core/dao/PlusSaTokenDao.java +++ b/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/core/dao/PlusSaTokenDao.java @@ -51,7 +51,11 @@ public class PlusSaTokenDao implements SaTokenDao { if (timeout == NEVER_EXPIRE) { RedisUtils.setCacheObject(key, value); } else { - RedisUtils.setCacheObject(key, value, Duration.ofSeconds(timeout)); + if (RedisUtils.hasKey(key)) { + RedisUtils.setCacheObject(key, value, true); + } else { + RedisUtils.setCacheObject(key, value, Duration.ofSeconds(timeout)); + } } CAFFEINE.invalidate(key); } @@ -114,7 +118,11 @@ public class PlusSaTokenDao implements SaTokenDao { if (timeout == NEVER_EXPIRE) { RedisUtils.setCacheObject(key, object); } else { - RedisUtils.setCacheObject(key, object, Duration.ofSeconds(timeout)); + if (RedisUtils.hasKey(key)) { + RedisUtils.setCacheObject(key, object, true); + } else { + RedisUtils.setCacheObject(key, object, Duration.ofSeconds(timeout)); + } } CAFFEINE.invalidate(key); } From 9086d32bee89a0614271002c9b691357e695057a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Mon, 13 Jan 2025 18:52:52 +0800 Subject: [PATCH 144/175] =?UTF-8?q?fix=20=E4=BF=AE=E5=A4=8D=20=E5=A4=9A?= =?UTF-8?q?=E8=A7=92=E8=89=B2=E6=9C=AA=E6=8B=86=E5=88=86=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/impl/FlwTaskAssigneeServiceImpl.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskAssigneeServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskAssigneeServiceImpl.java index 28c1e8b04..7910b7b35 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskAssigneeServiceImpl.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskAssigneeServiceImpl.java @@ -129,11 +129,16 @@ public class FlwTaskAssigneeServiceImpl implements IFlwTaskAssigneeService, Hand */ @Override public List fetchUsersByStorageId(String storageId) { - String[] parts = storageId.split(StrUtil.COLON, 2); - if (parts.length < 2) { - return getUsersByType(TaskAssigneeEnum.USER, List.of(Long.valueOf(parts[0]))); + List list = new ArrayList<>(); + for (String str : storageId.split(StrUtil.COMMA)) { + String[] parts = str.split(StrUtil.COLON, 2); + TaskAssigneeEnum enumd = TaskAssigneeEnum.USER; + if (parts.length >= 2) { + enumd = TaskAssigneeEnum.fromDesc(parts[0] + StrUtil.COLON); + } + list.addAll(getUsersByType(enumd, List.of(Long.valueOf(parts[1])))); } - return getUsersByType(TaskAssigneeEnum.fromCode(parts[0] + StrUtil.COLON), List.of(Long.valueOf(parts[1]))); + return list; } /** From 69130a76e4fcff2b06c4c1143fc5d2ddf4e780a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Mon, 13 Jan 2025 19:09:13 +0800 Subject: [PATCH 145/175] =?UTF-8?q?fix=20=E4=BF=AE=E5=A4=8D=20=E5=A4=9A?= =?UTF-8?q?=E8=A7=92=E8=89=B2=E6=9C=AA=E6=8B=86=E5=88=86=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../workflow/service/impl/FlwTaskAssigneeServiceImpl.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskAssigneeServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskAssigneeServiceImpl.java index 7910b7b35..2ed6538af 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskAssigneeServiceImpl.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskAssigneeServiceImpl.java @@ -132,11 +132,10 @@ public class FlwTaskAssigneeServiceImpl implements IFlwTaskAssigneeService, Hand List list = new ArrayList<>(); for (String str : storageId.split(StrUtil.COMMA)) { String[] parts = str.split(StrUtil.COLON, 2); - TaskAssigneeEnum enumd = TaskAssigneeEnum.USER; - if (parts.length >= 2) { - enumd = TaskAssigneeEnum.fromDesc(parts[0] + StrUtil.COLON); + if (parts.length < 2) { + list.addAll(getUsersByType(TaskAssigneeEnum.USER, List.of(Long.valueOf(parts[0])))); } - list.addAll(getUsersByType(enumd, List.of(Long.valueOf(parts[1])))); + list.addAll(getUsersByType(TaskAssigneeEnum.fromCode(parts[0] + StrUtil.COLON), List.of(Long.valueOf(parts[1])))); } return list; } From 7d82f954acf5e67a9375830b6835a3f211a745c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Mon, 13 Jan 2025 19:37:45 +0800 Subject: [PATCH 146/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E9=83=A8?= =?UTF-8?q?=E5=88=86=E4=BB=A3=E7=A0=81=E4=B8=8Ebug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dromara/workflow/listener/WorkflowGlobalListener.java | 1 - .../workflow/service/impl/FlwTaskAssigneeServiceImpl.java | 3 ++- script/bpmn/leave2.xml | 6 +++--- script/bpmn/leave4.xml | 2 +- script/bpmn/leave5.xml | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) 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 29b8b7279..35c16bda3 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 @@ -107,7 +107,6 @@ public class WorkflowGlobalListener implements GlobalListener { log.info("流程已结束,状态更新为: {}", status); return status; } - log.warn("流程未结束,实例ID: {}", instanceId); return null; } } diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskAssigneeServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskAssigneeServiceImpl.java index 2ed6538af..5f348661b 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskAssigneeServiceImpl.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskAssigneeServiceImpl.java @@ -134,8 +134,9 @@ public class FlwTaskAssigneeServiceImpl implements IFlwTaskAssigneeService, Hand String[] parts = str.split(StrUtil.COLON, 2); if (parts.length < 2) { list.addAll(getUsersByType(TaskAssigneeEnum.USER, List.of(Long.valueOf(parts[0])))); + } else { + list.addAll(getUsersByType(TaskAssigneeEnum.fromCode(parts[0] + StrUtil.COLON), List.of(Long.valueOf(parts[1])))); } - list.addAll(getUsersByType(TaskAssigneeEnum.fromCode(parts[0] + StrUtil.COLON), List.of(Long.valueOf(parts[1])))); } return list; } diff --git a/script/bpmn/leave2.xml b/script/bpmn/leave2.xml index 38ec0a9d7..35d270fda 100644 --- a/script/bpmn/leave2.xml +++ b/script/bpmn/leave2.xml @@ -1,6 +1,6 @@ - + fdcae93b-b69c-498a-b231-09255e74bcbd @@ -8,8 +8,8 @@ 7b8c7ead-7dc8-4951-a7f3-f0c41995909e - b3528155-dcb7-4445-bbdf-3d00e3499e86 - 5ed2362b-fc0c-4d52-831f-95208b830605 + b3528155-dcb7-4445-bbdf-3d00e3499e86 + 5ed2362b-fc0c-4d52-831f-95208b830605 c9fa6d7d-2a74-4e78-b947-0cad8a6af869 diff --git a/script/bpmn/leave4.xml b/script/bpmn/leave4.xml index 2061d176f..578be560f 100644 --- a/script/bpmn/leave4.xml +++ b/script/bpmn/leave4.xml @@ -1,6 +1,6 @@ - + e90b98ef-35b4-410c-a663-bae8b7624b9f diff --git a/script/bpmn/leave5.xml b/script/bpmn/leave5.xml index d6c0117c0..a5fc2d2c2 100644 --- a/script/bpmn/leave5.xml +++ b/script/bpmn/leave5.xml @@ -1,6 +1,6 @@ - + e1b04e96-dc81-4858-a309-2fe945d2f374 From 6f0dd8dc8939a6dfd85deb0dc8c818dc3bc0cf01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=89=9B=E5=AD=90Li?= Date: Tue, 14 Jan 2025 05:40:07 +0000 Subject: [PATCH 147/175] =?UTF-8?q?!636=20update=20=E4=BC=98=E5=8C=96=20?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E9=80=9A=E8=BF=87=E9=85=8D=E7=BD=AE=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E5=85=B3=E9=97=AD=E5=B7=A5=E4=BD=9C=E6=B5=81=20*=20up?= =?UTF-8?q?date=20=E4=BC=98=E5=8C=96=20=E6=94=AF=E6=8C=81=E9=80=9A?= =?UTF-8?q?=E8=BF=87=E9=85=8D=E7=BD=AE=E6=96=87=E4=BB=B6=E5=85=B3=E9=97=AD?= =?UTF-8?q?=E5=B7=A5=E4=BD=9C=E6=B5=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/FlwDefinitionController.java | 5 ++- .../controller/FlwInstanceController.java | 5 ++- .../service/impl/FlwCategoryServiceImpl.java | 5 ++- .../impl/FlwDefinitionServiceImpl.java | 17 ++++++--- .../service/impl/FlwInstanceServiceImpl.java | 23 +++++++---- .../service/impl/FlwTaskServiceImpl.java | 38 +++++++++++++------ 6 files changed, 66 insertions(+), 27 deletions(-) diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwDefinitionController.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwDefinitionController.java index b125f0f28..294f2f4c0 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwDefinitionController.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwDefinitionController.java @@ -14,6 +14,7 @@ import org.dromara.warm.flow.core.service.DefService; import org.dromara.warm.flow.orm.entity.FlowDefinition; import org.dromara.workflow.domain.vo.FlowDefinitionVo; import org.dromara.workflow.service.IFlwDefinitionService; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -33,8 +34,10 @@ import java.util.List; @RequestMapping("/workflow/definition") public class FlwDefinitionController extends BaseController { + @Autowired(required = false) + private DefService defService; + private final IFlwDefinitionService flwDefinitionService; - private final DefService defService; /** * 查询流程定义列表 diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwInstanceController.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwInstanceController.java index cb65f2158..3393162c7 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwInstanceController.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwInstanceController.java @@ -14,6 +14,7 @@ import org.dromara.workflow.domain.bo.FlowInstanceBo; import org.dromara.workflow.domain.bo.FlowInvalidBo; import org.dromara.workflow.domain.vo.FlowInstanceVo; import org.dromara.workflow.service.IFlwInstanceService; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -31,8 +32,10 @@ import java.util.Map; @RequestMapping("/workflow/instance") public class FlwInstanceController extends BaseController { + @Autowired(required = false) + private InsService insService; + private final IFlwInstanceService flwInstanceService; - private final InsService insService; /** * 查询正在运行的流程实例列表 diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwCategoryServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwCategoryServiceImpl.java index 0a5c0bb54..368212f10 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwCategoryServiceImpl.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwCategoryServiceImpl.java @@ -19,6 +19,7 @@ import org.dromara.workflow.domain.bo.FlowCategoryBo; import org.dromara.workflow.domain.vo.FlowCategoryVo; import org.dromara.workflow.mapper.FlwCategoryMapper; import org.dromara.workflow.service.IFlwCategoryService; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; @@ -35,8 +36,10 @@ import java.util.List; @Service public class FlwCategoryServiceImpl implements IFlwCategoryService { + @Autowired(required = false) + private DefService defService; + private final FlwCategoryMapper baseMapper; - private final DefService defService; /** * 查询流程分类 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 baec223fe..6ded1a6d4 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 @@ -36,6 +36,7 @@ import org.dromara.workflow.domain.vo.FlowDefinitionVo; import org.dromara.workflow.mapper.FlwCategoryMapper; import org.dromara.workflow.service.IFlwDefinitionService; import org.dromara.workflow.utils.WorkflowUtils; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; @@ -57,12 +58,18 @@ import static org.dromara.common.core.constant.TenantConstants.DEFAULT_TENANT_ID @Service public class FlwDefinitionServiceImpl implements IFlwDefinitionService { - private final DefService defService; - private final FlowDefinitionMapper flowDefinitionMapper; - private final FlowHisTaskMapper flowHisTaskMapper; + @Autowired(required = false) + private DefService defService; + @Autowired(required = false) + private FlowDefinitionMapper flowDefinitionMapper; + @Autowired(required = false) + private FlowHisTaskMapper flowHisTaskMapper; + @Autowired(required = false) + private FlowNodeMapper flowNodeMapper; + @Autowired(required = false) + private FlowSkipMapper flowSkipMapper; + private final FlwCategoryMapper flwCategoryMapper; - private final FlowNodeMapper flowNodeMapper; - private final FlowSkipMapper flowSkipMapper; /** * 查询流程定义列表 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 c053e6d4a..24f86de11 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 @@ -47,6 +47,7 @@ import org.dromara.workflow.mapper.FlwInstanceMapper; import org.dromara.workflow.service.IFlwInstanceService; import org.dromara.workflow.service.IFlwTaskService; import org.dromara.workflow.utils.WorkflowUtils; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -64,14 +65,22 @@ import java.util.stream.Collectors; @Service public class FlwInstanceServiceImpl implements IFlwInstanceService { - private final InsService insService; - private final DefService defService; - private final FlowHisTaskMapper flowHisTaskMapper; - private final FlowInstanceMapper flowInstanceMapper; - private final FlwInstanceMapper flwInstanceMapper; - private final TaskService taskService; - private final IFlwTaskService flwTaskService; + @Autowired(required = false) + private InsService insService; + @Autowired(required = false) + private DefService defService; + @Autowired(required = false) + private TaskService taskService; + @Autowired(required = false) + private FlowHisTaskMapper flowHisTaskMapper; + @Autowired(required = false) + private FlowInstanceMapper flowInstanceMapper; + private final FlowProcessEventHandler flowProcessEventHandler; + + private final IFlwTaskService flwTaskService; + + private final FlwInstanceMapper flwInstanceMapper; private final FlwCategoryMapper flwCategoryMapper; /** 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 fca38fbac..11f83ede6 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 @@ -45,6 +45,7 @@ import org.dromara.workflow.mapper.FlwCategoryMapper; import org.dromara.workflow.mapper.FlwTaskMapper; import org.dromara.workflow.service.IFlwTaskService; import org.dromara.workflow.utils.WorkflowUtils; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -64,19 +65,32 @@ import static org.dromara.workflow.common.constant.FlowConstant.*; @Service public class FlwTaskServiceImpl implements IFlwTaskService { - private final TaskService taskService; - private final InsService insService; - private final FlowInstanceMapper flowInstanceMapper; - private final FlwTaskMapper flwTaskMapper; - private final UserService userService; - private final FlowTaskMapper flowTaskMapper; - private final FlowHisTaskMapper flowHisTaskMapper; - private final FlowProcessEventHandler flowProcessEventHandler; - private final DefService defService; - private final HisTaskService hisTaskService; + @Autowired(required = false) + private TaskService taskService; + @Autowired(required = false) + private InsService insService; + @Autowired(required = false) + private DefService defService; + @Autowired(required = false) + private HisTaskService hisTaskService; + @Autowired(required = false) + private NodeService nodeService; + + @Autowired(required = false) + private FlowInstanceMapper flowInstanceMapper; + @Autowired(required = false) + private FlowTaskMapper flowTaskMapper; + @Autowired(required = false) + private FlowHisTaskMapper flowHisTaskMapper; + @Autowired(required = false) + private FlowNodeMapper flowNodeMapper; + private final IdentifierGenerator identifierGenerator; - private final NodeService nodeService; - private final FlowNodeMapper flowNodeMapper; + private final FlowProcessEventHandler flowProcessEventHandler; + + private final UserService userService; + + private final FlwTaskMapper flwTaskMapper; private final FlwCategoryMapper flwCategoryMapper; /** From 6f14c91d30f6b6fd0dd87d55b2a2cb313e2bd19e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Tue, 14 Jan 2025 14:05:30 +0800 Subject: [PATCH 148/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20!pr636=20?= =?UTF-8?q?=E6=94=B9=E4=B8=BA=E6=B3=A8=E8=A7=A3=E6=96=B9=E5=BC=8F=E5=85=B3?= =?UTF-8?q?=E9=97=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/application.yml | 2 +- .../service/impl/SysTenantServiceImpl.java | 10 ++++-- .../workflow/common/ConditionalOnEnable.java | 14 ++++++++ .../workflow/config/WarmFlowConfig.java | 2 ++ .../controller/FlwCategoryController.java | 2 ++ .../controller/FlwDefinitionController.java | 7 ++-- .../controller/FlwInstanceController.java | 7 ++-- .../controller/FlwTaskController.java | 2 ++ .../controller/TestLeaveController.java | 2 ++ .../handler/FlowProcessEventHandler.java | 2 ++ .../handler/WorkflowPermissionHandler.java | 2 ++ .../listener/WorkflowGlobalListener.java | 2 ++ .../impl/CategoryNameTranslationImpl.java | 2 ++ .../service/impl/FlwCategoryServiceImpl.java | 7 ++-- .../impl/FlwDefinitionServiceImpl.java | 19 ++++------- .../service/impl/FlwInstanceServiceImpl.java | 21 ++++-------- .../impl/FlwTaskAssigneeServiceImpl.java | 2 ++ .../service/impl/FlwTaskServiceImpl.java | 34 ++++++------------- .../service/impl/TestLeaveServiceImpl.java | 2 ++ .../service/impl/WorkflowServiceImpl.java | 2 ++ 20 files changed, 77 insertions(+), 66 deletions(-) create mode 100644 ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/ConditionalOnEnable.java diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml index dbe16888d..9db74dc3f 100644 --- a/ruoyi-admin/src/main/resources/application.yml +++ b/ruoyi-admin/src/main/resources/application.yml @@ -276,7 +276,7 @@ websocket: --- # warm-flow工作流配置 warm-flow: # 是否开启工作流,默认true - enabled: true + enabled: false # 是否开启设计器ui ui: true # 默认Authorization,如果有多个token,用逗号分隔 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 856dabba5..5e5e8cd20 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 @@ -57,7 +57,6 @@ public class SysTenantServiceImpl implements ISysTenantService { private final SysDictTypeMapper dictTypeMapper; private final SysDictDataMapper dictDataMapper; private final SysConfigMapper configMapper; - private final WorkflowService workflowService; /** * 查询租户 @@ -195,8 +194,13 @@ public class SysTenantServiceImpl implements ISysTenantService { config.setTenantId(tenantId); } configMapper.insertBatch(sysConfigList); - //新增租户流程定义 - workflowService.syncDef(tenantId); + + // 未开启工作流不执行下方操作 + if (SpringUtils.getProperty("workflow.enabled", Boolean.class, false)) { + WorkflowService workflowService = SpringUtils.getBean(WorkflowService.class); + // 新增租户流程定义 + workflowService.syncDef(tenantId); + } return true; } diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/ConditionalOnEnable.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/ConditionalOnEnable.java new file mode 100644 index 000000000..8adf0158b --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/ConditionalOnEnable.java @@ -0,0 +1,14 @@ +package org.dromara.workflow.common; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.TYPE, ElementType.METHOD }) +@ConditionalOnProperty(value = "workflow.enabled", havingValue = "true") +public @interface ConditionalOnEnable { +} diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/config/WarmFlowConfig.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/config/WarmFlowConfig.java index a38c83e27..4dec5b1cc 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/config/WarmFlowConfig.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/config/WarmFlowConfig.java @@ -1,6 +1,7 @@ package org.dromara.workflow.config; +import org.dromara.workflow.common.ConditionalOnEnable; import org.springframework.context.annotation.Configuration; /** @@ -8,6 +9,7 @@ import org.springframework.context.annotation.Configuration; * * @author may */ +@ConditionalOnEnable @Configuration public class WarmFlowConfig { diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwCategoryController.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwCategoryController.java index 99fa064df..9520cbdef 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwCategoryController.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwCategoryController.java @@ -13,6 +13,7 @@ import org.dromara.common.idempotent.annotation.RepeatSubmit; import org.dromara.common.log.annotation.Log; import org.dromara.common.log.enums.BusinessType; import org.dromara.common.web.core.BaseController; +import org.dromara.workflow.common.ConditionalOnEnable; import org.dromara.workflow.domain.bo.FlowCategoryBo; import org.dromara.workflow.domain.vo.FlowCategoryVo; import org.dromara.workflow.service.IFlwCategoryService; @@ -26,6 +27,7 @@ import java.util.List; * * @author may */ +@ConditionalOnEnable @Validated @RequiredArgsConstructor @RestController diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwDefinitionController.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwDefinitionController.java index 294f2f4c0..1310da3f6 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwDefinitionController.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwDefinitionController.java @@ -12,9 +12,9 @@ import org.dromara.common.web.core.BaseController; import org.dromara.warm.flow.core.entity.Definition; import org.dromara.warm.flow.core.service.DefService; import org.dromara.warm.flow.orm.entity.FlowDefinition; +import org.dromara.workflow.common.ConditionalOnEnable; import org.dromara.workflow.domain.vo.FlowDefinitionVo; import org.dromara.workflow.service.IFlwDefinitionService; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -28,15 +28,14 @@ import java.util.List; * * @author may */ +@ConditionalOnEnable @Validated @RequiredArgsConstructor @RestController @RequestMapping("/workflow/definition") public class FlwDefinitionController extends BaseController { - @Autowired(required = false) - private DefService defService; - + private final DefService defService; private final IFlwDefinitionService flwDefinitionService; /** diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwInstanceController.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwInstanceController.java index 3393162c7..f85b8ff0a 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwInstanceController.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwInstanceController.java @@ -9,12 +9,12 @@ import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.web.core.BaseController; import org.dromara.warm.flow.core.service.InsService; +import org.dromara.workflow.common.ConditionalOnEnable; import org.dromara.workflow.domain.bo.FlowCancelBo; import org.dromara.workflow.domain.bo.FlowInstanceBo; import org.dromara.workflow.domain.bo.FlowInvalidBo; import org.dromara.workflow.domain.vo.FlowInstanceVo; import org.dromara.workflow.service.IFlwInstanceService; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -26,15 +26,14 @@ import java.util.Map; * * @author may */ +@ConditionalOnEnable @Validated @RequiredArgsConstructor @RestController @RequestMapping("/workflow/instance") public class FlwInstanceController extends BaseController { - @Autowired(required = false) - private InsService insService; - + private final InsService insService; private final IFlwInstanceService flwInstanceService; /** 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 7736b7bf8..5d9535afc 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 @@ -11,6 +11,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.workflow.common.ConditionalOnEnable; import org.dromara.workflow.domain.bo.*; import org.dromara.workflow.domain.vo.FlowHisTaskVo; import org.dromara.workflow.domain.vo.FlowTaskVo; @@ -26,6 +27,7 @@ import java.util.Map; * * @author may */ +@ConditionalOnEnable @Validated @RequiredArgsConstructor @RestController diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/TestLeaveController.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/TestLeaveController.java index e1c246f06..98825d92d 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/TestLeaveController.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/TestLeaveController.java @@ -15,6 +15,7 @@ import org.dromara.common.log.enums.BusinessType; import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.web.core.BaseController; +import org.dromara.workflow.common.ConditionalOnEnable; import org.dromara.workflow.domain.bo.TestLeaveBo; import org.dromara.workflow.domain.vo.TestLeaveVo; import org.dromara.workflow.service.ITestLeaveService; @@ -29,6 +30,7 @@ import java.util.List; * @author may * @date 2023-07-21 */ +@ConditionalOnEnable @Validated @RequiredArgsConstructor @RestController diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/handler/FlowProcessEventHandler.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/handler/FlowProcessEventHandler.java index 9bac6bcd2..656e013e4 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 @@ -6,6 +6,7 @@ import org.dromara.common.core.domain.event.ProcessEvent; import org.dromara.common.core.domain.event.ProcessTaskEvent; import org.dromara.common.core.utils.SpringUtils; import org.dromara.common.tenant.helper.TenantHelper; +import org.dromara.workflow.common.ConditionalOnEnable; import org.springframework.stereotype.Component; /** @@ -14,6 +15,7 @@ import org.springframework.stereotype.Component; * @author may * @date 2024-06-02 */ +@ConditionalOnEnable @Slf4j @Component public class FlowProcessEventHandler { diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/handler/WorkflowPermissionHandler.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/handler/WorkflowPermissionHandler.java index a58709a5f..c18e4ed52 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/handler/WorkflowPermissionHandler.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/handler/WorkflowPermissionHandler.java @@ -4,6 +4,7 @@ import cn.hutool.core.util.ObjectUtil; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.dromara.common.core.domain.model.LoginUser; +import org.dromara.workflow.common.ConditionalOnEnable; import org.dromara.workflow.common.enums.TaskAssigneeEnum; import org.dromara.common.satoken.utils.LoginHelper; import org.dromara.warm.flow.core.dto.FlowParams; @@ -22,6 +23,7 @@ import java.util.stream.Stream; * * @author AprilWind */ +@ConditionalOnEnable @RequiredArgsConstructor @Component @Slf4j 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 35c16bda3..097d74ce7 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 @@ -11,6 +11,7 @@ import org.dromara.warm.flow.core.entity.Task; import org.dromara.warm.flow.core.listener.GlobalListener; import org.dromara.warm.flow.core.listener.ListenerVariable; import org.dromara.warm.flow.orm.entity.FlowTask; +import org.dromara.workflow.common.ConditionalOnEnable; import org.dromara.workflow.handler.FlowProcessEventHandler; import org.dromara.workflow.service.IFlwInstanceService; import org.dromara.workflow.service.IFlwTaskService; @@ -23,6 +24,7 @@ import java.util.List; * * @author may */ +@ConditionalOnEnable @Component @Slf4j @RequiredArgsConstructor diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/CategoryNameTranslationImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/CategoryNameTranslationImpl.java index 4adbadaf7..f13e66645 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/CategoryNameTranslationImpl.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/CategoryNameTranslationImpl.java @@ -4,6 +4,7 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.dromara.common.translation.annotation.TranslationType; import org.dromara.common.translation.core.TranslationInterface; +import org.dromara.workflow.common.ConditionalOnEnable; import org.dromara.workflow.common.constant.FlowConstant; import org.dromara.workflow.service.IFlwCategoryService; import org.springframework.stereotype.Service; @@ -13,6 +14,7 @@ import org.springframework.stereotype.Service; * * @author AprilWind */ +@ConditionalOnEnable @Slf4j @RequiredArgsConstructor @Service diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwCategoryServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwCategoryServiceImpl.java index 368212f10..1e9507b80 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwCategoryServiceImpl.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwCategoryServiceImpl.java @@ -13,13 +13,13 @@ import org.dromara.common.mybatis.helper.DataBaseHelper; import org.dromara.common.satoken.utils.LoginHelper; import org.dromara.warm.flow.core.service.DefService; import org.dromara.warm.flow.orm.entity.FlowDefinition; +import org.dromara.workflow.common.ConditionalOnEnable; import org.dromara.workflow.common.constant.FlowConstant; import org.dromara.workflow.domain.FlowCategory; import org.dromara.workflow.domain.bo.FlowCategoryBo; import org.dromara.workflow.domain.vo.FlowCategoryVo; import org.dromara.workflow.mapper.FlwCategoryMapper; import org.dromara.workflow.service.IFlwCategoryService; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; @@ -32,13 +32,12 @@ import java.util.List; * * @author may */ +@ConditionalOnEnable @RequiredArgsConstructor @Service public class FlwCategoryServiceImpl implements IFlwCategoryService { - @Autowired(required = false) - private DefService defService; - + private final DefService defService; private final FlwCategoryMapper baseMapper; /** 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 6ded1a6d4..4e72371a6 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 @@ -30,13 +30,13 @@ import org.dromara.warm.flow.orm.mapper.FlowDefinitionMapper; import org.dromara.warm.flow.orm.mapper.FlowHisTaskMapper; import org.dromara.warm.flow.orm.mapper.FlowNodeMapper; import org.dromara.warm.flow.orm.mapper.FlowSkipMapper; +import org.dromara.workflow.common.ConditionalOnEnable; import org.dromara.workflow.common.constant.FlowConstant; import org.dromara.workflow.domain.FlowCategory; import org.dromara.workflow.domain.vo.FlowDefinitionVo; import org.dromara.workflow.mapper.FlwCategoryMapper; import org.dromara.workflow.service.IFlwDefinitionService; import org.dromara.workflow.utils.WorkflowUtils; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; @@ -53,22 +53,17 @@ import static org.dromara.common.core.constant.TenantConstants.DEFAULT_TENANT_ID * * @author may */ +@ConditionalOnEnable @Slf4j @RequiredArgsConstructor @Service public class FlwDefinitionServiceImpl implements IFlwDefinitionService { - @Autowired(required = false) - private DefService defService; - @Autowired(required = false) - private FlowDefinitionMapper flowDefinitionMapper; - @Autowired(required = false) - private FlowHisTaskMapper flowHisTaskMapper; - @Autowired(required = false) - private FlowNodeMapper flowNodeMapper; - @Autowired(required = false) - private FlowSkipMapper flowSkipMapper; - + private final DefService defService; + private final FlowDefinitionMapper flowDefinitionMapper; + private final FlowHisTaskMapper flowHisTaskMapper; + private final FlowNodeMapper flowNodeMapper; + private final FlowSkipMapper flowSkipMapper; private final FlwCategoryMapper flwCategoryMapper; /** 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 24f86de11..7f09a4596 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 @@ -34,6 +34,7 @@ import org.dromara.warm.flow.orm.entity.FlowInstance; import org.dromara.warm.flow.orm.entity.FlowTask; import org.dromara.warm.flow.orm.mapper.FlowHisTaskMapper; import org.dromara.warm.flow.orm.mapper.FlowInstanceMapper; +import org.dromara.workflow.common.ConditionalOnEnable; import org.dromara.workflow.common.enums.TaskStatusEnum; import org.dromara.workflow.domain.bo.FlowCancelBo; import org.dromara.workflow.domain.bo.FlowInstanceBo; @@ -47,7 +48,6 @@ import org.dromara.workflow.mapper.FlwInstanceMapper; import org.dromara.workflow.service.IFlwInstanceService; import org.dromara.workflow.service.IFlwTaskService; import org.dromara.workflow.utils.WorkflowUtils; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -60,26 +60,19 @@ import java.util.stream.Collectors; * * @author may */ +@ConditionalOnEnable @Slf4j @RequiredArgsConstructor @Service public class FlwInstanceServiceImpl implements IFlwInstanceService { - @Autowired(required = false) - private InsService insService; - @Autowired(required = false) - private DefService defService; - @Autowired(required = false) - private TaskService taskService; - @Autowired(required = false) - private FlowHisTaskMapper flowHisTaskMapper; - @Autowired(required = false) - private FlowInstanceMapper flowInstanceMapper; - + private final InsService insService; + private final DefService defService; + private final TaskService taskService; + private final FlowHisTaskMapper flowHisTaskMapper; + private final FlowInstanceMapper flowInstanceMapper; private final FlowProcessEventHandler flowProcessEventHandler; - private final IFlwTaskService flwTaskService; - private final FlwInstanceMapper flwInstanceMapper; private final FlwCategoryMapper flwCategoryMapper; diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskAssigneeServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskAssigneeServiceImpl.java index 5f348661b..5877bb503 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskAssigneeServiceImpl.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskAssigneeServiceImpl.java @@ -20,6 +20,7 @@ import org.dromara.warm.flow.ui.dto.HandlerQuery; import org.dromara.warm.flow.ui.dto.TreeFunDto; import org.dromara.warm.flow.ui.service.HandlerSelectService; import org.dromara.warm.flow.ui.vo.HandlerSelectVo; +import org.dromara.workflow.common.ConditionalOnEnable; import org.dromara.workflow.common.enums.TaskAssigneeEnum; import org.dromara.workflow.service.IFlwTaskAssigneeService; import org.springframework.stereotype.Service; @@ -33,6 +34,7 @@ import java.util.Optional; * * @author AprilWind */ +@ConditionalOnEnable @Slf4j @RequiredArgsConstructor @Service 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 11f83ede6..faa7d9394 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 @@ -32,8 +32,8 @@ import org.dromara.warm.flow.core.service.*; import org.dromara.warm.flow.orm.entity.*; import org.dromara.warm.flow.orm.mapper.FlowHisTaskMapper; import org.dromara.warm.flow.orm.mapper.FlowInstanceMapper; -import org.dromara.warm.flow.orm.mapper.FlowNodeMapper; import org.dromara.warm.flow.orm.mapper.FlowTaskMapper; +import org.dromara.workflow.common.ConditionalOnEnable; import org.dromara.workflow.common.enums.TaskAssigneeType; import org.dromara.workflow.common.enums.TaskStatusEnum; import org.dromara.workflow.domain.bo.*; @@ -45,7 +45,6 @@ import org.dromara.workflow.mapper.FlwCategoryMapper; import org.dromara.workflow.mapper.FlwTaskMapper; import org.dromara.workflow.service.IFlwTaskService; import org.dromara.workflow.utils.WorkflowUtils; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -60,36 +59,23 @@ import static org.dromara.workflow.common.constant.FlowConstant.*; * * @author may */ +@ConditionalOnEnable @Slf4j @RequiredArgsConstructor @Service public class FlwTaskServiceImpl implements IFlwTaskService { - @Autowired(required = false) - private TaskService taskService; - @Autowired(required = false) - private InsService insService; - @Autowired(required = false) - private DefService defService; - @Autowired(required = false) - private HisTaskService hisTaskService; - @Autowired(required = false) - private NodeService nodeService; - - @Autowired(required = false) - private FlowInstanceMapper flowInstanceMapper; - @Autowired(required = false) - private FlowTaskMapper flowTaskMapper; - @Autowired(required = false) - private FlowHisTaskMapper flowHisTaskMapper; - @Autowired(required = false) - private FlowNodeMapper flowNodeMapper; - + private final TaskService taskService; + private final InsService insService; + private final DefService defService; + private final HisTaskService hisTaskService; + private final NodeService nodeService; + private final FlowInstanceMapper flowInstanceMapper; + private final FlowTaskMapper flowTaskMapper; + private final FlowHisTaskMapper flowHisTaskMapper; private final IdentifierGenerator identifierGenerator; private final FlowProcessEventHandler flowProcessEventHandler; - private final UserService userService; - private final FlwTaskMapper flwTaskMapper; private final FlwCategoryMapper flwCategoryMapper; 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 499d64b6e..a11e6c19a 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/TestLeaveServiceImpl.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/TestLeaveServiceImpl.java @@ -17,6 +17,7 @@ import org.dromara.common.core.utils.StringUtils; import org.dromara.common.mybatis.core.domain.BaseEntity; import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.workflow.common.ConditionalOnEnable; import org.dromara.workflow.domain.TestLeave; import org.dromara.workflow.domain.bo.TestLeaveBo; import org.dromara.workflow.domain.vo.TestLeaveVo; @@ -34,6 +35,7 @@ import java.util.List; * @author may * @date 2023-07-21 */ +@ConditionalOnEnable @RequiredArgsConstructor @Service @Slf4j diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WorkflowServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WorkflowServiceImpl.java index d00c90735..6be20c4cf 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WorkflowServiceImpl.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WorkflowServiceImpl.java @@ -8,6 +8,7 @@ import org.dromara.common.core.domain.dto.StartProcessDTO; import org.dromara.common.core.service.WorkflowService; import org.dromara.common.core.utils.StringUtils; import org.dromara.warm.flow.orm.entity.FlowInstance; +import org.dromara.workflow.common.ConditionalOnEnable; import org.dromara.workflow.domain.bo.CompleteTaskBo; import org.dromara.workflow.domain.bo.StartProcessBo; import org.dromara.workflow.service.IFlwDefinitionService; @@ -23,6 +24,7 @@ import java.util.Map; * * @author may */ +@ConditionalOnEnable @RequiredArgsConstructor @Service public class WorkflowServiceImpl implements WorkflowService { From dd54cc972a251112359d1d8acbdce8cd3221ffd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Tue, 14 Jan 2025 14:12:19 +0800 Subject: [PATCH 149/175] =?UTF-8?q?fix=20=E4=BF=AE=E5=A4=8D=20=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E5=90=8D=E4=B9=A6=E5=86=99=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/dromara/system/service/impl/SysTenantServiceImpl.java | 2 +- .../java/org/dromara/workflow/common/ConditionalOnEnable.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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 5e5e8cd20..2496e0a7d 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 @@ -196,7 +196,7 @@ public class SysTenantServiceImpl implements ISysTenantService { configMapper.insertBatch(sysConfigList); // 未开启工作流不执行下方操作 - if (SpringUtils.getProperty("workflow.enabled", Boolean.class, false)) { + if (SpringUtils.getProperty("work-flow.enabled", Boolean.class, false)) { WorkflowService workflowService = SpringUtils.getBean(WorkflowService.class); // 新增租户流程定义 workflowService.syncDef(tenantId); diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/ConditionalOnEnable.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/ConditionalOnEnable.java index 8adf0158b..e04426496 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/ConditionalOnEnable.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/ConditionalOnEnable.java @@ -9,6 +9,6 @@ import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.TYPE, ElementType.METHOD }) -@ConditionalOnProperty(value = "workflow.enabled", havingValue = "true") +@ConditionalOnProperty(value = "work-flow.enabled", havingValue = "true") public @interface ConditionalOnEnable { } From cb71df8a4293be196e1b74463a6e5520303e3cad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Tue, 14 Jan 2025 14:41:01 +0800 Subject: [PATCH 150/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E5=B7=A5?= =?UTF-8?q?=E4=BD=9C=E6=B5=81=E4=BD=BF=E7=94=A8=E7=B3=BB=E7=BB=9F=E8=87=AA?= =?UTF-8?q?=E5=B8=A6=E9=9B=AA=E8=8A=B1=E7=94=9F=E6=88=90=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ruoyi-admin/src/main/resources/application.yml | 2 +- .../dromara/workflow/config/WarmFlowConfig.java | 16 +++++++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml index 9db74dc3f..dbe16888d 100644 --- a/ruoyi-admin/src/main/resources/application.yml +++ b/ruoyi-admin/src/main/resources/application.yml @@ -276,7 +276,7 @@ websocket: --- # warm-flow工作流配置 warm-flow: # 是否开启工作流,默认true - enabled: false + enabled: true # 是否开启设计器ui ui: true # 默认Authorization,如果有多个token,用逗号分隔 diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/config/WarmFlowConfig.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/config/WarmFlowConfig.java index 4dec5b1cc..8bae9515f 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/config/WarmFlowConfig.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/config/WarmFlowConfig.java @@ -1,7 +1,12 @@ package org.dromara.workflow.config; +import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator; +import org.dromara.warm.flow.core.config.WarmFlow; +import org.dromara.warm.flow.core.utils.IdUtils; +import org.dromara.warm.plugin.modes.sb.config.BeanConfig; import org.dromara.workflow.common.ConditionalOnEnable; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; /** @@ -11,7 +16,16 @@ import org.springframework.context.annotation.Configuration; */ @ConditionalOnEnable @Configuration -public class WarmFlowConfig { +public class WarmFlowConfig extends BeanConfig { + + @Autowired + private IdentifierGenerator identifierGenerator; + + @Override + public void after(WarmFlow flowConfig) { + // 设置Mybatis-Plus默认主键生成器 + IdUtils.setInstanceNative(() -> identifierGenerator.nextId(null).longValue()); + } } From 62b7d96551d2c2ab7f31b95b9ff6538097e5f66b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Tue, 14 Jan 2025 23:00:04 +0800 Subject: [PATCH 151/175] =?UTF-8?q?fix=20=E4=BF=AE=E5=A4=8D=20=E5=AE=9E?= =?UTF-8?q?=E4=BD=93=E7=B1=BB=E6=96=B9=E6=B3=95=E4=B9=A6=E5=86=99=E9=94=99?= =?UTF-8?q?=E8=AF=AF(=E4=B8=8D=E5=BD=B1=E5=93=8D=E5=8A=9F=E8=83=BD)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/org/dromara/generator/domain/GenTableColumn.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/domain/GenTableColumn.java b/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/domain/GenTableColumn.java index e1560b421..6b2e429ed 100644 --- a/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/domain/GenTableColumn.java +++ b/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/domain/GenTableColumn.java @@ -159,7 +159,7 @@ public class GenTableColumn extends BaseEntity { } public boolean isEdit() { - return isInsert(this.isEdit); + return isEdit(this.isEdit); } public boolean isEdit(String isEdit) { From 3444b50da6c65abeddb80666b840946a0529518a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Wed, 15 Jan 2025 09:56:02 +0800 Subject: [PATCH 152/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E5=B7=A5?= =?UTF-8?q?=E4=BD=9C=E6=B5=81=E9=85=8D=E7=BD=AE=E4=B9=A6=E5=86=99=E9=94=99?= =?UTF-8?q?=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/dromara/system/service/impl/SysTenantServiceImpl.java | 2 +- .../java/org/dromara/workflow/common/ConditionalOnEnable.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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 2496e0a7d..f31bd3027 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTenantServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTenantServiceImpl.java @@ -196,7 +196,7 @@ public class SysTenantServiceImpl implements ISysTenantService { configMapper.insertBatch(sysConfigList); // 未开启工作流不执行下方操作 - if (SpringUtils.getProperty("work-flow.enabled", Boolean.class, false)) { + if (SpringUtils.getProperty("warm-flow.enabled", Boolean.class, false)) { WorkflowService workflowService = SpringUtils.getBean(WorkflowService.class); // 新增租户流程定义 workflowService.syncDef(tenantId); diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/ConditionalOnEnable.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/ConditionalOnEnable.java index e04426496..5d24b3509 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/ConditionalOnEnable.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/ConditionalOnEnable.java @@ -9,6 +9,6 @@ import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.TYPE, ElementType.METHOD }) -@ConditionalOnProperty(value = "work-flow.enabled", havingValue = "true") +@ConditionalOnProperty(value = "warm-flow.enabled", havingValue = "true") public @interface ConditionalOnEnable { } From 4ba4ea4fcc559a746daf44f276867e97e580019e Mon Sep 17 00:00:00 2001 From: AprilWind <2100166581@qq.com> Date: Wed, 15 Jan 2025 16:56:09 +0800 Subject: [PATCH 153/175] =?UTF-8?q?update=20=E5=8D=87=E7=BA=A7warm-flow?= =?UTF-8?q?=E5=88=B01.6.0-m4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 2 +- .../workflow/config/WarmFlowConfig.java | 17 +----- .../controller/FlwDefinitionController.java | 10 ++-- .../service/IFlwDefinitionService.java | 2 +- .../impl/FlwDefinitionServiceImpl.java | 57 +++++++++---------- .../service/impl/FlwInstanceServiceImpl.java | 26 ++++----- 6 files changed, 44 insertions(+), 70 deletions(-) diff --git a/pom.xml b/pom.xml index 2993af438..82ed3a855 100644 --- a/pom.xml +++ b/pom.xml @@ -50,7 +50,7 @@ 8.7.2-20241022 - 1.3.7 + 1.6.0-m4 3.2.2 diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/config/WarmFlowConfig.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/config/WarmFlowConfig.java index 8bae9515f..08f1808d1 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/config/WarmFlowConfig.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/config/WarmFlowConfig.java @@ -1,12 +1,6 @@ package org.dromara.workflow.config; - -import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator; -import org.dromara.warm.flow.core.config.WarmFlow; -import org.dromara.warm.flow.core.utils.IdUtils; -import org.dromara.warm.plugin.modes.sb.config.BeanConfig; import org.dromara.workflow.common.ConditionalOnEnable; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; /** @@ -16,16 +10,7 @@ import org.springframework.context.annotation.Configuration; */ @ConditionalOnEnable @Configuration -public class WarmFlowConfig extends BeanConfig { - - @Autowired - private IdentifierGenerator identifierGenerator; - - @Override - public void after(WarmFlow flowConfig) { - // 设置Mybatis-Plus默认主键生成器 - IdUtils.setInstanceNative(() -> identifierGenerator.nextId(null).longValue()); - } +public class WarmFlowConfig { } diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwDefinitionController.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwDefinitionController.java index 1310da3f6..10d9de838 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwDefinitionController.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwDefinitionController.java @@ -104,7 +104,6 @@ public class FlwDefinitionController extends BaseController { @Log(title = "流程定义", businessType = BusinessType.INSERT) @PutMapping("/publish/{id}") @RepeatSubmit() - @Transactional(rollbackFor = Exception.class) public R publish(@PathVariable Long id) { return R.ok(flwDefinitionService.publish(id)); } @@ -127,7 +126,6 @@ public class FlwDefinitionController extends BaseController { */ @Log(title = "流程定义", businessType = BusinessType.DELETE) @DeleteMapping("/{ids}") - @Transactional(rollbackFor = Exception.class) public R remove(@PathVariable List ids) { return toAjax(flwDefinitionService.removeDef(ids)); } @@ -153,9 +151,8 @@ public class FlwDefinitionController extends BaseController { */ @Log(title = "流程定义", businessType = BusinessType.IMPORT) @PostMapping("/importDef") - @Transactional(rollbackFor = Exception.class) public R importDef(MultipartFile file, String category) { - return R.ok(flwDefinitionService.importXml(file, category)); + return R.ok(flwDefinitionService.importJson(file, category)); } /** @@ -172,13 +169,13 @@ public class FlwDefinitionController extends BaseController { } /** - * 获取流程定义xml字符串 + * 获取流程定义JSON字符串 * * @param id 流程定义id */ @GetMapping("/xmlString/{id}") public R xmlString(@PathVariable Long id) { - return R.ok("操作成功", defService.xmlString(id)); + return R.ok("操作成功", defService.exportJson(id)); } /** @@ -189,6 +186,7 @@ public class FlwDefinitionController extends BaseController { */ @RepeatSubmit() @PutMapping("/active/{id}") + @Transactional(rollbackFor = Exception.class) public R active(@PathVariable Long id, @RequestParam boolean active) { return R.ok(active ? defService.active(id) : defService.unActive(id)); } diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwDefinitionService.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwDefinitionService.java index 6b5ca594a..1a2d29f77 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwDefinitionService.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwDefinitionService.java @@ -60,7 +60,7 @@ public interface IFlwDefinitionService { * @param category 分类 * @return 结果 */ - boolean importXml(MultipartFile file, String category); + boolean importJson(MultipartFile file, String category); /** * 删除流程定义 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 4e72371a6..da547ef95 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 @@ -3,22 +3,21 @@ package org.dromara.workflow.service.impl; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.convert.Convert; +import cn.hutool.core.io.IoUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.dom4j.Document; -import org.dom4j.io.OutputFormat; -import org.dom4j.io.XMLWriter; import org.dromara.common.core.exception.ServiceException; +import org.dromara.common.core.utils.DateUtils; import org.dromara.common.core.utils.StreamUtils; import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.json.utils.JsonUtils; import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.TableDataInfo; -import org.dromara.warm.flow.core.dto.FlowCombine; -import org.dromara.warm.flow.core.entity.Definition; +import org.dromara.warm.flow.core.dto.DefJson; import org.dromara.warm.flow.core.enums.NodeType; import org.dromara.warm.flow.core.enums.PublishStatus; import org.dromara.warm.flow.core.service.DefService; @@ -42,6 +41,8 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -120,6 +121,7 @@ public class FlwDefinitionServiceImpl implements IFlwDefinitionService { * @param id 流程定义id */ @Override + @Transactional(rollbackFor = Exception.class) public boolean publish(Long id) { List flowNodes = flowNodeMapper.selectList(new LambdaQueryWrapper().eq(FlowNode::getDefinitionId, id)); List errorMsg = new ArrayList<>(); @@ -143,16 +145,20 @@ public class FlwDefinitionServiceImpl implements IFlwDefinitionService { * @param file 文件 */ @Override - public boolean importXml(MultipartFile file, String category) { - try { - FlowCombine combine = defService.readXml(file.getInputStream()); - // 流程定义 - Definition definition = combine.getDefinition(); - definition.setCategory(category); - defService.importFlow(combine); + @Transactional(rollbackFor = Exception.class) + public boolean importJson(MultipartFile file, String category) { + try (InputStream inputStream = file.getInputStream()) { + byte[] fileBytes = inputStream.readAllBytes(); + String fileContent = new String(fileBytes, StandardCharsets.UTF_8); + DefJson defJson = JsonUtils.parseObject(fileContent, DefJson.class); + defJson.setCategory(category); + defService.importDef(defJson); + } catch (IOException e) { + log.error("读取文件流错误: {}", e.getMessage(), e); + throw new IllegalStateException("文件读取失败,请检查文件内容", e); } catch (Exception e) { log.error("导入流程定义错误: {}", e.getMessage(), e); - throw new RuntimeException(e); + throw new IllegalStateException("导入流程定义失败", e); } return true; } @@ -166,24 +172,15 @@ public class FlwDefinitionServiceImpl implements IFlwDefinitionService { */ @Override public void exportDef(Long id, HttpServletResponse response) throws IOException { - Document document = defService.exportXml(id); - // 设置生成xml的格式 - OutputFormat of = OutputFormat.createPrettyPrint(); - // 设置编码格式 - of.setEncoding("UTF-8"); - of.setIndent(true); - of.setIndent(" "); - of.setNewlines(true); - - // 创建一个xml文档编辑器 - XMLWriter writer = new XMLWriter(response.getOutputStream(), of); - writer.setEscapeText(false); + byte[] data = defService.exportJson(id).getBytes(StandardCharsets.UTF_8); + String filename = "workflow_export_" + DateUtils.dateTimeNow() + ".json"; + // 设置响应头和内容类型 response.reset(); - response.setCharacterEncoding("UTF-8"); - response.setContentType("application/x-msdownload"); - response.setHeader("Content-Disposition", "attachment;"); - writer.write(document); - writer.close(); + response.setCharacterEncoding(StandardCharsets.UTF_8.name()); + response.setContentType("application/json"); + response.setHeader("Content-Disposition", "attachment; filename=" + filename); + response.addHeader("Content-Length", "" + data.length); + IoUtil.write(response.getOutputStream(), false, data); } /** 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 7f09a4596..f5153c8db 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 @@ -19,13 +19,14 @@ import org.dromara.common.core.utils.StringUtils; import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.satoken.utils.LoginHelper; -import org.dromara.warm.flow.core.FlowFactory; +import org.dromara.warm.flow.core.FlowEngine; import org.dromara.warm.flow.core.constant.ExceptionCons; import org.dromara.warm.flow.core.dto.FlowParams; import org.dromara.warm.flow.core.entity.Definition; import org.dromara.warm.flow.core.entity.Instance; import org.dromara.warm.flow.core.entity.Task; import org.dromara.warm.flow.core.enums.NodeType; +import org.dromara.warm.flow.core.service.ChartService; import org.dromara.warm.flow.core.service.DefService; import org.dromara.warm.flow.core.service.InsService; import org.dromara.warm.flow.core.service.TaskService; @@ -51,7 +52,6 @@ import org.dromara.workflow.utils.WorkflowUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.io.IOException; import java.util.*; import java.util.stream.Collectors; @@ -68,6 +68,7 @@ public class FlwInstanceServiceImpl implements IFlwInstanceService { private final InsService insService; private final DefService defService; + private final ChartService chartService; private final TaskService taskService; private final FlowHisTaskMapper flowHisTaskMapper; private final FlowInstanceMapper flowInstanceMapper; @@ -248,7 +249,7 @@ public class FlwInstanceServiceImpl implements IFlwInstanceService { //撤销 WorkflowUtils.backTask(message, instance.getId(), applyNodeCode, BusinessStatusEnum.CANCEL.getStatus(), BusinessStatusEnum.CANCEL.getStatus()); //判断或签节点是否有多个,只保留一个 - List currentTaskList = taskService.list(FlowFactory.newTask().setInstanceId(instance.getId())); + List currentTaskList = taskService.list(FlowEngine.newTask().setInstanceId(instance.getId())); if (CollUtil.isNotEmpty(currentTaskList)) { if (currentTaskList.size() > 1) { currentTaskList.remove(0); @@ -284,14 +285,14 @@ public class FlwInstanceServiceImpl implements IFlwInstanceService { */ @Override public Map flowImage(String businessId) { - Map map = new HashMap<>(16); FlowInstance flowInstance = this.selectInstByBusinessId(businessId); - if (flowInstance == null) { + if (ObjectUtil.isNull(flowInstance)) { throw new ServiceException(ExceptionCons.NOT_FOUNT_INSTANCE); } + Long instanceId = flowInstance.getId(); //运行中的任务 List list = new ArrayList<>(); - List flowTaskList = flwTaskService.selectByInstId(flowInstance.getId()); + List flowTaskList = flwTaskService.selectByInstId(instanceId); if (CollUtil.isNotEmpty(flowTaskList)) { List flowHisTaskVos = BeanUtil.copyToList(flowTaskList, FlowHisTaskVo.class); for (FlowHisTaskVo flowHisTaskVo : flowHisTaskVos) { @@ -312,22 +313,15 @@ public class FlwInstanceServiceImpl implements IFlwInstanceService { } //历史任务 LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(); - wrapper.eq(FlowHisTask::getInstanceId, flowInstance.getId()); + wrapper.eq(FlowHisTask::getInstanceId, instanceId); wrapper.eq(FlowHisTask::getNodeType, NodeType.BETWEEN.getKey()); wrapper.orderByDesc(FlowHisTask::getCreateTime).orderByDesc(FlowHisTask::getUpdateTime); List flowHisTasks = flowHisTaskMapper.selectList(wrapper); if (CollUtil.isNotEmpty(flowHisTasks)) { list.addAll(BeanUtil.copyToList(flowHisTasks, FlowHisTaskVo.class)); } - - map.put("list", list); - try { - String flowChart = defService.flowChart(flowInstance.getId()); - map.put("image", flowChart); - } catch (IOException e) { - throw new RuntimeException(e); - } - return map; + String flowChart = chartService.chartIns(instanceId); + return Map.of("list", list, "image", flowChart); } /** From 652f5161a91475ae0c22a88eb06b36b240edb744 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Wed, 15 Jan 2025 17:40:31 +0800 Subject: [PATCH 154/175] =?UTF-8?q?update=20=E9=80=82=E9=85=8D=20=E6=96=B0?= =?UTF-8?q?=E7=89=88=E6=9C=AC=E5=B0=86xml=E8=BD=AC=E4=B8=BAjson?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../impl/FlwDefinitionServiceImpl.java | 16 +-- script/bpmn/leave1.json | 75 +++++++++++ script/bpmn/leave1.xml | 17 --- script/bpmn/leave2.json | 111 ++++++++++++++++ script/bpmn/leave2.xml | 24 ---- script/bpmn/leave3.json | 121 ++++++++++++++++++ script/bpmn/leave3.xml | 27 ---- script/bpmn/leave4.json | 90 +++++++++++++ script/bpmn/leave4.xml | 20 --- script/bpmn/leave5.json | 121 ++++++++++++++++++ script/bpmn/leave5.xml | 27 ---- 11 files changed, 522 insertions(+), 127 deletions(-) create mode 100644 script/bpmn/leave1.json delete mode 100644 script/bpmn/leave1.xml create mode 100644 script/bpmn/leave2.json delete mode 100644 script/bpmn/leave2.xml create mode 100644 script/bpmn/leave3.json delete mode 100644 script/bpmn/leave3.xml create mode 100644 script/bpmn/leave4.json delete mode 100644 script/bpmn/leave4.xml create mode 100644 script/bpmn/leave5.json delete mode 100644 script/bpmn/leave5.xml 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 da547ef95..a881ba692 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 @@ -11,7 +11,6 @@ import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.dromara.common.core.exception.ServiceException; -import org.dromara.common.core.utils.DateUtils; import org.dromara.common.core.utils.StreamUtils; import org.dromara.common.core.utils.StringUtils; import org.dromara.common.json.utils.JsonUtils; @@ -41,7 +40,6 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; import java.io.IOException; -import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; @@ -147,18 +145,13 @@ public class FlwDefinitionServiceImpl implements IFlwDefinitionService { @Override @Transactional(rollbackFor = Exception.class) public boolean importJson(MultipartFile file, String category) { - try (InputStream inputStream = file.getInputStream()) { - byte[] fileBytes = inputStream.readAllBytes(); - String fileContent = new String(fileBytes, StandardCharsets.UTF_8); - DefJson defJson = JsonUtils.parseObject(fileContent, DefJson.class); + try { + DefJson defJson = JsonUtils.parseObject(file.getBytes(), DefJson.class); defJson.setCategory(category); defService.importDef(defJson); } catch (IOException e) { log.error("读取文件流错误: {}", e.getMessage(), e); throw new IllegalStateException("文件读取失败,请检查文件内容", e); - } catch (Exception e) { - log.error("导入流程定义错误: {}", e.getMessage(), e); - throw new IllegalStateException("导入流程定义失败", e); } return true; } @@ -173,12 +166,11 @@ public class FlwDefinitionServiceImpl implements IFlwDefinitionService { @Override public void exportDef(Long id, HttpServletResponse response) throws IOException { byte[] data = defService.exportJson(id).getBytes(StandardCharsets.UTF_8); - String filename = "workflow_export_" + DateUtils.dateTimeNow() + ".json"; // 设置响应头和内容类型 response.reset(); response.setCharacterEncoding(StandardCharsets.UTF_8.name()); - response.setContentType("application/json"); - response.setHeader("Content-Disposition", "attachment; filename=" + filename); + response.setContentType("application/text"); + response.setHeader("Content-Disposition", "attachment;"); response.addHeader("Content-Length", "" + data.length); IoUtil.write(response.getOutputStream(), false, data); } diff --git a/script/bpmn/leave1.json b/script/bpmn/leave1.json new file mode 100644 index 000000000..0cf67bc46 --- /dev/null +++ b/script/bpmn/leave1.json @@ -0,0 +1,75 @@ +{ + "flowCode" : "leave1", + "flowName" : "请假申请-普通", + "category" : "1", + "version" : "1", + "formCustom" : "N", + "formPath" : "/workflow/leaveEdit/index", + "nodeList" : [ { + "nodeType" : 0, + "nodeCode" : "d5ee3ddf-3968-4379-a86f-9ceabde5faac", + "nodeName" : "开始", + "nodeRatio" : 0.000, + "coordinate" : "200,200|200,200", + "skipAnyNode" : "N", + "formCustom" : "N", + "skipList" : [ { + "nowNodeCode" : "d5ee3ddf-3968-4379-a86f-9ceabde5faac", + "nextNodeCode" : "dd515cdd-59f6-446f-94ca-25ca062afb42", + "skipType" : "PASS", + "coordinate" : "220,200;310,200" + } ] + }, { + "nodeType" : 1, + "nodeCode" : "dd515cdd-59f6-446f-94ca-25ca062afb42", + "nodeName" : "申请人", + "nodeRatio" : 0.000, + "coordinate" : "360,200|360,200", + "skipAnyNode" : "N", + "formCustom" : "N", + "skipList" : [ { + "nowNodeCode" : "dd515cdd-59f6-446f-94ca-25ca062afb42", + "nextNodeCode" : "78fa8e5b-e809-44ed-978a-41092409ebcf", + "skipType" : "PASS", + "coordinate" : "410,200;490,200" + } ] + }, { + "nodeType" : 1, + "nodeCode" : "78fa8e5b-e809-44ed-978a-41092409ebcf", + "nodeName" : "组长", + "permissionFlag" : "role:1", + "nodeRatio" : 0.000, + "coordinate" : "540,200|540,200", + "skipAnyNode" : "N", + "formCustom" : "N", + "skipList" : [ { + "nowNodeCode" : "78fa8e5b-e809-44ed-978a-41092409ebcf", + "nextNodeCode" : "a8abf15f-b83e-428a-86cc-033555ea9bbe", + "skipType" : "PASS", + "coordinate" : "590,200;670,200" + } ] + }, { + "nodeType" : 1, + "nodeCode" : "a8abf15f-b83e-428a-86cc-033555ea9bbe", + "nodeName" : "部门主管", + "permissionFlag" : "role:3,role:4", + "nodeRatio" : 0.000, + "coordinate" : "720,200|720,200", + "skipAnyNode" : "N", + "formCustom" : "N", + "skipList" : [ { + "nowNodeCode" : "a8abf15f-b83e-428a-86cc-033555ea9bbe", + "nextNodeCode" : "8b82b7d7-8660-455e-b880-d6d22ea3eb6d", + "skipType" : "PASS", + "coordinate" : "770,200;880,200" + } ] + }, { + "nodeType" : 2, + "nodeCode" : "8b82b7d7-8660-455e-b880-d6d22ea3eb6d", + "nodeName" : "结束", + "nodeRatio" : 0.000, + "coordinate" : "900,200|900,200", + "skipAnyNode" : "N", + "formCustom" : "N" + } ] +} \ No newline at end of file diff --git a/script/bpmn/leave1.xml b/script/bpmn/leave1.xml deleted file mode 100644 index 1013eb24e..000000000 --- a/script/bpmn/leave1.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - dd515cdd-59f6-446f-94ca-25ca062afb42 - - - 78fa8e5b-e809-44ed-978a-41092409ebcf - - - a8abf15f-b83e-428a-86cc-033555ea9bbe - - - 8b82b7d7-8660-455e-b880-d6d22ea3eb6d - - - diff --git a/script/bpmn/leave2.json b/script/bpmn/leave2.json new file mode 100644 index 000000000..9fce8ffd2 --- /dev/null +++ b/script/bpmn/leave2.json @@ -0,0 +1,111 @@ +{ + "flowCode" : "leave2", + "flowName" : "请假申请-排他网关", + "category" : "1", + "version" : "1", + "formCustom" : "N", + "formPath" : "/workflow/leaveEdit/index", + "nodeList" : [ { + "nodeType" : 0, + "nodeCode" : "cef3895c-f7d8-4598-8bf3-8ec2ef6ce84a", + "nodeName" : "开始", + "nodeRatio" : 0.000, + "coordinate" : "300,240|300,240", + "skipAnyNode" : "N", + "formCustom" : "N", + "skipList" : [ { + "nowNodeCode" : "cef3895c-f7d8-4598-8bf3-8ec2ef6ce84a", + "nextNodeCode" : "fdcae93b-b69c-498a-b231-09255e74bcbd", + "skipType" : "PASS", + "coordinate" : "320,240;390,240" + } ] + }, { + "nodeType" : 1, + "nodeCode" : "fdcae93b-b69c-498a-b231-09255e74bcbd", + "nodeName" : "申请人", + "nodeRatio" : 0.000, + "coordinate" : "440,240|440,240", + "skipAnyNode" : "N", + "formCustom" : "N", + "skipList" : [ { + "nowNodeCode" : "fdcae93b-b69c-498a-b231-09255e74bcbd", + "nextNodeCode" : "7b8c7ead-7dc8-4951-a7f3-f0c41995909e", + "skipType" : "PASS", + "coordinate" : "490,240;535,240" + } ] + }, { + "nodeType" : 3, + "nodeCode" : "7b8c7ead-7dc8-4951-a7f3-f0c41995909e", + "nodeRatio" : 0.000, + "coordinate" : "560,240", + "skipAnyNode" : "N", + "formCustom" : "N", + "skipList" : [ { + "nowNodeCode" : "7b8c7ead-7dc8-4951-a7f3-f0c41995909e", + "nextNodeCode" : "b3528155-dcb7-4445-bbdf-3d00e3499e86", + "skipType" : "PASS", + "skipCondition" : "le@@leaveDays|2", + "coordinate" : "560,265;560,320;670,320" + }, { + "nowNodeCode" : "7b8c7ead-7dc8-4951-a7f3-f0c41995909e", + "nextNodeCode" : "5ed2362b-fc0c-4d52-831f-95208b830605", + "skipName" : "大于两天", + "skipType" : "PASS", + "skipCondition" : "gt@@leaveDays|2", + "coordinate" : "560,215;560,160;670,160|560,187" + } ] + }, { + "nodeType" : 1, + "nodeCode" : "b3528155-dcb7-4445-bbdf-3d00e3499e86", + "nodeName" : "组长", + "permissionFlag" : "3,4", + "nodeRatio" : 0.000, + "coordinate" : "720,320|720,320", + "skipAnyNode" : "N", + "formCustom" : "N", + "skipList" : [ { + "nowNodeCode" : "b3528155-dcb7-4445-bbdf-3d00e3499e86", + "nextNodeCode" : "c9fa6d7d-2a74-4e78-b947-0cad8a6af869", + "skipType" : "PASS", + "coordinate" : "770,320;860,320;860,280" + } ] + }, { + "nodeType" : 1, + "nodeCode" : "c9fa6d7d-2a74-4e78-b947-0cad8a6af869", + "nodeName" : "总经理", + "permissionFlag" : "role:1", + "nodeRatio" : 0.000, + "coordinate" : "860,240|860,240", + "skipAnyNode" : "N", + "formCustom" : "N", + "skipList" : [ { + "nowNodeCode" : "c9fa6d7d-2a74-4e78-b947-0cad8a6af869", + "nextNodeCode" : "40aa65fd-0712-4d23-b6f7-d0432b920fd1", + "skipType" : "PASS", + "coordinate" : "910,240;980,240" + } ] + }, { + "nodeType" : 2, + "nodeCode" : "40aa65fd-0712-4d23-b6f7-d0432b920fd1", + "nodeName" : "结束", + "nodeRatio" : 0.000, + "coordinate" : "1000,240|1000,240", + "skipAnyNode" : "N", + "formCustom" : "N" + }, { + "nodeType" : 1, + "nodeCode" : "5ed2362b-fc0c-4d52-831f-95208b830605", + "nodeName" : "部门领导", + "permissionFlag" : "role:1", + "nodeRatio" : 0.000, + "coordinate" : "720,160|720,160", + "skipAnyNode" : "N", + "formCustom" : "N", + "skipList" : [ { + "nowNodeCode" : "5ed2362b-fc0c-4d52-831f-95208b830605", + "nextNodeCode" : "c9fa6d7d-2a74-4e78-b947-0cad8a6af869", + "skipType" : "PASS", + "coordinate" : "770,160;860,160;860,200" + } ] + } ] +} diff --git a/script/bpmn/leave2.xml b/script/bpmn/leave2.xml deleted file mode 100644 index 35d270fda..000000000 --- a/script/bpmn/leave2.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - fdcae93b-b69c-498a-b231-09255e74bcbd - - - 7b8c7ead-7dc8-4951-a7f3-f0c41995909e - - - b3528155-dcb7-4445-bbdf-3d00e3499e86 - 5ed2362b-fc0c-4d52-831f-95208b830605 - - - c9fa6d7d-2a74-4e78-b947-0cad8a6af869 - - - 40aa65fd-0712-4d23-b6f7-d0432b920fd1 - - - - c9fa6d7d-2a74-4e78-b947-0cad8a6af869 - - diff --git a/script/bpmn/leave3.json b/script/bpmn/leave3.json new file mode 100644 index 000000000..08daae4bf --- /dev/null +++ b/script/bpmn/leave3.json @@ -0,0 +1,121 @@ +{ + "flowCode" : "leave3", + "flowName" : "请假申请-并行网关", + "category" : "1", + "version" : "1", + "formCustom" : "N", + "formPath" : "/workflow/leaveEdit/index", + "nodeList" : [ { + "nodeType" : 0, + "nodeCode" : "a80ecf9f-f465-4ae5-a429-e30ec5d0f957", + "nodeName" : "开始", + "nodeRatio" : 0.000, + "coordinate" : "380,220|380,220", + "skipAnyNode" : "N", + "formCustom" : "N", + "skipList" : [ { + "nowNodeCode" : "a80ecf9f-f465-4ae5-a429-e30ec5d0f957", + "nextNodeCode" : "b7bbb571-06de-455c-8083-f83c07bf0b99", + "skipType" : "PASS", + "coordinate" : "400,220;470,220" + } ] + }, { + "nodeType" : 1, + "nodeCode" : "b7bbb571-06de-455c-8083-f83c07bf0b99", + "nodeName" : "申请人", + "nodeRatio" : 0.000, + "coordinate" : "520,220|520,220", + "skipAnyNode" : "N", + "formCustom" : "N", + "skipList" : [ { + "nowNodeCode" : "b7bbb571-06de-455c-8083-f83c07bf0b99", + "nextNodeCode" : "84d7ed24-bb44-4ba1-bf1f-e6f5092d3f0a", + "skipType" : "PASS", + "coordinate" : "570,220;655,220" + } ] + }, { + "nodeType" : 4, + "nodeCode" : "84d7ed24-bb44-4ba1-bf1f-e6f5092d3f0a", + "nodeRatio" : 0.000, + "coordinate" : "680,220", + "skipAnyNode" : "N", + "formCustom" : "N", + "skipList" : [ { + "nowNodeCode" : "84d7ed24-bb44-4ba1-bf1f-e6f5092d3f0a", + "nextNodeCode" : "4b7743cd-940c-431b-926f-e7b614fbf1fe", + "skipType" : "PASS", + "coordinate" : "680,195;680,140;750,140" + }, { + "nowNodeCode" : "84d7ed24-bb44-4ba1-bf1f-e6f5092d3f0a", + "nextNodeCode" : "762cb975-37d8-4276-b6db-79a4c3606394", + "skipType" : "PASS", + "coordinate" : "680,245;680,300;750,300" + } ] + }, { + "nodeType" : 1, + "nodeCode" : "4b7743cd-940c-431b-926f-e7b614fbf1fe", + "nodeName" : "市场部", + "permissionFlag" : "role:1", + "nodeRatio" : 0.000, + "coordinate" : "800,140|800,140", + "skipAnyNode" : "N", + "formCustom" : "N", + "skipList" : [ { + "nowNodeCode" : "4b7743cd-940c-431b-926f-e7b614fbf1fe", + "nextNodeCode" : "b66b6563-f9fe-41cc-a782-f7837bb6f3d2", + "skipType" : "PASS", + "coordinate" : "850,140;920,140;920,195" + } ] + }, { + "nodeType" : 4, + "nodeCode" : "b66b6563-f9fe-41cc-a782-f7837bb6f3d2", + "nodeRatio" : 0.000, + "coordinate" : "920,220", + "skipAnyNode" : "N", + "formCustom" : "N", + "skipList" : [ { + "nowNodeCode" : "b66b6563-f9fe-41cc-a782-f7837bb6f3d2", + "nextNodeCode" : "23e7429e-2b47-4431-b93e-40db7c431ce6", + "skipType" : "PASS", + "coordinate" : "945,220;975,220;975,220;960,220;960,220;990,220" + } ] + }, { + "nodeType" : 1, + "nodeCode" : "23e7429e-2b47-4431-b93e-40db7c431ce6", + "nodeName" : "CEO", + "permissionFlag" : "1", + "nodeRatio" : 0.000, + "coordinate" : "1040,220|1040,220", + "skipAnyNode" : "N", + "formCustom" : "N", + "skipList" : [ { + "nowNodeCode" : "23e7429e-2b47-4431-b93e-40db7c431ce6", + "nextNodeCode" : "f5ace37f-5a5e-4e64-a6f6-913ab9a71cd1", + "skipType" : "PASS", + "coordinate" : "1090,220;1140,220" + } ] + }, { + "nodeType" : 2, + "nodeCode" : "f5ace37f-5a5e-4e64-a6f6-913ab9a71cd1", + "nodeName" : "结束", + "nodeRatio" : 0.000, + "coordinate" : "1160,220|1160,220", + "skipAnyNode" : "N", + "formCustom" : "N" + }, { + "nodeType" : 1, + "nodeCode" : "762cb975-37d8-4276-b6db-79a4c3606394", + "nodeName" : "综合部", + "permissionFlag" : "role:3,role:4", + "nodeRatio" : 0.000, + "coordinate" : "800,300|800,300", + "skipAnyNode" : "N", + "formCustom" : "N", + "skipList" : [ { + "nowNodeCode" : "762cb975-37d8-4276-b6db-79a4c3606394", + "nextNodeCode" : "b66b6563-f9fe-41cc-a782-f7837bb6f3d2", + "skipType" : "PASS", + "coordinate" : "850,300;920,300;920,245" + } ] + } ] +} \ No newline at end of file diff --git a/script/bpmn/leave3.xml b/script/bpmn/leave3.xml deleted file mode 100644 index ffb8d9505..000000000 --- a/script/bpmn/leave3.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - b7bbb571-06de-455c-8083-f83c07bf0b99 - - - 84d7ed24-bb44-4ba1-bf1f-e6f5092d3f0a - - - 4b7743cd-940c-431b-926f-e7b614fbf1fe - 762cb975-37d8-4276-b6db-79a4c3606394 - - - b66b6563-f9fe-41cc-a782-f7837bb6f3d2 - - - 23e7429e-2b47-4431-b93e-40db7c431ce6 - - - f5ace37f-5a5e-4e64-a6f6-913ab9a71cd1 - - - - b66b6563-f9fe-41cc-a782-f7837bb6f3d2 - - diff --git a/script/bpmn/leave4.json b/script/bpmn/leave4.json new file mode 100644 index 000000000..f8f440812 --- /dev/null +++ b/script/bpmn/leave4.json @@ -0,0 +1,90 @@ +{ + "flowCode" : "leave4", + "flowName" : "请假申请-会签", + "category" : "1", + "version" : "1", + "formCustom" : "N", + "formPath" : "/workflow/leaveEdit/index", + "nodeList" : [ { + "nodeType" : 0, + "nodeCode" : "9ce8bf00-f25b-4fc6-91b8-827082fc4876", + "nodeName" : "开始", + "nodeRatio" : 0.000, + "coordinate" : "320,240|320,240", + "skipAnyNode" : "N", + "formCustom" : "N", + "skipList" : [ { + "nowNodeCode" : "9ce8bf00-f25b-4fc6-91b8-827082fc4876", + "nextNodeCode" : "e90b98ef-35b4-410c-a663-bae8b7624b9f", + "skipType" : "PASS", + "coordinate" : "340,240;410,240" + } ] + }, { + "nodeType" : 1, + "nodeCode" : "e90b98ef-35b4-410c-a663-bae8b7624b9f", + "nodeName" : "申请人", + "nodeRatio" : 0.000, + "coordinate" : "460,240|460,240", + "skipAnyNode" : "N", + "formCustom" : "N", + "skipList" : [ { + "nowNodeCode" : "e90b98ef-35b4-410c-a663-bae8b7624b9f", + "nextNodeCode" : "768b5b1a-6726-4d67-8853-4cc70d5b1045", + "skipType" : "PASS", + "coordinate" : "510,240;590,240" + } ] + }, { + "nodeType" : 1, + "nodeCode" : "768b5b1a-6726-4d67-8853-4cc70d5b1045", + "nodeName" : "百分之60通过", + "permissionFlag" : "${userList}", + "nodeRatio" : 60.000, + "coordinate" : "640,240|640,240", + "skipAnyNode" : "N", + "formCustom" : "N", + "skipList" : [ { + "nowNodeCode" : "768b5b1a-6726-4d67-8853-4cc70d5b1045", + "nextNodeCode" : "2f9f2e21-9bcf-42a3-a07c-13037aad22d1", + "skipType" : "PASS", + "coordinate" : "690,240;770,240" + } ] + }, { + "nodeType" : 1, + "nodeCode" : "2f9f2e21-9bcf-42a3-a07c-13037aad22d1", + "nodeName" : "全部审批通过", + "permissionFlag" : "role:1,role:3", + "nodeRatio" : 100.000, + "coordinate" : "820,240|820,240", + "skipAnyNode" : "N", + "formCustom" : "N", + "skipList" : [ { + "nowNodeCode" : "2f9f2e21-9bcf-42a3-a07c-13037aad22d1", + "nextNodeCode" : "27461e01-3d9f-4530-8fe3-bd5ec7f9571f", + "skipType" : "PASS", + "coordinate" : "870,240;950,240" + } ] + }, { + "nodeType" : 1, + "nodeCode" : "27461e01-3d9f-4530-8fe3-bd5ec7f9571f", + "nodeName" : "CEO", + "permissionFlag" : "1", + "nodeRatio" : 0.000, + "coordinate" : "1000,240|1000,240", + "skipAnyNode" : "N", + "formCustom" : "N", + "skipList" : [ { + "nowNodeCode" : "27461e01-3d9f-4530-8fe3-bd5ec7f9571f", + "nextNodeCode" : "b62b88c3-8d8d-4969-911e-2aaea219e7fc", + "skipType" : "PASS", + "coordinate" : "1050,240;1080,240;1080,240;1070,240;1070,240;1100,240" + } ] + }, { + "nodeType" : 2, + "nodeCode" : "b62b88c3-8d8d-4969-911e-2aaea219e7fc", + "nodeName" : "结束", + "nodeRatio" : 0.000, + "coordinate" : "1120,240|1120,240", + "skipAnyNode" : "N", + "formCustom" : "N" + } ] +} \ No newline at end of file diff --git a/script/bpmn/leave4.xml b/script/bpmn/leave4.xml deleted file mode 100644 index 578be560f..000000000 --- a/script/bpmn/leave4.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - e90b98ef-35b4-410c-a663-bae8b7624b9f - - - 768b5b1a-6726-4d67-8853-4cc70d5b1045 - - - 2f9f2e21-9bcf-42a3-a07c-13037aad22d1 - - - 27461e01-3d9f-4530-8fe3-bd5ec7f9571f - - - b62b88c3-8d8d-4969-911e-2aaea219e7fc - - - diff --git a/script/bpmn/leave5.json b/script/bpmn/leave5.json new file mode 100644 index 000000000..dc99494a5 --- /dev/null +++ b/script/bpmn/leave5.json @@ -0,0 +1,121 @@ +{ + "flowCode" : "leave5", + "flowName" : "请假申请-并行会签网关", + "category" : "1", + "version" : "1", + "formCustom" : "N", + "formPath" : "/workflow/leaveEdit/index", + "nodeList" : [ { + "nodeType" : 0, + "nodeCode" : "ebebaf26-9cb6-497e-8119-4c9fed4c597c", + "nodeName" : "开始", + "nodeRatio" : 0.000, + "coordinate" : "300,220|300,220", + "skipAnyNode" : "N", + "formCustom" : "N", + "skipList" : [ { + "nowNodeCode" : "ebebaf26-9cb6-497e-8119-4c9fed4c597c", + "nextNodeCode" : "e1b04e96-dc81-4858-a309-2fe945d2f374", + "skipType" : "PASS", + "coordinate" : "320,220;350,220;350,220;340,220;340,220;370,220" + } ] + }, { + "nodeType" : 1, + "nodeCode" : "e1b04e96-dc81-4858-a309-2fe945d2f374", + "nodeName" : "申请人", + "nodeRatio" : 0.000, + "coordinate" : "420,220|420,220", + "skipAnyNode" : "N", + "formCustom" : "N", + "skipList" : [ { + "nowNodeCode" : "e1b04e96-dc81-4858-a309-2fe945d2f374", + "nextNodeCode" : "3e743f4f-51ca-41d4-8e94-21f5dd9b59c9", + "skipType" : "PASS", + "coordinate" : "470,220;535,220" + } ] + }, { + "nodeType" : 4, + "nodeCode" : "3e743f4f-51ca-41d4-8e94-21f5dd9b59c9", + "nodeRatio" : 0.000, + "coordinate" : "560,220", + "skipAnyNode" : "N", + "formCustom" : "N", + "skipList" : [ { + "nowNodeCode" : "3e743f4f-51ca-41d4-8e94-21f5dd9b59c9", + "nextNodeCode" : "c80f273e-1f17-4bd8-9ad1-04a4a94ea862", + "skipType" : "PASS", + "coordinate" : "560,245;560,320;650,320" + }, { + "nowNodeCode" : "3e743f4f-51ca-41d4-8e94-21f5dd9b59c9", + "nextNodeCode" : "1e3e8d3b-18ae-4d6c-a814-ce0d724adfa4", + "skipType" : "PASS", + "coordinate" : "560,195;560,120;650,120" + } ] + }, { + "nodeType" : 1, + "nodeCode" : "c80f273e-1f17-4bd8-9ad1-04a4a94ea862", + "nodeName" : "会签", + "permissionFlag" : "role:1,role:3", + "nodeRatio" : 100.000, + "coordinate" : "700,320|700,320", + "skipAnyNode" : "N", + "formCustom" : "N", + "skipList" : [ { + "nowNodeCode" : "c80f273e-1f17-4bd8-9ad1-04a4a94ea862", + "nextNodeCode" : "1a20169e-3d82-4926-a151-e2daad28de1b", + "skipType" : "PASS", + "coordinate" : "750,320;860,320;860,245" + } ] + }, { + "nodeType" : 4, + "nodeCode" : "1a20169e-3d82-4926-a151-e2daad28de1b", + "nodeRatio" : 0.000, + "coordinate" : "860,220", + "skipAnyNode" : "N", + "formCustom" : "N", + "skipList" : [ { + "nowNodeCode" : "1a20169e-3d82-4926-a151-e2daad28de1b", + "nextNodeCode" : "7a8f0473-e409-442e-a843-5c2b813d00e9", + "skipType" : "PASS", + "coordinate" : "885,220;950,220" + } ] + }, { + "nodeType" : 1, + "nodeCode" : "7a8f0473-e409-442e-a843-5c2b813d00e9", + "nodeName" : "CEO", + "permissionFlag" : "1", + "nodeRatio" : 0.000, + "coordinate" : "1000,220|1000,220", + "skipAnyNode" : "N", + "formCustom" : "N", + "skipList" : [ { + "nowNodeCode" : "7a8f0473-e409-442e-a843-5c2b813d00e9", + "nextNodeCode" : "03c4d2bc-58b5-4408-a2e4-65afb046f169", + "skipType" : "PASS", + "coordinate" : "1050,220;1120,220" + } ] + }, { + "nodeType" : 2, + "nodeCode" : "03c4d2bc-58b5-4408-a2e4-65afb046f169", + "nodeName" : "结束", + "nodeRatio" : 0.000, + "coordinate" : "1140,220|1140,220", + "skipAnyNode" : "N", + "formCustom" : "N" + }, { + "nodeType" : 1, + "nodeCode" : "1e3e8d3b-18ae-4d6c-a814-ce0d724adfa4", + "nodeName" : "百分之60票签", + "permissionFlag" : "${userList}", + "nodeRatio" : 60.000, + "coordinate" : "700,120|700,120", + "skipAnyNode" : "N", + "formCustom" : "N", + "skipList" : [ { + "nowNodeCode" : "1e3e8d3b-18ae-4d6c-a814-ce0d724adfa4", + "nextNodeCode" : "1a20169e-3d82-4926-a151-e2daad28de1b", + "skipType" : "PASS", + "coordinate" : "750,120;860,120;860,195" + } ] + } ] +} \ No newline at end of file diff --git a/script/bpmn/leave5.xml b/script/bpmn/leave5.xml deleted file mode 100644 index a5fc2d2c2..000000000 --- a/script/bpmn/leave5.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - e1b04e96-dc81-4858-a309-2fe945d2f374 - - - 3e743f4f-51ca-41d4-8e94-21f5dd9b59c9 - - - c80f273e-1f17-4bd8-9ad1-04a4a94ea862 - 1e3e8d3b-18ae-4d6c-a814-ce0d724adfa4 - - - 1a20169e-3d82-4926-a151-e2daad28de1b - - - 7a8f0473-e409-442e-a843-5c2b813d00e9 - - - 03c4d2bc-58b5-4408-a2e4-65afb046f169 - - - - 1a20169e-3d82-4926-a151-e2daad28de1b - - From ece1dee990ecf7bc7b7b7350b8cd8b604b00a27f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Wed, 15 Jan 2025 17:41:57 +0800 Subject: [PATCH 155/175] =?UTF-8?q?update=20=E5=B0=86=E9=83=A8=E7=BD=B2?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E8=BF=81=E7=A7=BB=E5=88=B0=E6=9B=B4=E9=80=82?= =?UTF-8?q?=E5=90=88=E7=9A=84=E6=96=87=E4=BB=B6=E5=A4=B9=E4=B8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- script/{bpmn => leave}/leave1.json | 0 script/{bpmn => leave}/leave2.json | 0 script/{bpmn => leave}/leave3.json | 0 script/{bpmn => leave}/leave4.json | 0 script/{bpmn => leave}/leave5.json | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename script/{bpmn => leave}/leave1.json (100%) rename script/{bpmn => leave}/leave2.json (100%) rename script/{bpmn => leave}/leave3.json (100%) rename script/{bpmn => leave}/leave4.json (100%) rename script/{bpmn => leave}/leave5.json (100%) diff --git a/script/bpmn/leave1.json b/script/leave/leave1.json similarity index 100% rename from script/bpmn/leave1.json rename to script/leave/leave1.json diff --git a/script/bpmn/leave2.json b/script/leave/leave2.json similarity index 100% rename from script/bpmn/leave2.json rename to script/leave/leave2.json diff --git a/script/bpmn/leave3.json b/script/leave/leave3.json similarity index 100% rename from script/bpmn/leave3.json rename to script/leave/leave3.json diff --git a/script/bpmn/leave4.json b/script/leave/leave4.json similarity index 100% rename from script/bpmn/leave4.json rename to script/leave/leave4.json diff --git a/script/bpmn/leave5.json b/script/leave/leave5.json similarity index 100% rename from script/bpmn/leave5.json rename to script/leave/leave5.json From 089a79002f697198e9f4cbeb0ca85711d329eb52 Mon Sep 17 00:00:00 2001 From: AprilWind <2100166581@qq.com> Date: Wed, 15 Jan 2025 19:06:42 +0800 Subject: [PATCH 156/175] =?UTF-8?q?update=20=E5=8D=87=E7=BA=A7warm-flow?= =?UTF-8?q?=E7=9A=84sql=E8=AF=AD=E5=8F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- script/sql/oracle/oracle_ry_workflow.sql | 226 +++++++++--------- script/sql/postgres/postgres_ry_workflow.sql | 184 +++++++------- script/sql/ry_workflow.sql | 186 +++++++------- .../sql/sqlserver/sqlserver_ry_workflow.sql | 2 +- 4 files changed, 303 insertions(+), 295 deletions(-) diff --git a/script/sql/oracle/oracle_ry_workflow.sql b/script/sql/oracle/oracle_ry_workflow.sql index 6a7c5c579..a0f71d0fa 100644 --- a/script/sql/oracle/oracle_ry_workflow.sql +++ b/script/sql/oracle/oracle_ry_workflow.sql @@ -1,22 +1,21 @@ - create table FLOW_DEFINITION ( - ID NUMBER (20) not null, - FLOW_CODE VARCHAR2 (40) not null, - FLOW_NAME VARCHAR2 (100) not null, - CATEGORY VARCHAR2 (100), - VERSION VARCHAR2 (20) not null, - IS_PUBLISH NUMBER (1) default 0 not null, - FORM_CUSTOM VARCHAR2 (1) default 'N', - FORM_PATH VARCHAR2 (100), - ACTIVITY_STATUS NUMBER (1) default 1, - LISTENER_TYPE VARCHAR2 (100), - LISTENER_PATH VARCHAR2 (500), - EXT VARCHAR2 (500), - CREATE_TIME DATE, - UPDATE_TIME DATE, - DEL_FLAG VARCHAR2 (1) default '0', - TENANT_ID VARCHAR2 (40) + ID NUMBER(20) not null, + FLOW_CODE VARCHAR2(40) not null, + FLOW_NAME VARCHAR2(100) not null, + CATEGORY VARCHAR2(100), + VERSION VARCHAR2(20) not null, + IS_PUBLISH NUMBER(1) default 0 not null, + FORM_CUSTOM VARCHAR2(1) default 'N', + FORM_PATH VARCHAR2(100), + ACTIVITY_STATUS NUMBER(1) default 1, + LISTENER_TYPE VARCHAR2(100), + LISTENER_PATH VARCHAR2(500), + EXT VARCHAR2(500), + CREATE_TIME DATE, + UPDATE_TIME DATE, + DEL_FLAG VARCHAR2(1) default '0', + TENANT_ID VARCHAR2(40) ); alter table FLOW_DEFINITION add constraint PK_FLOW_DEFINITION primary key (ID); @@ -41,27 +40,27 @@ comment on column FLOW_DEFINITION.TENANT_ID is '租户id'; create table FLOW_NODE ( - ID NUMBER (20) not null, - NODE_TYPE NUMBER (1) not null, - DEFINITION_ID NUMBER (20) not null, - NODE_CODE VARCHAR2 (100) not null, - NODE_NAME VARCHAR2 (100), - NODE_RATIO NUMBER (6,3), - COORDINATE VARCHAR2 (100), - SKIP_ANY_NODE VARCHAR2 (100) default 'N', - ANY_NODE_SKIP VARCHAR2 (100), - LISTENER_TYPE VARCHAR2 (100), - LISTENER_PATH VARCHAR2 (500), - HANDLER_TYPE VARCHAR2 (100), - HANDLER_PATH VARCHAR2 (400), - FORM_CUSTOM VARCHAR2 (1) default 'N', - FORM_PATH VARCHAR2 (100), - VERSION VARCHAR2 (20), - CREATE_TIME DATE, - UPDATE_TIME DATE, - DEL_FLAG VARCHAR2 (1) default '0', - TENANT_ID VARCHAR2 (40), - PERMISSION_FLAG VARCHAR2 (200) + ID NUMBER(20) not null, + NODE_TYPE NUMBER(1) not null, + DEFINITION_ID NUMBER(20) not null, + NODE_CODE VARCHAR2(100) not null, + NODE_NAME VARCHAR2(100), + NODE_RATIO NUMBER(6, 3), + COORDINATE VARCHAR2(100), + SKIP_ANY_NODE VARCHAR2(100) default 'N', + ANY_NODE_SKIP VARCHAR2(100), + LISTENER_TYPE VARCHAR2(100), + LISTENER_PATH VARCHAR2(500), + HANDLER_TYPE VARCHAR2(100), + HANDLER_PATH VARCHAR2(400), + FORM_CUSTOM VARCHAR2(1) default 'N', + FORM_PATH VARCHAR2(100), + VERSION VARCHAR2(20), + CREATE_TIME DATE, + UPDATE_TIME DATE, + DEL_FLAG VARCHAR2(1) default '0', + TENANT_ID VARCHAR2(40), + PERMISSION_FLAG VARCHAR2(200) ); alter table FLOW_NODE add constraint PK_FLOW_NODE primary key (ID); @@ -91,20 +90,20 @@ comment on column FLOW_NODE.PERMISSION_FLAG is '权限标识(权限类型:权 create table FLOW_SKIP ( - ID NUMBER (20) not null, - DEFINITION_ID NUMBER (20) not null, - NOW_NODE_CODE VARCHAR2 (100) not null, - NOW_NODE_TYPE NUMBER (1), - NEXT_NODE_CODE VARCHAR2 (100) not null, - NEXT_NODE_TYPE NUMBER (1), - SKIP_NAME VARCHAR2 (100), - SKIP_TYPE VARCHAR2 (40), - SKIP_CONDITION VARCHAR2 (200), - COORDINATE VARCHAR2 (100), - CREATE_TIME DATE, - UPDATE_TIME DATE, - DEL_FLAG VARCHAR2 (1) default '0', - TENANT_ID VARCHAR2 (40) + ID NUMBER(20) not null, + DEFINITION_ID NUMBER(20) not null, + NOW_NODE_CODE VARCHAR2(100) not null, + NOW_NODE_TYPE NUMBER(1), + NEXT_NODE_CODE VARCHAR2(100) not null, + NEXT_NODE_TYPE NUMBER(1), + SKIP_NAME VARCHAR2(100), + SKIP_TYPE VARCHAR2(40), + SKIP_CONDITION VARCHAR2(200), + COORDINATE VARCHAR2(100), + CREATE_TIME DATE, + UPDATE_TIME DATE, + DEL_FLAG VARCHAR2(1) default '0', + TENANT_ID VARCHAR2(40) ); alter table FLOW_SKIP add constraint PK_FLOW_SKIP primary key (ID); @@ -127,21 +126,22 @@ comment on column FLOW_SKIP.TENANT_ID is '租户id'; create table FLOW_INSTANCE ( - ID NUMBER not null, - DEFINITION_ID NUMBER not null, - BUSINESS_ID VARCHAR2 (40) not null, - NODE_TYPE NUMBER (1), - NODE_CODE VARCHAR2 (100), - NODE_NAME VARCHAR2 (100), - VARIABLE CLOB, - FLOW_STATUS VARCHAR2 (20), - ACTIVITY_STATUS NUMBER (1) default 1, - CREATE_BY VARCHAR2 (64) default '', - CREATE_TIME DATE, - UPDATE_TIME DATE, - EXT VARCHAR2 (500), - DEL_FLAG VARCHAR2 (1) default '0', - TENANT_ID VARCHAR2 (40) + ID NUMBER not null, + DEFINITION_ID NUMBER not null, + BUSINESS_ID VARCHAR2(40) not null, + NODE_TYPE NUMBER(1), + NODE_CODE VARCHAR2(100), + NODE_NAME VARCHAR2(100), + VARIABLE CLOB, + FLOW_STATUS VARCHAR2(20), + ACTIVITY_STATUS NUMBER(1) default 1, + DEF_JSON CLOB, + CREATE_BY VARCHAR2(64) default '', + CREATE_TIME DATE, + UPDATE_TIME DATE, + EXT VARCHAR2(500), + DEL_FLAG VARCHAR2(1) default '0', + TENANT_ID VARCHAR2(40) ); alter table FLOW_INSTANCE add constraint PK_FLOW_INSTANCE primary key (ID); @@ -156,6 +156,7 @@ comment on column FLOW_INSTANCE.NODE_NAME is '开始节点名称'; comment on column FLOW_INSTANCE.VARIABLE is '任务变量'; comment on column FLOW_INSTANCE.FLOW_STATUS is '流程状态(0待提交 1审批中 2 审批通过 3自动通过 4终止 5作废 6撤销 7取回 8已完成 9已退回 10失效)'; comment on column FLOW_INSTANCE.ACTIVITY_STATUS is '流程激活状态(0挂起 1激活)'; +comment on column FLOW_INSTANCE.DEF_JSON is '流程定义json'; comment on column FLOW_INSTANCE.CREATE_BY is '创建者'; comment on column FLOW_INSTANCE.CREATE_TIME is '创建时间'; comment on column FLOW_INSTANCE.UPDATE_TIME is '更新时间'; @@ -165,18 +166,18 @@ comment on column FLOW_INSTANCE.TENANT_ID is '租户id'; create table FLOW_TASK ( - ID NUMBER (20) not null, - DEFINITION_ID NUMBER (20) not null, - INSTANCE_ID NUMBER (20) not null, - NODE_CODE VARCHAR2 (100), - NODE_NAME VARCHAR2 (100), - NODE_TYPE NUMBER (1), - FORM_CUSTOM VARCHAR2 (1) default 'N', - FORM_PATH VARCHAR2 (100), - CREATE_TIME DATE, - UPDATE_TIME DATE, - DEL_FLAG VARCHAR2 (1) default '0', - TENANT_ID VARCHAR2 (40) + ID NUMBER(20) not null, + DEFINITION_ID NUMBER(20) not null, + INSTANCE_ID NUMBER(20) not null, + NODE_CODE VARCHAR2(100), + NODE_NAME VARCHAR2(100), + NODE_TYPE NUMBER(1), + FORM_CUSTOM VARCHAR2(1) default 'N', + FORM_PATH VARCHAR2(100), + CREATE_TIME DATE, + UPDATE_TIME DATE, + DEL_FLAG VARCHAR2(1) default '0', + TENANT_ID VARCHAR2(40) ); alter table FLOW_TASK add constraint PK_FLOW_TASK primary key (ID); @@ -197,28 +198,30 @@ comment on column FLOW_TASK.TENANT_ID is '租户id'; create table FLOW_HIS_TASK ( - ID NUMBER (20) not null, - DEFINITION_ID NUMBER (20) not null, - INSTANCE_ID NUMBER (20) not null, - TASK_ID NUMBER (20) not null, - NODE_CODE VARCHAR2 (100), - NODE_NAME VARCHAR2 (100), - NODE_TYPE NUMBER (1), - TARGET_NODE_CODE VARCHAR2 (100), - TARGET_NODE_NAME VARCHAR2 (100), - APPROVER VARCHAR2 (40), - COOPERATE_TYPE NUMBER (1) default 0, - COLLABORATOR VARCHAR2 (40), - SKIP_TYPE VARCHAR2 (10), - FLOW_STATUS VARCHAR2 (20), - FORM_CUSTOM VARCHAR2 (1) default 'N', - FORM_PATH VARCHAR2 (100), - MESSAGE VARCHAR2 (500), - EXT VARCHAR2 (500), - CREATE_TIME DATE, - UPDATE_TIME DATE, - DEL_FLAG VARCHAR2 (1) default '0', - TENANT_ID VARCHAR2 (40) + ID NUMBER(20) not null, + DEFINITION_ID NUMBER(20) not null, + INSTANCE_ID NUMBER(20) not null, + TASK_ID NUMBER(20) not null, + NODE_CODE VARCHAR2(100), + NODE_NAME VARCHAR2(100), + NODE_TYPE NUMBER(1), + TARGET_NODE_CODE VARCHAR2(200), + TARGET_NODE_NAME VARCHAR2(200), + APPROVER VARCHAR2(40), + COOPERATE_TYPE NUMBER(1) default 0, + COLLABORATOR VARCHAR2(40), + SKIP_TYPE VARCHAR2(10), + FLOW_STATUS VARCHAR2(20), + FORM_CUSTOM VARCHAR2(1) default 'N', + FORM_PATH VARCHAR2(100), + MESSAGE VARCHAR2(500), + VARIABLE CLOB, + EXT VARCHAR2(500), + CREATE_TIME DATE, + UPDATE_TIME DATE, + DEL_FLAG VARCHAR2(1) default '0', + TENANT_ID VARCHAR2(40) + ); alter table FLOW_HIS_TASK add constraint PK_FLOW_HIS_TASK primary key (ID); @@ -238,6 +241,7 @@ comment on column FLOW_HIS_TASK.FLOW_STATUS is '流程状态(1审批中 2 审 comment on column FLOW_HIS_TASK.FORM_CUSTOM is '审批表单是否自定义 (Y是 N否)'; comment on column FLOW_HIS_TASK.FORM_PATH is '审批表单路径'; comment on column FLOW_HIS_TASK.MESSAGE is '审批意见'; +comment on column FLOW_HIS_TASK.VARIABLE is '任务变量'; comment on column FLOW_HIS_TASK.EXT is '扩展字段,预留给业务系统使用'; comment on column FLOW_HIS_TASK.CREATE_TIME is '任务开始时间'; comment on column FLOW_HIS_TASK.UPDATE_TIME is '审批完成时间'; @@ -249,15 +253,15 @@ comment on column FLOW_HIS_TASK.COLLABORATOR is '协作人'; create table FLOW_USER ( - ID NUMBER (20) not null, - TYPE VARCHAR2 (1) not null, - PROCESSED_BY VARCHAR2 (80), - ASSOCIATED NUMBER (20) not null, - CREATE_TIME DATE, - CREATE_BY VARCHAR2 (80), - UPDATE_TIME DATE, - DEL_FLAG VARCHAR2 (1) default '0', - TENANT_ID VARCHAR2 (40) + ID NUMBER(20) not null, + TYPE VARCHAR2(1) not null, + PROCESSED_BY VARCHAR2(80), + ASSOCIATED NUMBER(20) not null, + CREATE_TIME DATE, + CREATE_BY VARCHAR2(80), + UPDATE_TIME DATE, + DEL_FLAG VARCHAR2(1) default '0', + TENANT_ID VARCHAR2(40) ); alter table FLOW_USER add constraint PK_FLOW_USER primary key (ID); @@ -312,7 +316,7 @@ COMMENT ON COLUMN flow_category.update_time IS '更新时间'; INSERT INTO flow_category VALUES (100, '000000', 0, '0', 'OA审批', 0, '0', 103, 1, SYSDATE, NULL, NULL); INSERT INTO flow_category VALUES (101, '000000', 100, '0,100', '假勤管理', 0, '0', 103, 1, SYSDATE, NULL, NULL); -INSERT INTO flow_category VALUES (102, '000000', 100, '0,100', '人事管理', 0, '0', 103, 1, SYSDATE, NULL, NULL); +INSERT INTO flow_category VALUES (102, '000000', 100, '0,100', '人事管理', 1, '0', 103, 1, SYSDATE, NULL, NULL); INSERT INTO flow_category VALUES (103, '000000', 101, '0,100,101', '请假', 0, '0', 103, 1, SYSDATE, NULL, NULL); INSERT INTO flow_category VALUES (104, '000000', 101, '0,100,101', '出差', 1, '0', 103, 1, SYSDATE, NULL, NULL); INSERT INTO flow_category VALUES (105, '000000', 101, '0,100,101', '加班', 2, '0', 103, 1, SYSDATE, NULL, NULL); diff --git a/script/sql/postgres/postgres_ry_workflow.sql b/script/sql/postgres/postgres_ry_workflow.sql index aacd1453e..337b066a8 100644 --- a/script/sql/postgres/postgres_ry_workflow.sql +++ b/script/sql/postgres/postgres_ry_workflow.sql @@ -3,22 +3,22 @@ -- ---------------------------- CREATE TABLE flow_definition ( - id int8 NOT NULL, -- 主键id - flow_code varchar(40) NOT NULL, -- 流程编码 - flow_name varchar(100) NOT NULL, -- 流程名称 - category varchar(100) NULL, -- 流程类别 - "version" varchar(20) NOT NULL, -- 流程版本 - is_publish int2 NOT NULL DEFAULT 0, -- 是否发布(0未发布 1已发布 9失效) - form_custom bpchar(1) NULL DEFAULT 'N':: character varying, -- 审批表单是否自定义(Y是 N否) - form_path varchar(100) NULL, -- 审批表单路径 - activity_status int2 NOT NULL DEFAULT 1, -- 流程激活状态(0挂起 1激活) - listener_type varchar(100) NULL, -- 监听器类型 - listener_path varchar(400) NULL, -- 监听器路径 - ext varchar(500) NULL, -- 扩展字段,预留给业务系统使用 - create_time timestamp NULL, -- 创建时间 - update_time timestamp NULL, -- 更新时间 - del_flag bpchar(1) NULL DEFAULT '0':: character varying, -- 删除标志 - tenant_id varchar(40) NULL, -- 租户id + id int8 NOT NULL, -- 主键id + flow_code varchar(40) NOT NULL, -- 流程编码 + flow_name varchar(100) NOT NULL, -- 流程名称 + category varchar(100) NULL, -- 流程类别 + "version" varchar(20) NOT NULL, -- 流程版本 + is_publish int2 NOT NULL DEFAULT 0, -- 是否发布(0未发布 1已发布 9失效) + form_custom bpchar(1) NULL DEFAULT 'N':: character varying, -- 审批表单是否自定义(Y是 N否) + form_path varchar(100) NULL, -- 审批表单路径 + activity_status int2 NOT NULL DEFAULT 1, -- 流程激活状态(0挂起 1激活) + listener_type varchar(100) NULL, -- 监听器类型 + listener_path varchar(400) NULL, -- 监听器路径 + ext varchar(500) NULL, -- 扩展字段,预留给业务系统使用 + create_time timestamp NULL, -- 创建时间 + update_time timestamp NULL, -- 更新时间 + del_flag bpchar(1) NULL DEFAULT '0':: character varying, -- 删除标志 + tenant_id varchar(40) NULL, -- 租户id CONSTRAINT flow_definition_pkey PRIMARY KEY (id) ); COMMENT ON TABLE flow_definition IS '流程定义表'; @@ -56,12 +56,12 @@ CREATE TABLE flow_node listener_path varchar(400) NULL, -- 监听器路径 handler_type varchar(100) NULL, -- 处理器类型 handler_path varchar(400) NULL, -- 处理器路径 - form_custom bpchar(1) NULL DEFAULT 'N':: character varying, -- 审批表单是否自定义(Y是 N否) + form_custom bpchar(1) NULL DEFAULT 'N':: character varying, -- 审批表单是否自定义(Y是 N否) form_path varchar(100) NULL, -- 审批表单路径 "version" varchar(20) NOT NULL, -- 版本 create_time timestamp NULL, -- 创建时间 update_time timestamp NULL, -- 更新时间 - del_flag bpchar(1) NULL DEFAULT '0':: character varying, -- 删除标志 + del_flag bpchar(1) NULL DEFAULT '0':: character varying, -- 删除标志 tenant_id varchar(40) NULL, -- 租户id CONSTRAINT flow_node_pkey PRIMARY KEY (id) ); @@ -92,20 +92,20 @@ COMMENT ON COLUMN flow_node.tenant_id IS '租户id'; CREATE TABLE flow_skip ( - id int8 NOT NULL, -- 主键id - definition_id int8 NOT NULL, -- 流程定义id - now_node_code varchar(100) NOT NULL, -- 当前流程节点的编码 - now_node_type int2 NULL, -- 当前节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关) - next_node_code varchar(100) NOT NULL, -- 下一个流程节点的编码 - next_node_type int2 NULL, -- 下一个节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关) - skip_name varchar(100) NULL, -- 跳转名称 - skip_type varchar(40) NULL, -- 跳转类型(PASS审批通过 REJECT退回) - skip_condition varchar(200) NULL, -- 跳转条件 - coordinate varchar(100) NULL, -- 坐标 - create_time timestamp NULL, -- 创建时间 - update_time timestamp NULL, -- 更新时间 - del_flag bpchar(1) NULL DEFAULT '0':: character varying, -- 删除标志 - tenant_id varchar(40) NULL, -- 租户id + id int8 NOT NULL, -- 主键id + definition_id int8 NOT NULL, -- 流程定义id + now_node_code varchar(100) NOT NULL, -- 当前流程节点的编码 + now_node_type int2 NULL, -- 当前节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关) + next_node_code varchar(100) NOT NULL, -- 下一个流程节点的编码 + next_node_type int2 NULL, -- 下一个节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关) + skip_name varchar(100) NULL, -- 跳转名称 + skip_type varchar(40) NULL, -- 跳转类型(PASS审批通过 REJECT退回) + skip_condition varchar(200) NULL, -- 跳转条件 + coordinate varchar(100) NULL, -- 坐标 + create_time timestamp NULL, -- 创建时间 + update_time timestamp NULL, -- 更新时间 + del_flag bpchar(1) NULL DEFAULT '0':: character varying, -- 删除标志 + tenant_id varchar(40) NULL, -- 租户id CONSTRAINT flow_skip_pkey PRIMARY KEY (id) ); COMMENT ON TABLE flow_skip IS '节点跳转关联表'; @@ -127,21 +127,21 @@ COMMENT ON COLUMN flow_skip.tenant_id IS '租户id'; CREATE TABLE flow_instance ( - id int8 NOT NULL, -- 主键id - definition_id int8 NOT NULL, -- 对应flow_definition表的id - business_id varchar(40) NOT NULL, -- 业务id - node_type int2 NOT NULL, -- 节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关) - node_code varchar(40) NOT NULL, -- 流程节点编码 - node_name varchar(100) NULL, -- 流程节点名称 - variable text NULL, -- 任务变量 - flow_status varchar(20) NOT NULL, -- 流程状态(0待提交 1审批中 2 审批通过 8已完成 9已退回 10失效) - activity_status int2 NOT NULL DEFAULT 1, -- 流程激活状态(0挂起 1激活) - create_by varchar(64) NULL DEFAULT '':: character varying, -- 创建者 - create_time timestamp NULL, -- 创建时间 - update_time timestamp NULL, -- 更新时间 - ext varchar(500) NULL, -- 扩展字段,预留给业务系统使用 - del_flag bpchar(1) NULL DEFAULT '0':: character varying, -- 删除标志 - tenant_id varchar(40) NULL, -- 租户id + id int8 NOT NULL, -- 主键id + definition_id int8 NOT NULL, -- 对应flow_definition表的id + business_id varchar(40) NOT NULL, -- 业务id + node_type int2 NOT NULL, -- 节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关) + node_code varchar(40) NOT NULL, -- 流程节点编码 + node_name varchar(100) NULL, -- 流程节点名称 + variable text NULL, -- 任务变量 + flow_status varchar(20) NOT NULL, -- 流程状态(0待提交 1审批中 2 审批通过 8已完成 9已退回 10失效) + activity_status int2 NOT NULL DEFAULT 1, -- 流程激活状态(0挂起 1激活) + create_by varchar(64) NULL DEFAULT '':: character varying, -- 创建者 + create_time timestamp NULL, -- 创建时间 + update_time timestamp NULL, -- 更新时间 + ext varchar(500) NULL, -- 扩展字段,预留给业务系统使用 + del_flag bpchar(1) NULL DEFAULT '0':: character varying, -- 删除标志 + tenant_id varchar(40) NULL, -- 租户id CONSTRAINT flow_instance_pkey PRIMARY KEY (id) ); COMMENT ON TABLE flow_instance IS '流程实例表'; @@ -164,18 +164,18 @@ COMMENT ON COLUMN flow_instance.tenant_id IS '租户id'; CREATE TABLE flow_task ( - id int8 NOT NULL, -- 主键id - definition_id int8 NOT NULL, -- 对应flow_definition表的id - instance_id int8 NOT NULL, -- 对应flow_instance表的id - node_code varchar(100) NOT NULL, -- 节点编码 - node_name varchar(100) NULL, -- 节点名称 - node_type int2 NOT NULL, -- 节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关) - form_custom bpchar(1) NULL DEFAULT 'N':: character varying, -- 审批表单是否自定义(Y是 N否) - form_path varchar(100) NULL, -- 审批表单路径 - create_time timestamp NULL, -- 创建时间 - update_time timestamp NULL, -- 更新时间 - del_flag bpchar(1) NULL DEFAULT '0':: character varying, -- 删除标志 - tenant_id varchar(40) NULL, -- 租户id + id int8 NOT NULL, -- 主键id + definition_id int8 NOT NULL, -- 对应flow_definition表的id + instance_id int8 NOT NULL, -- 对应flow_instance表的id + node_code varchar(100) NOT NULL, -- 节点编码 + node_name varchar(100) NULL, -- 节点名称 + node_type int2 NOT NULL, -- 节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关) + form_custom bpchar(1) NULL DEFAULT 'N':: character varying, -- 审批表单是否自定义(Y是 N否) + form_path varchar(100) NULL, -- 审批表单路径 + create_time timestamp NULL, -- 创建时间 + update_time timestamp NULL, -- 更新时间 + del_flag bpchar(1) NULL DEFAULT '0':: character varying, -- 删除标志 + tenant_id varchar(40) NULL, -- 租户id CONSTRAINT flow_task_pkey PRIMARY KEY (id) ); COMMENT ON TABLE flow_task IS '待办任务表'; @@ -195,28 +195,29 @@ COMMENT ON COLUMN flow_task.tenant_id IS '租户id'; CREATE TABLE flow_his_task ( - id int8 NOT NULL, -- 主键id - definition_id int8 NOT NULL, -- 对应flow_definition表的id - instance_id int8 NOT NULL, -- 对应flow_instance表的id - task_id int8 NOT NULL, -- 对应flow_task表的id - node_code varchar(100) NULL, -- 开始节点编码 - node_name varchar(100) NULL, -- 开始节点名称 - node_type int2 NULL, -- 开始节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关) - target_node_code varchar(100) NULL, -- 目标节点编码 - target_node_name varchar(100) NULL, -- 结束节点名称 - approver varchar(40) NULL, -- 审批者 - cooperate_type int2 NOT NULL DEFAULT 0, -- 协作方式(1审批 2转办 3委派 4会签 5票签 6加签 7减签) - collaborator varchar(40) NULL, -- 协作人(只有转办、会签、票签、委派) - skip_type varchar(10) NULL, -- 流转类型(PASS通过 REJECT退回 NONE无动作) - flow_status varchar(20) NOT NULL, -- 流程状态(0待提交 1审批中 2 审批通过 8已完成 9已退回 10失效) - form_custom bpchar(1) NULL DEFAULT 'N':: character varying, -- 审批表单是否自定义(Y是 N否) - form_path varchar(100) NULL, -- 审批表单路径 - ext varchar(500) NULL, -- 扩展字段,预留给业务系统使用 - message varchar(500) NULL, -- 审批意见 - create_time timestamp NULL, -- 创建时间 - update_time timestamp NULL, -- 更新时间 - del_flag bpchar(1) NULL DEFAULT '0':: character varying, -- 删除标志 - tenant_id varchar(40) NULL, -- 租户id + id int8 NOT NULL, -- 主键id + definition_id int8 NOT NULL, -- 对应flow_definition表的id + instance_id int8 NOT NULL, -- 对应flow_instance表的id + task_id int8 NOT NULL, -- 对应flow_task表的id + node_code varchar(100) NULL, -- 开始节点编码 + node_name varchar(100) NULL, -- 开始节点名称 + node_type int2 NULL, -- 开始节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关) + target_node_code varchar(200) NULL, -- 目标节点编码 + target_node_name varchar(200) NULL, -- 结束节点名称 + approver varchar(40) NULL, -- 审批者 + cooperate_type int2 NOT NULL DEFAULT 0, -- 协作方式(1审批 2转办 3委派 4会签 5票签 6加签 7减签) + collaborator varchar(40) NULL, -- 协作人(只有转办、会签、票签、委派) + skip_type varchar(10) NULL, -- 流转类型(PASS通过 REJECT退回 NONE无动作) + flow_status varchar(20) NOT NULL, -- 流程状态(0待提交 1审批中 2 审批通过 8已完成 9已退回 10失效) + form_custom bpchar(1) NULL DEFAULT 'N':: character varying, -- 审批表单是否自定义(Y是 N否) + form_path varchar(100) NULL, -- 审批表单路径 + ext varchar(500) NULL, -- 扩展字段,预留给业务系统使用 + message varchar(500) NULL, -- 审批意见 + variable text NULL, -- 任务变量 + create_time timestamp NULL, -- 创建时间 + update_time timestamp NULL, -- 更新时间 + del_flag bpchar(1) NULL DEFAULT '0':: character varying, -- 删除标志 + tenant_id varchar(40) NULL, -- 租户id CONSTRAINT flow_his_task_pkey PRIMARY KEY (id) ); COMMENT ON TABLE flow_his_task IS '历史任务记录表'; @@ -238,6 +239,7 @@ COMMENT ON COLUMN flow_his_task.flow_status IS '流程状态(1审批中 2 审 COMMENT ON COLUMN flow_his_task.form_custom IS '审批表单是否自定义(Y是 N否)'; COMMENT ON COLUMN flow_his_task.form_path IS '审批表单路径'; COMMENT ON COLUMN flow_his_task.message IS '审批意见'; +COMMENT ON COLUMN flow_his_task.variable IS '任务变量'; COMMENT ON COLUMN flow_his_task.ext IS '扩展字段,预留给业务系统使用'; COMMENT ON COLUMN flow_his_task.create_time IS '任务开始时间'; COMMENT ON COLUMN flow_his_task.update_time IS '审批完成时间'; @@ -246,15 +248,15 @@ COMMENT ON COLUMN flow_his_task.tenant_id IS '租户id'; CREATE TABLE flow_user ( - id int8 NOT NULL, -- 主键id - "type" bpchar(1) NOT NULL, -- 人员类型(1待办任务的审批人权限 2待办任务的转办人权限 3流程实例的抄送人权限 4待办任务的委托人权限) - processed_by varchar(80) NULL, -- 权限人 - associated int8 NOT NULL, -- 任务表id - create_time timestamp NULL, -- 创建时间 - create_by varchar(80) NULL, -- 创建人 - update_time timestamp NULL, -- 更新时间 - del_flag bpchar(1) NULL DEFAULT '0':: character varying, -- 删除标志 - tenant_id varchar(40) NULL, -- 租户id + id int8 NOT NULL, -- 主键id + "type" bpchar(1) NOT NULL, -- 人员类型(1待办任务的审批人权限 2待办任务的转办人权限 3流程实例的抄送人权限 4待办任务的委托人权限) + processed_by varchar(80) NULL, -- 权限人 + associated int8 NOT NULL, -- 任务表id + create_time timestamp NULL, -- 创建时间 + create_by varchar(80) NULL, -- 创建人 + update_time timestamp NULL, -- 更新时间 + del_flag bpchar(1) NULL DEFAULT '0':: character varying, -- 删除标志 + tenant_id varchar(40) NULL, -- 租户id CONSTRAINT flow_user_pk PRIMARY KEY (id) ); CREATE INDEX user_processed_type ON flow_user USING btree (processed_by, type); @@ -306,7 +308,7 @@ COMMENT ON COLUMN flow_category.update_time IS '更新时间'; INSERT INTO flow_category VALUES (100, '000000', 0, '0', 'OA审批', 0, '0', 103, 1, now(), NULL, NULL); INSERT INTO flow_category VALUES (101, '000000', 100, '0,100', '假勤管理', 0, '0', 103, 1, now(), NULL, NULL); -INSERT INTO flow_category VALUES (102, '000000', 100, '0,100', '人事管理', 0, '0', 103, 1, now(), NULL, NULL); +INSERT INTO flow_category VALUES (102, '000000', 100, '0,100', '人事管理', 1, '0', 103, 1, now(), NULL, NULL); INSERT INTO flow_category VALUES (103, '000000', 101, '0,100,101', '请假', 0, '0', 103, 1, now(), NULL, NULL); INSERT INTO flow_category VALUES (104, '000000', 101, '0,100,101', '出差', 1, '0', 103, 1, now(), NULL, NULL); INSERT INTO flow_category VALUES (105, '000000', 101, '0,100,101', '加班', 2, '0', 103, 1, now(), NULL, NULL); diff --git a/script/sql/ry_workflow.sql b/script/sql/ry_workflow.sql index 7b82ef6b2..c5adb64ed 100644 --- a/script/sql/ry_workflow.sql +++ b/script/sql/ry_workflow.sql @@ -3,106 +3,107 @@ -- ---------------------------- CREATE TABLE `flow_definition` ( - `id` bigint unsigned NOT NULL COMMENT '主键id', - `flow_code` varchar(40) NOT NULL COMMENT '流程编码', - `flow_name` varchar(100) NOT NULL COMMENT '流程名称', - `category` varchar(100) DEFAULT NULL COMMENT '流程类别', - `version` varchar(20) NOT NULL COMMENT '流程版本', - `is_publish` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否发布(0未发布 1已发布 9失效)', - `form_custom` char(1) DEFAULT 'N' COMMENT '审批表单是否自定义(Y是 N否)', - `form_path` varchar(100) DEFAULT NULL COMMENT '审批表单路径', - `activity_status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '流程激活状态(0挂起 1激活)', - `listener_type` varchar(100) DEFAULT NULL COMMENT '监听器类型', - `listener_path` varchar(400) DEFAULT NULL COMMENT '监听器路径', - `ext` varchar(500) DEFAULT NULL COMMENT '业务详情 存业务表对象json字符串', - `create_time` datetime DEFAULT NULL COMMENT '创建时间', - `update_time` datetime DEFAULT NULL COMMENT '更新时间', - `del_flag` char(1) DEFAULT '0' COMMENT '删除标志', - `tenant_id` varchar(40) DEFAULT NULL COMMENT '租户id', + `id` bigint unsigned NOT NULL COMMENT '主键id', + `flow_code` varchar(40) NOT NULL COMMENT '流程编码', + `flow_name` varchar(100) NOT NULL COMMENT '流程名称', + `category` varchar(100) DEFAULT NULL COMMENT '流程类别', + `version` varchar(20) NOT NULL COMMENT '流程版本', + `is_publish` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否发布(0未发布 1已发布 9失效)', + `form_custom` char(1) DEFAULT 'N' COMMENT '审批表单是否自定义(Y是 N否)', + `form_path` varchar(100) DEFAULT NULL COMMENT '审批表单路径', + `activity_status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '流程激活状态(0挂起 1激活)', + `listener_type` varchar(100) DEFAULT NULL COMMENT '监听器类型', + `listener_path` varchar(400) DEFAULT NULL COMMENT '监听器路径', + `ext` varchar(500) DEFAULT NULL COMMENT '业务详情 存业务表对象json字符串', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + `del_flag` char(1) DEFAULT '0' COMMENT '删除标志', + `tenant_id` varchar(40) DEFAULT NULL COMMENT '租户id', PRIMARY KEY (`id`) USING BTREE -) ENGINE=InnoDB COMMENT='流程定义表'; +) ENGINE = InnoDB COMMENT ='流程定义表'; CREATE TABLE `flow_node` ( `id` bigint unsigned NOT NULL COMMENT '主键id', - `node_type` tinyint(1) NOT NULL COMMENT '节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)', - `definition_id` bigint NOT NULL COMMENT '流程定义id', - `node_code` varchar(100) NOT NULL COMMENT '流程节点编码', - `node_name` varchar(100) DEFAULT NULL COMMENT '流程节点名称', - `permission_flag` varchar(200) DEFAULT NULL COMMENT '权限标识(权限类型:权限标识,可以多个,用逗号隔开)', - `node_ratio` DECIMAL(6,3) DEFAULT NULL COMMENT '流程签署比例值', - `coordinate` varchar(100) DEFAULT NULL COMMENT '坐标', - `skip_any_node` varchar(100) DEFAULT 'N' COMMENT '是否可以退回任意节点(Y是 N否)即将删除', - `any_node_skip` varchar(100) DEFAULT NULL COMMENT '任意结点跳转', - `listener_type` varchar(100) DEFAULT NULL COMMENT '监听器类型', - `listener_path` varchar(400) DEFAULT NULL COMMENT '监听器路径', + `node_type` tinyint(1) NOT NULL COMMENT '节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)', + `definition_id` bigint NOT NULL COMMENT '流程定义id', + `node_code` varchar(100) NOT NULL COMMENT '流程节点编码', + `node_name` varchar(100) DEFAULT NULL COMMENT '流程节点名称', + `permission_flag` varchar(200) DEFAULT NULL COMMENT '权限标识(权限类型:权限标识,可以多个,用逗号隔开)', + `node_ratio` decimal(6, 3) DEFAULT NULL COMMENT '流程签署比例值', + `coordinate` varchar(100) DEFAULT NULL COMMENT '坐标', + `skip_any_node` varchar(100) DEFAULT 'N' COMMENT '是否可以退回任意节点(Y是 N否)即将删除', + `any_node_skip` varchar(100) DEFAULT NULL COMMENT '任意结点跳转', + `listener_type` varchar(100) DEFAULT NULL COMMENT '监听器类型', + `listener_path` varchar(400) DEFAULT NULL COMMENT '监听器路径', `handler_type` varchar(100) DEFAULT NULL COMMENT '处理器类型', `handler_path` varchar(400) DEFAULT NULL COMMENT '处理器路径', - `form_custom` char(1) DEFAULT 'N' COMMENT '审批表单是否自定义(Y是 N否)', - `form_path` varchar(100) DEFAULT NULL COMMENT '审批表单路径', - `version` varchar(20) NOT NULL COMMENT '版本', - `create_time` datetime DEFAULT NULL COMMENT '创建时间', - `update_time` datetime DEFAULT NULL COMMENT '更新时间', - `del_flag` char(1) DEFAULT '0' COMMENT '删除标志', - `tenant_id` varchar(40) DEFAULT NULL COMMENT '租户id', + `form_custom` char(1) DEFAULT 'N' COMMENT '审批表单是否自定义(Y是 N否)', + `form_path` varchar(100) DEFAULT NULL COMMENT '审批表单路径', + `version` varchar(20) NOT NULL COMMENT '版本', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + `del_flag` char(1) DEFAULT '0' COMMENT '删除标志', + `tenant_id` varchar(40) DEFAULT NULL COMMENT '租户id', PRIMARY KEY (`id`) USING BTREE -) ENGINE=InnoDB COMMENT='流程节点表'; +) ENGINE = InnoDB COMMENT ='流程节点表'; CREATE TABLE `flow_skip` ( `id` bigint unsigned NOT NULL COMMENT '主键id', - `definition_id` bigint NOT NULL COMMENT '流程定义id', - `now_node_code` varchar(100) NOT NULL COMMENT '当前流程节点的编码', - `now_node_type` tinyint(1) DEFAULT NULL COMMENT '当前节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)', - `next_node_code` varchar(100) NOT NULL COMMENT '下一个流程节点的编码', - `next_node_type` tinyint(1) DEFAULT NULL COMMENT '下一个节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)', + `definition_id` bigint NOT NULL COMMENT '流程定义id', + `now_node_code` varchar(100) NOT NULL COMMENT '当前流程节点的编码', + `now_node_type` tinyint(1) DEFAULT NULL COMMENT '当前节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)', + `next_node_code` varchar(100) NOT NULL COMMENT '下一个流程节点的编码', + `next_node_type` tinyint(1) DEFAULT NULL COMMENT '下一个节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)', `skip_name` varchar(100) DEFAULT NULL COMMENT '跳转名称', `skip_type` varchar(40) DEFAULT NULL COMMENT '跳转类型(PASS审批通过 REJECT退回)', `skip_condition` varchar(200) DEFAULT NULL COMMENT '跳转条件', `coordinate` varchar(100) DEFAULT NULL COMMENT '坐标', `create_time` datetime DEFAULT NULL COMMENT '创建时间', `update_time` datetime DEFAULT NULL COMMENT '更新时间', - `del_flag` char(1) DEFAULT '0' COMMENT '删除标志', - `tenant_id` varchar(40) DEFAULT NULL COMMENT '租户id', + `del_flag` char(1) DEFAULT '0' COMMENT '删除标志', + `tenant_id` varchar(40) DEFAULT NULL COMMENT '租户id', PRIMARY KEY (`id`) USING BTREE -) ENGINE=InnoDB COMMENT='节点跳转关联表'; +) ENGINE = InnoDB COMMENT ='节点跳转关联表'; CREATE TABLE `flow_instance` ( - `id` bigint NOT NULL COMMENT '主键id', - `definition_id` bigint NOT NULL COMMENT '对应flow_definition表的id', - `business_id` varchar(40) NOT NULL COMMENT '业务id', - `node_type` tinyint(1) NOT NULL COMMENT '节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)', - `node_code` varchar(40) NOT NULL COMMENT '流程节点编码', - `node_name` varchar(100) DEFAULT NULL COMMENT '流程节点名称', - `variable` text COMMENT '任务变量', - `flow_status` varchar(20) NOT NULL COMMENT '流程状态(0待提交 1审批中 2 审批通过 3自动通过 4终止 5作废 6撤销 7取回 8已完成 9已退回 10失效)', - `activity_status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '流程激活状态(0挂起 1激活)', - `create_by` varchar(64) DEFAULT '' COMMENT '创建者', - `create_time` datetime DEFAULT NULL COMMENT '创建时间', - `update_time` datetime DEFAULT NULL COMMENT '更新时间', - `ext` varchar(500) DEFAULT NULL COMMENT '扩展字段,预留给业务系统使用', - `del_flag` char(1) DEFAULT '0' COMMENT '删除标志', - `tenant_id` varchar(40) DEFAULT NULL COMMENT '租户id', + `id` bigint NOT NULL COMMENT '主键id', + `definition_id` bigint NOT NULL COMMENT '对应flow_definition表的id', + `business_id` varchar(40) NOT NULL COMMENT '业务id', + `node_type` tinyint(1) NOT NULL COMMENT '节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)', + `node_code` varchar(40) NOT NULL COMMENT '流程节点编码', + `node_name` varchar(100) DEFAULT NULL COMMENT '流程节点名称', + `variable` text COMMENT '任务变量', + `flow_status` varchar(20) NOT NULL COMMENT '流程状态(0待提交 1审批中 2 审批通过 3自动通过 4终止 5作废 6撤销 7取回 8已完成 9已退回 10失效)', + `activity_status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '流程激活状态(0挂起 1激活)', + `def_json` text COMMENT '流程定义json', + `create_by` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + `ext` varchar(500) DEFAULT NULL COMMENT '扩展字段,预留给业务系统使用', + `del_flag` char(1) DEFAULT '0' COMMENT '删除标志', + `tenant_id` varchar(40) DEFAULT NULL COMMENT '租户id', PRIMARY KEY (`id`) USING BTREE -) ENGINE=InnoDB COMMENT='流程实例表'; +) ENGINE = InnoDB COMMENT ='流程实例表'; CREATE TABLE `flow_task` ( - `id` bigint NOT NULL COMMENT '主键id', - `definition_id` bigint NOT NULL COMMENT '对应flow_definition表的id', - `instance_id` bigint NOT NULL COMMENT '对应flow_instance表的id', - `node_code` varchar(100) NOT NULL COMMENT '节点编码', - `node_name` varchar(100) DEFAULT NULL COMMENT '节点名称', - `node_type` tinyint(1) NOT NULL COMMENT '节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)', - `form_custom` char(1) DEFAULT 'N' COMMENT '审批表单是否自定义(Y是 N否)', - `form_path` varchar(100) DEFAULT NULL COMMENT '审批表单路径', - `create_time` datetime DEFAULT NULL COMMENT '创建时间', - `update_time` datetime DEFAULT NULL COMMENT '更新时间', - `del_flag` char(1) DEFAULT '0' COMMENT '删除标志', - `tenant_id` varchar(40) DEFAULT NULL COMMENT '租户id', + `id` bigint NOT NULL COMMENT '主键id', + `definition_id` bigint NOT NULL COMMENT '对应flow_definition表的id', + `instance_id` bigint NOT NULL COMMENT '对应flow_instance表的id', + `node_code` varchar(100) NOT NULL COMMENT '节点编码', + `node_name` varchar(100) DEFAULT NULL COMMENT '节点名称', + `node_type` tinyint(1) NOT NULL COMMENT '节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)', + `form_custom` char(1) DEFAULT 'N' COMMENT '审批表单是否自定义(Y是 N否)', + `form_path` varchar(100) DEFAULT NULL COMMENT '审批表单路径', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + `del_flag` char(1) DEFAULT '0' COMMENT '删除标志', + `tenant_id` varchar(40) DEFAULT NULL COMMENT '租户id', PRIMARY KEY (`id`) USING BTREE -) ENGINE=InnoDB COMMENT='待办任务表'; +) ENGINE = InnoDB COMMENT ='待办任务表'; CREATE TABLE `flow_his_task` ( @@ -113,39 +114,40 @@ CREATE TABLE `flow_his_task` `node_code` varchar(100) DEFAULT NULL COMMENT '开始节点编码', `node_name` varchar(100) DEFAULT NULL COMMENT '开始节点名称', `node_type` tinyint(1) DEFAULT NULL COMMENT '开始节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关)', - `target_node_code` varchar(100) DEFAULT NULL COMMENT '目标节点编码', - `target_node_name` varchar(100) DEFAULT NULL COMMENT '结束节点名称', + `target_node_code` varchar(200) DEFAULT NULL COMMENT '目标节点编码', + `target_node_name` varchar(200) DEFAULT NULL COMMENT '结束节点名称', `approver` varchar(40) DEFAULT NULL COMMENT '审批者', `cooperate_type` tinyint(1) NOT NULL DEFAULT '0' COMMENT '协作方式(1审批 2转办 3委派 4会签 5票签 6加签 7减签)', `collaborator` varchar(40) DEFAULT NULL COMMENT '协作人', - `skip_type` varchar(10) NOT NULL COMMENT '流转类型(PASS通过 REJECT退回 NONE无动作)', - `flow_status` varchar(20) NOT NULL COMMENT '流程状态(1审批中 2 审批通过 9已退回 10失效)', - `form_custom` char(1) DEFAULT 'N' COMMENT '审批表单是否自定义(Y是 N否)', - `form_path` varchar(100) DEFAULT NULL COMMENT '审批表单路径', + `skip_type` varchar(10) NOT NULL COMMENT '流转类型(PASS通过 REJECT退回 NONE无动作)', + `flow_status` varchar(20) NOT NULL COMMENT '流程状态(1审批中 2 审批通过 9已退回 10失效)', + `form_custom` char(1) DEFAULT 'N' COMMENT '审批表单是否自定义(Y是 N否)', + `form_path` varchar(100) DEFAULT NULL COMMENT '审批表单路径', `message` varchar(500) DEFAULT NULL COMMENT '审批意见', + `variable` TEXT DEFAULT NULL COMMENT '任务变量', `ext` varchar(500) DEFAULT NULL COMMENT '业务详情 存业务表对象json字符串', `create_time` datetime DEFAULT NULL COMMENT '任务开始时间', `update_time` datetime DEFAULT NULL COMMENT '审批完成时间', `del_flag` char(1) DEFAULT '0' COMMENT '删除标志', `tenant_id` varchar(40) DEFAULT NULL COMMENT '租户id', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB COMMENT ='历史任务记录表'; +) ENGINE = InnoDB COMMENT ='历史任务记录表'; CREATE TABLE `flow_user` ( - `id` bigint unsigned NOT NULL COMMENT '主键id', - `type` char(1) NOT NULL COMMENT '人员类型(1待办任务的审批人权限 2待办任务的转办人权限 3待办任务的委托人权限)', - `processed_by` varchar(80) DEFAULT NULL COMMENT '权限人', - `associated` bigint NOT NULL COMMENT '任务表id', - `create_time` datetime DEFAULT NULL COMMENT '创建时间', - `create_by` varchar(80) DEFAULT NULL COMMENT '创建人', - `update_time` datetime DEFAULT NULL COMMENT '更新时间', - `del_flag` char(1) DEFAULT '0' COMMENT '删除标志', - `tenant_id` varchar(40) DEFAULT NULL COMMENT '租户id', + `id` bigint unsigned NOT NULL COMMENT '主键id', + `type` char(1) NOT NULL COMMENT '人员类型(1待办任务的审批人权限 2待办任务的转办人权限 3待办任务的委托人权限)', + `processed_by` varchar(80) DEFAULT NULL COMMENT '权限人', + `associated` bigint NOT NULL COMMENT '任务表id', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `create_by` varchar(80) DEFAULT NULL COMMENT '创建人', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + `del_flag` char(1) DEFAULT '0' COMMENT '删除标志', + `tenant_id` varchar(40) DEFAULT NULL COMMENT '租户id', PRIMARY KEY (`id`) USING BTREE, - KEY `user_processed_type` (`processed_by`,`type`) -) ENGINE=InnoDB COMMENT='流程用户表'; + KEY `user_processed_type` (`processed_by`, `type`) +) ENGINE = InnoDB COMMENT ='流程用户表'; -- ---------------------------- -- 流程分类表 @@ -169,7 +171,7 @@ create table flow_category INSERT INTO flow_category values (100, '000000', 0, '0', 'OA审批', 0, '0', 103, 1, sysdate(), null, null); INSERT INTO flow_category values (101, '000000', 100, '0,100', '假勤管理', 0, '0', 103, 1, sysdate(), null, null); -INSERT INTO flow_category values (102, '000000', 100, '0,100', '人事管理', 0, '0', 103, 1, sysdate(), null, null); +INSERT INTO flow_category values (102, '000000', 100, '0,100', '人事管理', 1, '0', 103, 1, sysdate(), null, null); INSERT INTO flow_category values (103, '000000', 101, '0,100,101', '请假', 0, '0', 103, 1, sysdate(), null, null); INSERT INTO flow_category values (104, '000000', 101, '0,100,101', '出差', 1, '0', 103, 1, sysdate(), null, null); INSERT INTO flow_category values (105, '000000', 101, '0,100,101', '加班', 2, '0', 103, 1, sysdate(), null, null); diff --git a/script/sql/sqlserver/sqlserver_ry_workflow.sql b/script/sql/sqlserver/sqlserver_ry_workflow.sql index dc5c6b210..2ccb6faec 100644 --- a/script/sql/sqlserver/sqlserver_ry_workflow.sql +++ b/script/sql/sqlserver/sqlserver_ry_workflow.sql @@ -1086,7 +1086,7 @@ INSERT flow_category VALUES (100, N'000000', 0, N'0', N'OA审批', 0, N'0', 103, GO INSERT flow_category VALUES (101, N'000000', 100, N'0,100', N'假勤管理', 0, N'0', 103, 1, getdate(), NULL, NULL); GO -INSERT flow_category VALUES (102, N'000000', 100, N'0,100', N'人事管理', 0, N'0', 103, 1, getdate(), NULL, NULL); +INSERT flow_category VALUES (102, N'000000', 100, N'0,100', N'人事管理', 1, N'0', 103, 1, getdate(), NULL, NULL); GO INSERT flow_category VALUES (103, N'000000', 101, N'0,100,101', N'请假', 0, N'0', 103, 1, getdate(), NULL, NULL); GO From 8f21e9e2fde6f1e5acc5355f3a9a4c8dbfbeba47 Mon Sep 17 00:00:00 2001 From: AprilWind <2100166581@qq.com> Date: Wed, 15 Jan 2025 20:46:11 +0800 Subject: [PATCH 157/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E4=BB=A5=E5=8F=8A=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dromara/common/core/constant/Constants.java | 2 +- .../common/core/constant/SystemConstants.java | 7 ++++++- .../java/org/dromara/system/domain/SysClient.java | 2 +- .../java/org/dromara/system/domain/SysDept.java | 2 +- .../java/org/dromara/system/domain/SysRole.java | 2 +- .../java/org/dromara/system/domain/SysTenant.java | 2 +- .../dromara/system/domain/SysTenantPackage.java | 8 +++++++- .../java/org/dromara/system/domain/SysUser.java | 2 +- .../org/dromara/workflow/domain/FlowCategory.java | 2 +- script/sql/oracle/oracle_ry_vue_5.X.sql | 14 +++++++------- script/sql/oracle/oracle_ry_workflow.sql | 2 +- script/sql/postgres/postgres_ry_vue_5.X.sql | 14 +++++++------- script/sql/postgres/postgres_ry_workflow.sql | 2 +- script/sql/ry_vue_5.X.sql | 14 +++++++------- script/sql/ry_workflow.sql | 2 +- script/sql/sqlserver/sqlserver_ry_vue_5.X.sql | 14 +++++++------- script/sql/sqlserver/sqlserver_ry_workflow.sql | 2 +- script/sql/update/oracle/update_5.0-5.1.sql | 4 ++-- script/sql/update/postgres/update_5.0-5.1.sql | 4 ++-- script/sql/update/sqlserver/update_5.0-5.1.sql | 4 ++-- script/sql/update/update_5.0-5.1.sql | 4 ++-- 21 files changed, 60 insertions(+), 49 deletions(-) diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/Constants.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/Constants.java index d031921bd..273c7344a 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/Constants.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/Constants.java @@ -68,7 +68,7 @@ public interface Constants { Integer CAPTCHA_EXPIRATION = 2; /** - * 顶级部门id + * 顶级父级id */ Long TOP_PARENT_ID = 0L; diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/SystemConstants.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/SystemConstants.java index 79afb951f..55240bbf8 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 @@ -1,7 +1,7 @@ package org.dromara.common.core.constant; /** - * 用户常量信息 + * 系统常量信息 * * @author Lion Li */ @@ -22,6 +22,11 @@ public interface SystemConstants { */ String YES = "Y"; + /** + * 是否为系统默认(否) + */ + String NO = "N"; + /** * 是否菜单外链(是) */ diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysClient.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysClient.java index 0f681be08..ee2475d08 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysClient.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysClient.java @@ -68,7 +68,7 @@ public class SysClient extends BaseEntity { private String status; /** - * 删除标志(0代表存在 2代表删除) + * 删除标志(0代表存在 1代表删除) */ @TableLogic private String delFlag; diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysDept.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysDept.java index 48ca6821b..b94fd8a31 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysDept.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysDept.java @@ -70,7 +70,7 @@ public class SysDept extends TenantEntity { private String status; /** - * 删除标志(0代表存在 2代表删除) + * 删除标志(0代表存在 1代表删除) */ @TableLogic private String delFlag; diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysRole.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysRole.java index 2b4246404..a7c0ad5a0 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysRole.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysRole.java @@ -62,7 +62,7 @@ public class SysRole extends TenantEntity { private String status; /** - * 删除标志(0代表存在 2代表删除) + * 删除标志(0代表存在 1代表删除) */ @TableLogic private String delFlag; diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysTenant.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysTenant.java index a564a40c5..9800c3075 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysTenant.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysTenant.java @@ -95,7 +95,7 @@ public class SysTenant extends BaseEntity { private String status; /** - * 删除标志(0代表存在 2代表删除) + * 删除标志(0代表存在 1代表删除) */ @TableLogic private String delFlag; diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysTenantPackage.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysTenantPackage.java index f7e423f0f..5f58e3eca 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysTenantPackage.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysTenantPackage.java @@ -25,28 +25,34 @@ public class SysTenantPackage extends BaseEntity { */ @TableId(value = "package_id") private Long packageId; + /** * 套餐名称 */ private String packageName; + /** * 关联菜单id */ private String menuIds; + /** * 备注 */ private String remark; + /** * 菜单树选择项是否关联显示( 0:父子不互相关联显示 1:父子互相关联显示) */ private Boolean menuCheckStrictly; + /** * 状态(0正常 1停用) */ private String status; + /** - * 删除标志(0代表存在 2代表删除) + * 删除标志(0代表存在 1代表删除) */ @TableLogic private String delFlag; diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysUser.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysUser.java index 4e603e551..3712f805f 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysUser.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysUser.java @@ -83,7 +83,7 @@ public class SysUser extends TenantEntity { private String status; /** - * 删除标志(0代表存在 2代表删除) + * 删除标志(0代表存在 1代表删除) */ @TableLogic private String delFlag; 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 2ec297c5a..86ac1ac32 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 @@ -50,7 +50,7 @@ public class FlowCategory extends TenantEntity { private Long orderNum; /** - * 删除标志(0代表存在 2代表删除) + * 删除标志(0代表存在 1代表删除) */ @TableLogic private String delFlag; diff --git a/script/sql/oracle/oracle_ry_vue_5.X.sql b/script/sql/oracle/oracle_ry_vue_5.X.sql index 6171b8d31..2dd8198ff 100644 --- a/script/sql/oracle/oracle_ry_vue_5.X.sql +++ b/script/sql/oracle/oracle_ry_vue_5.X.sql @@ -65,7 +65,7 @@ comment on column sys_social.create_by is '创建者'; comment on column sys_social.create_time is '创建时间'; comment on column sys_social.update_by is '更新者'; comment on column sys_social.update_time is '更新时间'; -comment on column sys_social.del_flag is '删除标志(0代表存在 2代表删除)'; +comment on column sys_social.del_flag is '删除标志(0代表存在 1代表删除)'; -- ---------------------------- -- 租户表 @@ -108,7 +108,7 @@ comment on column sys_tenant.package_id is '租户套餐编号'; comment on column sys_tenant.expire_time is '过期时间'; comment on column sys_tenant.account_count is '用户数量(-1不限制)'; comment on column sys_tenant.status is '租户状态(0正常 1停用)'; -comment on column sys_tenant.del_flag is '删除标志(0代表存在 2代表删除)'; +comment on column sys_tenant.del_flag is '删除标志(0代表存在 1代表删除)'; comment on column sys_tenant.create_dept is '创建部门'; comment on column sys_tenant.create_by is '创建者'; comment on column sys_tenant.create_time is '创建时间'; @@ -148,7 +148,7 @@ comment on column sys_tenant_package.package_name is '套餐名称'; comment on column sys_tenant_package.menu_ids is '关联菜单id'; comment on column sys_tenant_package.remark is '备注'; comment on column sys_tenant_package.status is '状态(0正常 1停用)'; -comment on column sys_tenant_package.del_flag is '删除标志(0代表存在 2代表删除)'; +comment on column sys_tenant_package.del_flag is '删除标志(0代表存在 1代表删除)'; comment on column sys_tenant_package.create_dept is '创建部门'; comment on column sys_tenant_package.create_by is '创建者'; comment on column sys_tenant_package.create_time is '创建时间'; @@ -193,7 +193,7 @@ comment on column sys_dept.leader is '负责人'; comment on column sys_dept.phone is '联系电话'; comment on column sys_dept.email is '邮箱'; comment on column sys_dept.status is '部门状态(0正常 1停用)'; -comment on column sys_dept.del_flag is '删除标志(0代表存在 2代表删除)'; +comment on column sys_dept.del_flag is '删除标志(0代表存在 1代表删除)'; comment on column sys_dept.create_dept is '创建部门'; comment on column sys_dept.create_by is '创建者'; comment on column sys_dept.create_time is '创建时间'; @@ -258,7 +258,7 @@ comment on column sys_user.sex is '用户性别(0男 1女 2未知)' comment on column sys_user.avatar is '头像路径'; comment on column sys_user.password is '密码'; comment on column sys_user.status is '帐号状态(0正常 1停用)'; -comment on column sys_user.del_flag is '删除标志(0代表存在 2代表删除)'; +comment on column sys_user.del_flag is '删除标志(0代表存在 1代表删除)'; comment on column sys_user.login_ip is '最后登录IP'; comment on column sys_user.login_date is '最后登录时间'; comment on column sys_user.create_dept is '创建部门'; @@ -356,7 +356,7 @@ comment on column sys_role.data_scope is '数据范围(1:全部 comment on column sys_role.menu_check_strictly is '菜单树选择项是否关联显示'; comment on column sys_role.dept_check_strictly is '部门树选择项是否关联显示'; comment on column sys_role.status is '角色状态(0正常 1停用)'; -comment on column sys_role.del_flag is '删除标志(0代表存在 2代表删除)'; +comment on column sys_role.del_flag is '删除标志(0代表存在 1代表删除)'; comment on column sys_role.create_dept is '创建部门'; comment on column sys_role.create_by is '创建者'; comment on column sys_role.create_time is '创建时间'; @@ -1245,7 +1245,7 @@ comment on column sys_client.device_type is '设备类型'; comment on column sys_client.active_timeout is 'token活跃超时时间'; comment on column sys_client.timeout is 'token固定超时'; comment on column sys_client.status is '状态(0正常 1停用)'; -comment on column sys_client.del_flag is '删除标志(0代表存在 2代表删除)'; +comment on column sys_client.del_flag is '删除标志(0代表存在 1代表删除)'; comment on column sys_client.create_dept is '创建部门'; comment on column sys_client.create_by is '创建者'; comment on column sys_client.create_time is '创建时间'; diff --git a/script/sql/oracle/oracle_ry_workflow.sql b/script/sql/oracle/oracle_ry_workflow.sql index a0f71d0fa..b515b78ff 100644 --- a/script/sql/oracle/oracle_ry_workflow.sql +++ b/script/sql/oracle/oracle_ry_workflow.sql @@ -307,7 +307,7 @@ COMMENT ON COLUMN flow_category.parent_id IS '父流程分类id'; COMMENT ON COLUMN flow_category.ancestors IS '祖级列表'; COMMENT ON COLUMN flow_category.category_name IS '流程分类名称'; COMMENT ON COLUMN flow_category.order_num IS '显示顺序'; -COMMENT ON COLUMN flow_category.del_flag IS '删除标志(0代表存在 2代表删除)'; +COMMENT ON COLUMN flow_category.del_flag IS '删除标志(0代表存在 1代表删除)'; COMMENT ON COLUMN flow_category.create_dept IS '创建部门'; COMMENT ON COLUMN flow_category.create_by IS '创建者'; COMMENT ON COLUMN flow_category.create_time IS '创建时间'; diff --git a/script/sql/postgres/postgres_ry_vue_5.X.sql b/script/sql/postgres/postgres_ry_vue_5.X.sql index af97ac7dc..b3499e89f 100644 --- a/script/sql/postgres/postgres_ry_vue_5.X.sql +++ b/script/sql/postgres/postgres_ry_vue_5.X.sql @@ -64,7 +64,7 @@ comment on column sys_social.create_by is '创建者'; comment on column sys_social.create_time is '创建时间'; comment on column sys_social.update_by is '更新者'; comment on column sys_social.update_time is '更新时间'; -comment on column sys_social.del_flag is '删除标志(0代表存在 2代表删除)'; +comment on column sys_social.del_flag is '删除标志(0代表存在 1代表删除)'; -- ---------------------------- -- 租户表 @@ -109,7 +109,7 @@ comment on column sys_tenant.package_id is '租户套餐编号'; comment on column sys_tenant.expire_time is '过期时间'; comment on column sys_tenant.account_count is '用户数量(-1不限制)'; comment on column sys_tenant.status is '租户状态(0正常 1停用)'; -comment on column sys_tenant.del_flag is '删除标志(0代表存在 2代表删除)'; +comment on column sys_tenant.del_flag is '删除标志(0代表存在 1代表删除)'; comment on column sys_tenant.create_dept is '创建部门'; comment on column sys_tenant.create_by is '创建者'; comment on column sys_tenant.create_time is '创建时间'; @@ -151,7 +151,7 @@ comment on column sys_tenant_package.package_name is '套餐名称'; comment on column sys_tenant_package.menu_ids is '关联菜单id'; comment on column sys_tenant_package.remark is '备注'; comment on column sys_tenant_package.status is '状态(0正常 1停用)'; -comment on column sys_tenant_package.del_flag is '删除标志(0代表存在 2代表删除)'; +comment on column sys_tenant_package.del_flag is '删除标志(0代表存在 1代表删除)'; comment on column sys_tenant_package.create_dept is '创建部门'; comment on column sys_tenant_package.create_by is '创建者'; comment on column sys_tenant_package.create_time is '创建时间'; @@ -196,7 +196,7 @@ comment on column sys_dept.leader is '负责人'; comment on column sys_dept.phone is '联系电话'; comment on column sys_dept.email is '邮箱'; comment on column sys_dept.status is '部门状态(0正常 1停用)'; -comment on column sys_dept.del_flag is '删除标志(0代表存在 2代表删除)'; +comment on column sys_dept.del_flag is '删除标志(0代表存在 1代表删除)'; comment on column sys_dept.create_dept is '创建部门'; comment on column sys_dept.create_by is '创建者'; comment on column sys_dept.create_time is '创建时间'; @@ -259,7 +259,7 @@ comment on column sys_user.sex is '用户性别(0男 1女 2未知)' comment on column sys_user.avatar is '头像地址'; comment on column sys_user.password is '密码'; comment on column sys_user.status is '帐号状态(0正常 1停用)'; -comment on column sys_user.del_flag is '删除标志(0代表存在 2代表删除)'; +comment on column sys_user.del_flag is '删除标志(0代表存在 1代表删除)'; comment on column sys_user.login_ip is '最后登陆IP'; comment on column sys_user.login_date is '最后登陆时间'; comment on column sys_user.create_dept is '创建部门'; @@ -357,7 +357,7 @@ comment on column sys_role.data_scope is '数据范围(1:全部数 comment on column sys_role.menu_check_strictly is '菜单树选择项是否关联显示'; comment on column sys_role.dept_check_strictly is '部门树选择项是否关联显示'; comment on column sys_role.status is '角色状态(0正常 1停用)'; -comment on column sys_role.del_flag is '删除标志(0代表存在 2代表删除)'; +comment on column sys_role.del_flag is '删除标志(0代表存在 1代表删除)'; comment on column sys_role.create_dept is '创建部门'; comment on column sys_role.create_by is '创建者'; comment on column sys_role.create_time is '创建时间'; @@ -1244,7 +1244,7 @@ comment on column sys_client.device_type is '设备类型'; comment on column sys_client.active_timeout is 'token活跃超时时间'; comment on column sys_client.timeout is 'token固定超时'; comment on column sys_client.status is '状态(0正常 1停用)'; -comment on column sys_client.del_flag is '删除标志(0代表存在 2代表删除)'; +comment on column sys_client.del_flag is '删除标志(0代表存在 1代表删除)'; comment on column sys_client.create_dept is '创建部门'; comment on column sys_client.create_by is '创建者'; comment on column sys_client.create_time is '创建时间'; diff --git a/script/sql/postgres/postgres_ry_workflow.sql b/script/sql/postgres/postgres_ry_workflow.sql index 337b066a8..9bcf2cf17 100644 --- a/script/sql/postgres/postgres_ry_workflow.sql +++ b/script/sql/postgres/postgres_ry_workflow.sql @@ -299,7 +299,7 @@ COMMENT ON COLUMN flow_category.parent_id IS '父流程分类id'; COMMENT ON COLUMN flow_category.ancestors IS '祖级列表'; COMMENT ON COLUMN flow_category.category_name IS '流程分类名称'; COMMENT ON COLUMN flow_category.order_num IS '显示顺序'; -COMMENT ON COLUMN flow_category.del_flag IS '删除标志(0代表存在 2代表删除)'; +COMMENT ON COLUMN flow_category.del_flag IS '删除标志(0代表存在 1代表删除)'; COMMENT ON COLUMN flow_category.create_dept IS '创建部门'; COMMENT ON COLUMN flow_category.create_by IS '创建者'; COMMENT ON COLUMN flow_category.create_time IS '创建时间'; diff --git a/script/sql/ry_vue_5.X.sql b/script/sql/ry_vue_5.X.sql index d73369617..9e6244ddb 100644 --- a/script/sql/ry_vue_5.X.sql +++ b/script/sql/ry_vue_5.X.sql @@ -31,7 +31,7 @@ create table sys_social create_time datetime comment '创建时间', update_by bigint(20) comment '更新者', update_time datetime comment '更新时间', - del_flag char(1) default '0' comment '删除标志(0代表存在 2代表删除)', + del_flag char(1) default '0' comment '删除标志(0代表存在 1代表删除)', PRIMARY KEY (id) ) engine=innodb comment = '社会化关系表'; @@ -55,7 +55,7 @@ create table sys_tenant expire_time datetime comment '过期时间', account_count int default -1 comment '用户数量(-1不限制)', status char(1) default '0' comment '租户状态(0正常 1停用)', - del_flag char(1) default '0' comment '删除标志(0代表存在 2代表删除)', + del_flag char(1) default '0' comment '删除标志(0代表存在 1代表删除)', create_dept bigint(20) comment '创建部门', create_by bigint(20) comment '创建者', create_time datetime comment '创建时间', @@ -82,7 +82,7 @@ create table sys_tenant_package ( remark varchar(200) comment '备注', menu_check_strictly tinyint(1) default 1 comment '菜单树选择项是否关联显示', status char(1) default '0' comment '状态(0正常 1停用)', - del_flag char(1) default '0' comment '删除标志(0代表存在 2代表删除)', + del_flag char(1) default '0' comment '删除标志(0代表存在 1代表删除)', create_dept bigint(20) comment '创建部门', create_by bigint(20) comment '创建者', create_time datetime comment '创建时间', @@ -107,7 +107,7 @@ create table sys_dept ( phone varchar(11) default null comment '联系电话', email varchar(50) default null comment '邮箱', status char(1) default '0' comment '部门状态(0正常 1停用)', - del_flag char(1) default '0' comment '删除标志(0代表存在 2代表删除)', + del_flag char(1) default '0' comment '删除标志(0代表存在 1代表删除)', create_dept bigint(20) default null comment '创建部门', create_by bigint(20) default null comment '创建者', create_time datetime comment '创建时间', @@ -149,7 +149,7 @@ create table sys_user ( avatar bigint(20) comment '头像地址', password varchar(100) default '' comment '密码', status char(1) default '0' comment '帐号状态(0正常 1停用)', - del_flag char(1) default '0' comment '删除标志(0代表存在 2代表删除)', + del_flag char(1) default '0' comment '删除标志(0代表存在 1代表删除)', login_ip varchar(128) default '' comment '最后登录IP', login_date datetime comment '最后登录时间', create_dept bigint(20) default null comment '创建部门', @@ -212,7 +212,7 @@ create table sys_role ( menu_check_strictly tinyint(1) default 1 comment '菜单树选择项是否关联显示', dept_check_strictly tinyint(1) default 1 comment '部门树选择项是否关联显示', status char(1) not null comment '角色状态(0正常 1停用)', - del_flag char(1) default '0' comment '删除标志(0代表存在 2代表删除)', + del_flag char(1) default '0' comment '删除标志(0代表存在 1代表删除)', create_dept bigint(20) default null comment '创建部门', create_by bigint(20) default null comment '创建者', create_time datetime comment '创建时间', @@ -856,7 +856,7 @@ create table sys_client ( active_timeout int(11) default 1800 comment 'token活跃超时时间', timeout int(11) default 604800 comment 'token固定超时', status char(1) default '0' comment '状态(0正常 1停用)', - del_flag char(1) default '0' comment '删除标志(0代表存在 2代表删除)', + del_flag char(1) default '0' comment '删除标志(0代表存在 1代表删除)', create_dept bigint(20) default null comment '创建部门', create_by bigint(20) default null comment '创建者', create_time datetime default null comment '创建时间', diff --git a/script/sql/ry_workflow.sql b/script/sql/ry_workflow.sql index c5adb64ed..9455636a0 100644 --- a/script/sql/ry_workflow.sql +++ b/script/sql/ry_workflow.sql @@ -160,7 +160,7 @@ create table flow_category ancestors varchar(500) default '' comment '祖级列表', category_name varchar(30) not null comment '流程分类名称', order_num int(4) default 0 comment '显示顺序', - del_flag char(1) default '0' comment '删除标志(0代表存在 2代表删除)', + del_flag char(1) default '0' comment '删除标志(0代表存在 1代表删除)', create_dept bigint(20) null comment '创建部门', create_by bigint(20) null comment '创建者', create_time datetime null comment '创建时间', diff --git a/script/sql/sqlserver/sqlserver_ry_vue_5.X.sql b/script/sql/sqlserver/sqlserver_ry_vue_5.X.sql index bc0da269a..4607fb246 100644 --- a/script/sql/sqlserver/sqlserver_ry_vue_5.X.sql +++ b/script/sql/sqlserver/sqlserver_ry_vue_5.X.sql @@ -175,7 +175,7 @@ EXEC sys.sp_addextendedproperty 'COLUMN', N'oauth_token_secret' GO EXEC sys.sp_addextendedproperty - 'MS_Description', N'删除标志(0代表存在 2代表删除)' , + 'MS_Description', N'删除标志(0代表存在 1代表删除)' , 'SCHEMA', N'dbo', 'TABLE', N'sys_social', 'COLUMN', N'del_flag' @@ -330,7 +330,7 @@ EXEC sys.sp_addextendedproperty 'COLUMN', N'status' GO EXEC sys.sp_addextendedproperty - 'MS_Description', N'删除标志(0代表存在 2代表删除)' , + 'MS_Description', N'删除标志(0代表存在 1代表删除)' , 'SCHEMA', N'dbo', 'TABLE', N'sys_tenant', 'COLUMN', N'del_flag' @@ -427,7 +427,7 @@ EXEC sys.sp_addextendedproperty 'COLUMN', N'status' GO EXEC sys.sp_addextendedproperty - 'MS_Description', N'删除标志(0代表存在 2代表删除)' , + 'MS_Description', N'删除标志(0代表存在 1代表删除)' , 'SCHEMA', N'dbo', 'TABLE', N'sys_tenant_package', 'COLUMN', N'del_flag' @@ -1017,7 +1017,7 @@ EXEC sys.sp_addextendedproperty 'COLUMN', N'status' GO EXEC sys.sp_addextendedproperty - 'MS_Description', N'删除标志(0代表存在 2代表删除)' , + 'MS_Description', N'删除标志(0代表存在 1代表删除)' , 'SCHEMA', N'dbo', 'TABLE', N'sys_dept', 'COLUMN', N'del_flag' @@ -2342,7 +2342,7 @@ EXEC sys.sp_addextendedproperty 'COLUMN', N'status' GO EXEC sys.sp_addextendedproperty - 'MS_Description', N'删除标志(0代表存在 2代表删除)' , + 'MS_Description', N'删除标志(0代表存在 1代表删除)' , 'SCHEMA', N'dbo', 'TABLE', N'sys_role', 'COLUMN', N'del_flag' @@ -2727,7 +2727,7 @@ EXEC sys.sp_addextendedproperty 'COLUMN', N'status' GO EXEC sys.sp_addextendedproperty - 'MS_Description', N'删除标志(0代表存在 2代表删除)' , + 'MS_Description', N'删除标志(0代表存在 1代表删除)' , 'SCHEMA', N'dbo', 'TABLE', N'sys_user', 'COLUMN', N'del_flag' @@ -3206,7 +3206,7 @@ EXEC sp_addextendedproperty 'COLUMN', N'status' GO EXEC sp_addextendedproperty - 'MS_Description', N'删除标志(0代表存在 2代表删除)', + 'MS_Description', N'删除标志(0代表存在 1代表删除)', 'SCHEMA', N'dbo', 'TABLE', N'sys_client', 'COLUMN', N'del_flag' diff --git a/script/sql/sqlserver/sqlserver_ry_workflow.sql b/script/sql/sqlserver/sqlserver_ry_workflow.sql index 2ccb6faec..478dc869b 100644 --- a/script/sql/sqlserver/sqlserver_ry_workflow.sql +++ b/script/sql/sqlserver/sqlserver_ry_workflow.sql @@ -1035,7 +1035,7 @@ EXEC sp_addextendedproperty GO EXEC sp_addextendedproperty -'MS_Description', N'删除标志(0代表存在 2代表删除)', +'MS_Description', N'删除标志(0代表存在 1代表删除)', 'SCHEMA', N'dbo', 'TABLE', N'flow_category', 'COLUMN', N'del_flag' diff --git a/script/sql/update/oracle/update_5.0-5.1.sql b/script/sql/update/oracle/update_5.0-5.1.sql index 09cfae825..5341fecf9 100644 --- a/script/sql/update/oracle/update_5.0-5.1.sql +++ b/script/sql/update/oracle/update_5.0-5.1.sql @@ -71,7 +71,7 @@ comment on column sys_social.create_by is '创建者'; comment on column sys_social.create_time is '创建时间'; comment on column sys_social.update_by is '更新者'; comment on column sys_social.update_time is '更新时间'; -comment on column sys_social.del_flag is '删除标志(0代表存在 2代表删除)'; +comment on column sys_social.del_flag is '删除标志(0代表存在 1代表删除)'; -- ---------------------------- @@ -107,7 +107,7 @@ comment on column sys_client.device_type is '设备类型'; comment on column sys_client.active_timeout is 'token活跃超时时间'; comment on column sys_client.timeout is 'token固定超时'; comment on column sys_client.status is '状态(0正常 1停用)'; -comment on column sys_client.del_flag is '删除标志(0代表存在 2代表删除)'; +comment on column sys_client.del_flag is '删除标志(0代表存在 1代表删除)'; comment on column sys_client.create_dept is '创建部门'; comment on column sys_client.create_by is '创建者'; comment on column sys_client.create_time is '创建时间'; diff --git a/script/sql/update/postgres/update_5.0-5.1.sql b/script/sql/update/postgres/update_5.0-5.1.sql index f5f0a5c7a..14d7eb693 100644 --- a/script/sql/update/postgres/update_5.0-5.1.sql +++ b/script/sql/update/postgres/update_5.0-5.1.sql @@ -70,7 +70,7 @@ comment on column sys_social.create_by is '创建者'; comment on column sys_social.create_time is '创建时间'; comment on column sys_social.update_by is '更新者'; comment on column sys_social.update_time is '更新时间'; -comment on column sys_social.del_flag is '删除标志(0代表存在 2代表删除)'; +comment on column sys_social.del_flag is '删除标志(0代表存在 1代表删除)'; -- ---------------------------- @@ -106,7 +106,7 @@ comment on column sys_client.device_type is '设备类型'; comment on column sys_client.active_timeout is 'token活跃超时时间'; comment on column sys_client.timeout is 'token固定超时'; comment on column sys_client.status is '状态(0正常 1停用)'; -comment on column sys_client.del_flag is '删除标志(0代表存在 2代表删除)'; +comment on column sys_client.del_flag is '删除标志(0代表存在 1代表删除)'; comment on column sys_client.create_dept is '创建部门'; comment on column sys_client.create_by is '创建者'; comment on column sys_client.create_time is '创建时间'; diff --git a/script/sql/update/sqlserver/update_5.0-5.1.sql b/script/sql/update/sqlserver/update_5.0-5.1.sql index bde3813ac..81434a394 100644 --- a/script/sql/update/sqlserver/update_5.0-5.1.sql +++ b/script/sql/update/sqlserver/update_5.0-5.1.sql @@ -188,7 +188,7 @@ EXEC sys.sp_addextendedproperty 'COLUMN', N'oauth_token_secret' GO EXEC sys.sp_addextendedproperty - 'MS_Description', N'删除标志(0代表存在 2代表删除)' , + 'MS_Description', N'删除标志(0代表存在 1代表删除)' , 'SCHEMA', N'dbo', 'TABLE', N'sys_social', 'COLUMN', N'del_flag' @@ -304,7 +304,7 @@ EXEC sp_addextendedproperty 'COLUMN', N'status' GO EXEC sp_addextendedproperty -'MS_Description', N'删除标志(0代表存在 2代表删除)', +'MS_Description', N'删除标志(0代表存在 1代表删除)', 'SCHEMA', N'dbo', 'TABLE', N'sys_client', 'COLUMN', N'del_flag' diff --git a/script/sql/update/update_5.0-5.1.sql b/script/sql/update/update_5.0-5.1.sql index 871bda38f..4ebd71cde 100644 --- a/script/sql/update/update_5.0-5.1.sql +++ b/script/sql/update/update_5.0-5.1.sql @@ -36,7 +36,7 @@ create table sys_social create_time datetime comment '创建时间', update_by bigint(20) comment '更新者', update_time datetime comment '更新时间', - del_flag char(1) default '0' comment '删除标志(0代表存在 2代表删除)', + del_flag char(1) default '0' comment '删除标志(0代表存在 1代表删除)', PRIMARY KEY (id) ) engine=innodb comment = '社会化关系表'; @@ -55,7 +55,7 @@ create table sys_client ( active_timeout int(11) default 1800 comment 'token活跃超时时间', timeout int(11) default 604800 comment 'token固定超时', status char(1) default '0' comment '状态(0正常 1停用)', - del_flag char(1) default '0' comment '删除标志(0代表存在 2代表删除)', + del_flag char(1) default '0' comment '删除标志(0代表存在 1代表删除)', create_dept bigint(20) default null comment '创建部门', create_by bigint(20) default null comment '创建者', create_time datetime default null comment '创建时间', From 197253717689a5868d3cef3b79d67842b1987e98 Mon Sep 17 00:00:00 2001 From: AprilWind <2100166581@qq.com> Date: Wed, 15 Jan 2025 20:50:56 +0800 Subject: [PATCH 158/175] =?UTF-8?q?update=20=E5=9B=9E=E9=80=80update.sql?= =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- script/sql/update/oracle/update_5.0-5.1.sql | 4 ++-- script/sql/update/postgres/update_5.0-5.1.sql | 4 ++-- script/sql/update/sqlserver/update_5.0-5.1.sql | 4 ++-- script/sql/update/update_5.0-5.1.sql | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/script/sql/update/oracle/update_5.0-5.1.sql b/script/sql/update/oracle/update_5.0-5.1.sql index 5341fecf9..09cfae825 100644 --- a/script/sql/update/oracle/update_5.0-5.1.sql +++ b/script/sql/update/oracle/update_5.0-5.1.sql @@ -71,7 +71,7 @@ comment on column sys_social.create_by is '创建者'; comment on column sys_social.create_time is '创建时间'; comment on column sys_social.update_by is '更新者'; comment on column sys_social.update_time is '更新时间'; -comment on column sys_social.del_flag is '删除标志(0代表存在 1代表删除)'; +comment on column sys_social.del_flag is '删除标志(0代表存在 2代表删除)'; -- ---------------------------- @@ -107,7 +107,7 @@ comment on column sys_client.device_type is '设备类型'; comment on column sys_client.active_timeout is 'token活跃超时时间'; comment on column sys_client.timeout is 'token固定超时'; comment on column sys_client.status is '状态(0正常 1停用)'; -comment on column sys_client.del_flag is '删除标志(0代表存在 1代表删除)'; +comment on column sys_client.del_flag is '删除标志(0代表存在 2代表删除)'; comment on column sys_client.create_dept is '创建部门'; comment on column sys_client.create_by is '创建者'; comment on column sys_client.create_time is '创建时间'; diff --git a/script/sql/update/postgres/update_5.0-5.1.sql b/script/sql/update/postgres/update_5.0-5.1.sql index 14d7eb693..f5f0a5c7a 100644 --- a/script/sql/update/postgres/update_5.0-5.1.sql +++ b/script/sql/update/postgres/update_5.0-5.1.sql @@ -70,7 +70,7 @@ comment on column sys_social.create_by is '创建者'; comment on column sys_social.create_time is '创建时间'; comment on column sys_social.update_by is '更新者'; comment on column sys_social.update_time is '更新时间'; -comment on column sys_social.del_flag is '删除标志(0代表存在 1代表删除)'; +comment on column sys_social.del_flag is '删除标志(0代表存在 2代表删除)'; -- ---------------------------- @@ -106,7 +106,7 @@ comment on column sys_client.device_type is '设备类型'; comment on column sys_client.active_timeout is 'token活跃超时时间'; comment on column sys_client.timeout is 'token固定超时'; comment on column sys_client.status is '状态(0正常 1停用)'; -comment on column sys_client.del_flag is '删除标志(0代表存在 1代表删除)'; +comment on column sys_client.del_flag is '删除标志(0代表存在 2代表删除)'; comment on column sys_client.create_dept is '创建部门'; comment on column sys_client.create_by is '创建者'; comment on column sys_client.create_time is '创建时间'; diff --git a/script/sql/update/sqlserver/update_5.0-5.1.sql b/script/sql/update/sqlserver/update_5.0-5.1.sql index 81434a394..bde3813ac 100644 --- a/script/sql/update/sqlserver/update_5.0-5.1.sql +++ b/script/sql/update/sqlserver/update_5.0-5.1.sql @@ -188,7 +188,7 @@ EXEC sys.sp_addextendedproperty 'COLUMN', N'oauth_token_secret' GO EXEC sys.sp_addextendedproperty - 'MS_Description', N'删除标志(0代表存在 1代表删除)' , + 'MS_Description', N'删除标志(0代表存在 2代表删除)' , 'SCHEMA', N'dbo', 'TABLE', N'sys_social', 'COLUMN', N'del_flag' @@ -304,7 +304,7 @@ EXEC sp_addextendedproperty 'COLUMN', N'status' GO EXEC sp_addextendedproperty -'MS_Description', N'删除标志(0代表存在 1代表删除)', +'MS_Description', N'删除标志(0代表存在 2代表删除)', 'SCHEMA', N'dbo', 'TABLE', N'sys_client', 'COLUMN', N'del_flag' diff --git a/script/sql/update/update_5.0-5.1.sql b/script/sql/update/update_5.0-5.1.sql index 4ebd71cde..871bda38f 100644 --- a/script/sql/update/update_5.0-5.1.sql +++ b/script/sql/update/update_5.0-5.1.sql @@ -36,7 +36,7 @@ create table sys_social create_time datetime comment '创建时间', update_by bigint(20) comment '更新者', update_time datetime comment '更新时间', - del_flag char(1) default '0' comment '删除标志(0代表存在 1代表删除)', + del_flag char(1) default '0' comment '删除标志(0代表存在 2代表删除)', PRIMARY KEY (id) ) engine=innodb comment = '社会化关系表'; @@ -55,7 +55,7 @@ create table sys_client ( active_timeout int(11) default 1800 comment 'token活跃超时时间', timeout int(11) default 604800 comment 'token固定超时', status char(1) default '0' comment '状态(0正常 1停用)', - del_flag char(1) default '0' comment '删除标志(0代表存在 1代表删除)', + del_flag char(1) default '0' comment '删除标志(0代表存在 2代表删除)', create_dept bigint(20) default null comment '创建部门', create_by bigint(20) default null comment '创建者', create_time datetime default null comment '创建时间', From fe5a1f358d1e8cd200d1b76df6fecba8610209af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Thu, 16 Jan 2025 09:34:25 +0800 Subject: [PATCH 159/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E6=9B=B4?= =?UTF-8?q?=E6=AD=A3=E7=B1=BB=E5=91=BD=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/dromara/common/social/topiam/AuthTopIamRequest.java | 2 +- .../topiam/{AuthTopiamSource.java => AuthTopIamSource.java} | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/topiam/{AuthTopiamSource.java => AuthTopIamSource.java} (95%) diff --git a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/topiam/AuthTopIamRequest.java b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/topiam/AuthTopIamRequest.java index 31bb955d4..080c97a93 100644 --- a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/topiam/AuthTopIamRequest.java +++ b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/topiam/AuthTopIamRequest.java @@ -19,7 +19,7 @@ import me.zhyd.oauth.utils.UrlBuilder; import org.dromara.common.core.utils.SpringUtils; import org.dromara.common.json.utils.JsonUtils; -import static org.dromara.common.social.topiam.AuthTopiamSource.TOPIAM; +import static org.dromara.common.social.topiam.AuthTopIamSource.TOPIAM; /** * TopIAM 认证请求 diff --git a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/topiam/AuthTopiamSource.java b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/topiam/AuthTopIamSource.java similarity index 95% rename from ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/topiam/AuthTopiamSource.java rename to ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/topiam/AuthTopIamSource.java index e47d6c640..852d7f5cc 100644 --- a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/topiam/AuthTopiamSource.java +++ b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/topiam/AuthTopIamSource.java @@ -9,7 +9,7 @@ import me.zhyd.oauth.request.AuthDefaultRequest; * @author xlsea * @since 2024-01-06 */ -public enum AuthTopiamSource implements AuthSource { +public enum AuthTopIamSource implements AuthSource { /** * 测试 From 6bc2d9d4a761191d149a9902c6ea6fafd7030c85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Thu, 16 Jan 2025 10:23:55 +0800 Subject: [PATCH 160/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E5=8D=87?= =?UTF-8?q?=E7=BA=A7sqlserver=20warmflow=20sql=E8=84=9A=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sql/sqlserver/sqlserver_ry_workflow.sql | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/script/sql/sqlserver/sqlserver_ry_workflow.sql b/script/sql/sqlserver/sqlserver_ry_workflow.sql index 478dc869b..ea4b7205a 100644 --- a/script/sql/sqlserver/sqlserver_ry_workflow.sql +++ b/script/sql/sqlserver/sqlserver_ry_workflow.sql @@ -458,6 +458,7 @@ CREATE TABLE flow_instance ( variable nvarchar(max) NULL, flow_status nvarchar(20) NOT NULL, activity_status tinyint DEFAULT('1') NULL, + def_json nvarchar(max) NULL, create_by nvarchar(64) NULL, create_time datetime2(7) NULL, update_time datetime2(7) NULL, @@ -535,6 +536,13 @@ EXEC sp_addextendedproperty 'COLUMN', N'activity_status' GO +EXEC sp_addextendedproperty +'MS_Description', N'流程定义json', +'SCHEMA', N'dbo', +'TABLE', N'flow_instance', +'COLUMN', N'def_json' +GO + EXEC sp_addextendedproperty 'MS_Description', N'创建者', 'SCHEMA', N'dbo', @@ -698,8 +706,8 @@ CREATE TABLE flow_his_task ( definition_id bigint NOT NULL, instance_id bigint NOT NULL, task_id bigint NOT NULL, - node_code nvarchar(100) NULL, - node_name nvarchar(100) NULL, + node_code nvarchar(200) NULL, + node_name nvarchar(200) NULL, node_type tinyint NULL, target_node_code nvarchar(100) NULL, target_node_name nvarchar(100) NULL, @@ -711,6 +719,7 @@ CREATE TABLE flow_his_task ( form_custom nchar(1) DEFAULT('N') NULL, form_path nvarchar(100) NULL, message nvarchar(500) NULL, + variable nvarchar(max) NULL, ext nvarchar(500) NULL, create_time datetime2(7) NULL, update_time datetime2(7) NULL, @@ -842,6 +851,13 @@ EXEC sp_addextendedproperty 'COLUMN', N'message' GO +EXEC sp_addextendedproperty +'MS_Description', N'任务变量', +'SCHEMA', N'dbo', +'TABLE', N'flow_his_task', +'COLUMN', N'variable' +GO + EXEC sp_addextendedproperty 'MS_Description', N'业务详情 存业务表对象json字符串', 'SCHEMA', N'dbo', From 875c9fa77ca33b9ad864e6a865114d847515faad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Thu, 16 Jan 2025 11:00:38 +0800 Subject: [PATCH 161/175] =?UTF-8?q?fix=20=E4=BF=AE=E5=A4=8D=20=E5=8D=87?= =?UTF-8?q?=E7=BA=A7=E4=B9=8B=E5=90=8E=E9=83=A8=E7=BD=B2=E5=BC=82=E5=B8=B8?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/org/dromara/workflow/utils/WorkflowUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/utils/WorkflowUtils.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/utils/WorkflowUtils.java index 0bf8f429b..e48ffc820 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/utils/WorkflowUtils.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/utils/WorkflowUtils.java @@ -187,7 +187,7 @@ public class WorkflowUtils { 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.NONE.getKey()); + Node nextNode = NODE_SERVICE.getNextNode(definitionId, startNode.getNodeCode(), null, SkipType.PASS.getKey()); return nextNode.getNodeCode(); } From 9d8b9fabbea813e980d7f8e67ee633a55d205955 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Thu, 16 Jan 2025 11:50:19 +0800 Subject: [PATCH 162/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20ws?= =?UTF-8?q?=E6=A8=A1=E5=9D=97=E6=9B=BF=E6=8D=A2session=E7=9A=84=E6=97=B6?= =?UTF-8?q?=E5=80=99=E5=85=B3=E9=97=ADsession=E8=BF=9E=E6=8E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/websocket/holder/WebSocketSessionHolder.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/holder/WebSocketSessionHolder.java b/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/holder/WebSocketSessionHolder.java index 368801c3d..9c2372b85 100644 --- a/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/holder/WebSocketSessionHolder.java +++ b/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/holder/WebSocketSessionHolder.java @@ -2,6 +2,7 @@ package org.dromara.common.websocket.holder; import lombok.AccessLevel; import lombok.NoArgsConstructor; +import org.springframework.web.socket.CloseStatus; import org.springframework.web.socket.WebSocketSession; import java.util.Map; @@ -25,6 +26,7 @@ public class WebSocketSessionHolder { * @param session 要添加的WebSocket会话 */ public static void addSession(Long sessionKey, WebSocketSession session) { + removeSession(sessionKey); USER_SESSION_MAP.put(sessionKey, session); } @@ -34,8 +36,10 @@ public class WebSocketSessionHolder { * @param sessionKey 要移除的会话键 */ public static void removeSession(Long sessionKey) { - if (USER_SESSION_MAP.containsKey(sessionKey)) { - USER_SESSION_MAP.remove(sessionKey); + WebSocketSession session = USER_SESSION_MAP.remove(sessionKey); + try { + session.close(CloseStatus.BAD_DATA); + } catch (Exception ignored) { } } From 69b95b3e7a3a1438abb03c1c5981f6cc19c22663 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Thu, 16 Jan 2025 17:56:29 +0800 Subject: [PATCH 163/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E9=BB=98?= =?UTF-8?q?=E8=AE=A4=E6=B3=A8=E9=87=8A=E6=8E=89slave=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E6=BA=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/application-dev.yml | 16 ++++++++-------- .../src/main/resources/application-prod.yml | 16 ++++++++-------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/ruoyi-admin/src/main/resources/application-dev.yml b/ruoyi-admin/src/main/resources/application-dev.yml index 6a804a947..63b76e951 100644 --- a/ruoyi-admin/src/main/resources/application-dev.yml +++ b/ruoyi-admin/src/main/resources/application-dev.yml @@ -52,14 +52,14 @@ spring: url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true username: root password: root - # 从库数据源 - slave: - lazy: true - type: ${spring.datasource.type} - driverClassName: com.mysql.cj.jdbc.Driver - url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true - username: - password: +# # 从库数据源 +# slave: +# lazy: true +# type: ${spring.datasource.type} +# driverClassName: com.mysql.cj.jdbc.Driver +# url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true +# username: +# password: # oracle: # type: ${spring.datasource.type} # driverClassName: oracle.jdbc.OracleDriver diff --git a/ruoyi-admin/src/main/resources/application-prod.yml b/ruoyi-admin/src/main/resources/application-prod.yml index 15f2c5243..3e41f84c0 100644 --- a/ruoyi-admin/src/main/resources/application-prod.yml +++ b/ruoyi-admin/src/main/resources/application-prod.yml @@ -55,14 +55,14 @@ spring: url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true username: root password: root - # 从库数据源 - slave: - lazy: true - type: ${spring.datasource.type} - driverClassName: com.mysql.cj.jdbc.Driver - url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true - username: - password: +# # 从库数据源 +# slave: +# lazy: true +# type: ${spring.datasource.type} +# driverClassName: com.mysql.cj.jdbc.Driver +# url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true +# username: +# password: # oracle: # type: ${spring.datasource.type} # driverClassName: oracle.jdbc.OracleDriver From 79ec3fd2c9e871b1c7314d1819d450c52faaff93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Fri, 17 Jan 2025 09:29:22 +0800 Subject: [PATCH 164/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E5=8D=87?= =?UTF-8?q?=E7=BA=A7warmflow=201.6.0-m5=20=E8=A7=A3=E5=86=B3=E7=9B=91?= =?UTF-8?q?=E5=90=AC=E5=99=A8=E9=94=99=E8=AF=AF=E8=A7=A6=E5=8F=91=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 82ed3a855..1d6b01767 100644 --- a/pom.xml +++ b/pom.xml @@ -50,7 +50,7 @@ 8.7.2-20241022 - 1.6.0-m4 + 1.6.0-m5 3.2.2 From 0ae521a7dc948e3589104f8b48ad49b77ff9d066 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Fri, 17 Jan 2025 10:42:31 +0800 Subject: [PATCH 165/175] update springboot 3.3.5 => 3.4.1 update springdoc 2.7.0 => 2.8.3 update mybatis-plus 3.5.9 => 3.5.10 update hutool 5.8.31 => 5.8.35 update springboot-admin 3.3.4 => 3.4.1 update redisson 3.39.0 => 3.43.0 update mapstruct-plus 1.4.5 => 1.4.6 update lombok 1.18.34 => 1.18.36 update anyline 20241022 => 20250101 update snailjob beta1 => beta1.1 --- pom.xml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/pom.xml b/pom.xml index 1d6b01767..32ea9a496 100644 --- a/pom.xml +++ b/pom.xml @@ -14,27 +14,27 @@ 5.2.3 - 3.3.5 + 3.4.1 UTF-8 UTF-8 17 3.5.16 - 2.7.0 + 2.8.3 0.15.0 4.0.3 2.3 1.39.0 - 3.5.9 + 3.5.10 3.9.1 - 5.8.31 - 3.3.4 - 3.39.0 + 5.8.35 + 3.4.1 + 3.43.0 2.2.7 4.3.1 - 1.3.0-beta1 - 1.4.5 + 1.3.0-beta1.1 + 1.4.6 0.2.0 - 1.18.34 + 1.18.36 1.76 1.16.7 @@ -48,7 +48,7 @@ 1.2.83 - 8.7.2-20241022 + 8.7.2-20250101 1.6.0-m5 From 8c57d694c50388f792ac020ca85674aa064b2ee6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Fri, 17 Jan 2025 10:49:32 +0800 Subject: [PATCH 166/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E7=BC=96?= =?UTF-8?q?=E8=AF=91=E8=AD=A6=E5=91=8A=E9=97=AE=E9=A2=98=20=E6=9B=BF?= =?UTF-8?q?=E6=8D=A2=E8=BF=87=E6=9C=9F=E6=96=B9=E6=B3=95=E4=B8=8E=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/org/dromara/common/core/utils/DateUtils.java | 7 ++++--- .../java/org/dromara/common/core/utils/StringUtils.java | 7 ++++--- .../main/java/org/dromara/common/log/aspect/LogAspect.java | 3 +-- .../java/org/dromara/common/social/utils/SocialUtils.java | 2 +- .../web/interceptor/PlusWebInvokeTimeInterceptor.java | 2 +- 5 files changed, 11 insertions(+), 10 deletions(-) diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/DateUtils.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/DateUtils.java index 88cdbbc72..41d0f6c25 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/DateUtils.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/DateUtils.java @@ -1,7 +1,5 @@ package org.dromara.common.core.utils; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; import org.apache.commons.lang3.time.DateFormatUtils; import org.dromara.common.core.enums.FormatsType; import org.dromara.common.core.exception.ServiceException; @@ -18,13 +16,16 @@ import java.util.concurrent.TimeUnit; * * @author ruoyi */ -@NoArgsConstructor(access = AccessLevel.PRIVATE) public class DateUtils extends org.apache.commons.lang3.time.DateUtils { private static final String[] PARSE_PATTERNS = { "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM", "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM", "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"}; + @Deprecated + private DateUtils() { + } + /** * 获取当前日期和时间 * diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/StringUtils.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/StringUtils.java index 897ab920a..506bf08d5 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/StringUtils.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/StringUtils.java @@ -4,8 +4,6 @@ import cn.hutool.core.collection.CollUtil; import cn.hutool.core.convert.Convert; import cn.hutool.core.lang.Validator; import cn.hutool.core.util.StrUtil; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; import org.springframework.util.AntPathMatcher; import java.util.*; @@ -17,13 +15,16 @@ import java.util.stream.Collectors; * * @author Lion Li */ -@NoArgsConstructor(access = AccessLevel.PRIVATE) public class StringUtils extends org.apache.commons.lang3.StringUtils { public static final String SEPARATOR = ","; public static final String SLASH = "/"; + @Deprecated + private StringUtils() { + } + /** * 获取参数不为空值 * diff --git a/ruoyi-common/ruoyi-common-log/src/main/java/org/dromara/common/log/aspect/LogAspect.java b/ruoyi-common/ruoyi-common-log/src/main/java/org/dromara/common/log/aspect/LogAspect.java index 71b3790b7..8ab2719e1 100644 --- a/ruoyi-common/ruoyi-common-log/src/main/java/org/dromara/common/log/aspect/LogAspect.java +++ b/ruoyi-common/ruoyi-common-log/src/main/java/org/dromara/common/log/aspect/LogAspect.java @@ -113,13 +113,12 @@ public class LogAspect { // 设置消耗时间 StopWatch stopWatch = KEY_CACHE.get(); stopWatch.stop(); - operLog.setCostTime(stopWatch.getTime()); + operLog.setCostTime(stopWatch.getDuration().toMillis()); // 发布事件保存数据库 SpringUtils.context().publishEvent(operLog); } catch (Exception exp) { // 记录本地异常日志 log.error("异常信息:{}", exp.getMessage()); - exp.printStackTrace(); } finally { KEY_CACHE.remove(); } diff --git a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/utils/SocialUtils.java b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/utils/SocialUtils.java index 357256d52..db696e515 100644 --- a/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/utils/SocialUtils.java +++ b/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/utils/SocialUtils.java @@ -59,7 +59,7 @@ public class SocialUtils { case "microsoft" -> new AuthMicrosoftRequest(builder.build(), STATE_CACHE); case "renren" -> new AuthRenrenRequest(builder.build(), STATE_CACHE); case "stack_overflow" -> new AuthStackOverflowRequest(builder.stackOverflowKey(obj.getStackOverflowKey()).build(), STATE_CACHE); - case "huawei" -> new AuthHuaweiRequest(builder.build(), STATE_CACHE); + case "huawei" -> new AuthHuaweiV3Request(builder.build(), STATE_CACHE); case "wechat_enterprise" -> new AuthWeChatEnterpriseQrcodeRequest(builder.agentId(obj.getAgentId()).build(), STATE_CACHE); case "gitlab" -> new AuthGitlabRequest(builder.build(), STATE_CACHE); case "wechat_mp" -> new AuthWeChatMpRequest(builder.build(), STATE_CACHE); diff --git a/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/interceptor/PlusWebInvokeTimeInterceptor.java b/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/interceptor/PlusWebInvokeTimeInterceptor.java index 7cb6b7877..f25601572 100644 --- a/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/interceptor/PlusWebInvokeTimeInterceptor.java +++ b/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/interceptor/PlusWebInvokeTimeInterceptor.java @@ -67,7 +67,7 @@ public class PlusWebInvokeTimeInterceptor implements HandlerInterceptor { StopWatch stopWatch = KEY_CACHE.get(); if (ObjectUtil.isNotNull(stopWatch)) { stopWatch.stop(); - log.info("[PLUS]结束请求 => URL[{}],耗时:[{}]毫秒", request.getMethod() + " " + request.getRequestURI(), stopWatch.getTime()); + log.info("[PLUS]结束请求 => URL[{}],耗时:[{}]毫秒", request.getMethod() + " " + request.getRequestURI(), stopWatch.getDuration().toMillis()); KEY_CACHE.remove(); } } From a2714fb9f7ffb84d850d01a2f9acd1cb27c58fdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A7=8B=E8=BE=9E=E6=9C=AA=E5=AF=92?= <545073804@qq.com> Date: Fri, 17 Jan 2025 07:55:17 +0000 Subject: [PATCH 167/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20OSS?= =?UTF-8?q?=E7=A7=81=E6=9C=89=E6=A1=B6=E7=9A=84=E4=B8=B4=E6=97=B6URL?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 秋辞未寒 <545073804@qq.com> --- .../main/java/org/dromara/common/oss/core/OssClient.java | 8 ++++---- .../dromara/system/service/impl/SysOssServiceImpl.java | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) 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 1261b4777..59c599bd0 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 @@ -284,13 +284,13 @@ public class OssClient { /** * 获取私有URL链接 * - * @param objectKey 对象KEY - * @param second 授权时间 + * @param objectKey 对象KEY + * @param expiredTime 链接授权到期时间 */ - public String getPrivateUrl(String objectKey, Integer second) { + public String getPrivateUrl(String objectKey, Duration expiredTime) { // 使用 AWS S3 预签名 URL 的生成器 获取对象的预签名 URL URL url = presigner.presignGetObject( - x -> x.signatureDuration(Duration.ofSeconds(second)) + x -> x.signatureDuration(expiredTime) .getObjectRequest( y -> y.bucket(properties.getBucketName()) .key(objectKey) diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java index f58f06166..496113742 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java @@ -262,7 +262,7 @@ public class SysOssServiceImpl implements ISysOssService, OssService { OssClient storage = OssFactory.instance(oss.getService()); // 仅修改桶类型为 private 的URL,临时URL时长为120s if (AccessPolicyType.PRIVATE == storage.getAccessPolicy()) { - oss.setUrl(storage.getPrivateUrl(oss.getFileName(), 120)); + oss.setUrl(storage.getPrivateUrl(oss.getFileName(), Duration.ofSeconds(120))); } return oss; } From b38ca837d621c8f340794d737aa54b549e1fbfdf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Fri, 17 Jan 2025 15:29:51 +0800 Subject: [PATCH 168/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E7=BB=91?= =?UTF-8?q?=E5=AE=9A=E4=B8=89=E6=96=B9=E4=B8=8E=E8=A7=A3=E7=BB=91=E4=B8=89?= =?UTF-8?q?=E6=96=B9=E6=A0=A1=E9=AA=8Ctoken=E6=98=AF=E5=90=A6=E5=AD=98?= =?UTF-8?q?=E5=9C=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/dromara/web/controller/AuthController.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/ruoyi-admin/src/main/java/org/dromara/web/controller/AuthController.java b/ruoyi-admin/src/main/java/org/dromara/web/controller/AuthController.java index c1ffef3d3..7fbc57f95 100644 --- a/ruoyi-admin/src/main/java/org/dromara/web/controller/AuthController.java +++ b/ruoyi-admin/src/main/java/org/dromara/web/controller/AuthController.java @@ -2,6 +2,7 @@ package org.dromara.web.controller; import cn.dev33.satoken.annotation.SaIgnore; import cn.dev33.satoken.exception.NotLoginException; +import cn.dev33.satoken.stp.StpUtil; import cn.hutool.core.codec.Base64; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; @@ -111,7 +112,7 @@ public class AuthController { } /** - * 第三方登录请求 + * 获取跳转URL * * @param source 登录来源 * @return 结果 @@ -133,13 +134,15 @@ public class AuthController { } /** - * 第三方登录回调业务处理 绑定授权 + * 前端回调绑定授权(需要token) * * @param loginBody 请求体 * @return 结果 */ @PostMapping("/social/callback") public R socialCallback(@RequestBody SocialLoginBody loginBody) { + // 校验token + StpUtil.checkLogin(); // 获取第三方登录信息 AuthResponse response = SocialUtils.loginAuth( loginBody.getSource(), loginBody.getSocialCode(), @@ -155,12 +158,14 @@ public class AuthController { /** - * 取消授权 + * 取消授权(需要token) * * @param socialId socialId */ @DeleteMapping(value = "/unlock/{socialId}") public R unlockSocial(@PathVariable Long socialId) { + // 校验token + StpUtil.checkLogin(); Boolean rows = socialUserService.deleteWithValidById(socialId); return rows ? R.ok() : R.fail("取消授权失败"); } From ce7f5121b0adb5140631d7efae45da50d0f5b6ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Fri, 17 Jan 2025 15:30:08 +0800 Subject: [PATCH 169/175] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E6=9F=A5?= =?UTF-8?q?=E8=AF=A2oss=E5=9B=BE=E7=89=87url=E6=8E=A5=E5=8F=A3=E6=94=B9?= =?UTF-8?q?=E4=B8=BAquery=E6=A0=87=E8=AF=86=E7=AC=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/dromara/system/controller/system/SysOssController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysOssController.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysOssController.java index 73ada3b84..81200c115 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysOssController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysOssController.java @@ -53,7 +53,7 @@ public class SysOssController extends BaseController { * * @param ossIds OSS对象ID串 */ - @SaCheckPermission("system:oss:list") + @SaCheckPermission("system:oss:query") @GetMapping("/listByIds/{ossIds}") public R> listByIds(@NotEmpty(message = "主键不能为空") @PathVariable Long[] ossIds) { From a6fc47b4f6078571093c957f2ea02a30b080f4bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Fri, 17 Jan 2025 15:59:43 +0800 Subject: [PATCH 170/175] =?UTF-8?q?fix=20=E4=BF=AE=E5=A4=8D=20=E9=83=A8?= =?UTF-8?q?=E7=BD=B2=E5=B7=A5=E4=BD=9C=E6=B5=81=E7=BC=BA=E5=B0=91=E5=AD=97?= =?UTF-8?q?=E4=BD=93=E6=96=87=E4=BB=B6=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ruoyi-admin/Dockerfile | 2 ++ ruoyi-admin/zhFonts/.uuid | 1 + ruoyi-admin/zhFonts/SIMSUN.TTC | Bin 0 -> 18008680 bytes ruoyi-admin/zhFonts/fonts.dir | 4 ++++ ruoyi-admin/zhFonts/fonts.scale | 4 ++++ 5 files changed, 11 insertions(+) create mode 100644 ruoyi-admin/zhFonts/.uuid create mode 100644 ruoyi-admin/zhFonts/SIMSUN.TTC create mode 100644 ruoyi-admin/zhFonts/fonts.dir create mode 100644 ruoyi-admin/zhFonts/fonts.scale diff --git a/ruoyi-admin/Dockerfile b/ruoyi-admin/Dockerfile index e0be8aeef..b489ab57c 100644 --- a/ruoyi-admin/Dockerfile +++ b/ruoyi-admin/Dockerfile @@ -16,6 +16,8 @@ ENV SERVER_PORT=8080 LANG=C.UTF-8 LC_ALL=C.UTF-8 JAVA_OPTS="" EXPOSE ${SERVER_PORT} ADD ./target/ruoyi-admin.jar ./app.jar +# 工作流字体文件 +ADD ./zhFonts/ /usr/share/fonts/zhFonts/ SHELL ["/bin/bash", "-c"] diff --git a/ruoyi-admin/zhFonts/.uuid b/ruoyi-admin/zhFonts/.uuid new file mode 100644 index 000000000..cee5cdd7c --- /dev/null +++ b/ruoyi-admin/zhFonts/.uuid @@ -0,0 +1 @@ +3f2ee348-0303-40ca-bf03-03f48d2d2141 \ No newline at end of file diff --git a/ruoyi-admin/zhFonts/SIMSUN.TTC b/ruoyi-admin/zhFonts/SIMSUN.TTC new file mode 100644 index 0000000000000000000000000000000000000000..6ca8de3dab297b4a66a6cf57e1992148d768191a GIT binary patch literal 18008680 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

k(n<*+CMg;C|WZwB8v_vWAFJ|5v|QWpFNPM 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

kn;ISH!aHI7HdY5F9T@}3b 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¨C6 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

-+4M=ANO1Cz;Od&) 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