diff --git a/LICENSE b/LICENSE index 8564f294c..32b307112 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2018 RuoYi +Copyright (c) 2019 RuoYi-Vue-Plus Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in @@ -17,4 +17,4 @@ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md index ce17def9d..b877e68c4 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,7 @@ ## 平台简介 +[![码云Gitee](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/badge/star.svg?theme=blue)](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus) +[![License](https://img.shields.io/badge/License-MIT-blue.svg)](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/blob/master/LICENSE) +[![使用IntelliJ IDEA开发维护](https://img.shields.io/badge/IntelliJ%20IDEA-提供支持-blue.svg)](https://www.jetbrains.com/?from=RuoYi-Vue-Plus) 基于 RuoYi-Vue 集成 Mybatis-Plus Lombok Hutool 等便捷开发工具 适配重写相关业务 便于开发 定期与 RuoYi-Vue 同步 * 前端开发框架 Vue、Element UI @@ -19,7 +22,7 @@ ### 依赖改动 -* ORM框架 使用 Mybatis-Plus 3.4.2 简化CRUD (不支持主子表) +* ORM框架 使用 Mybatis-Plus 简化CRUD (不支持主子表) * Bean简化 使用 Lombok 简化 get set toString 等等 * 容器改动 Tomcat 改为 并发性能更好的 undertow * 分页移除 pagehelper 改为 Mybatis-Plus 分页 @@ -45,10 +48,11 @@ * 同步升级 RuoYi-Vue 3.5.0 * 单模块 fast 分支 [RuoYi-Vue-Plus-fast](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/tree/fast/) +* Oracle 模块 oracle 分支 [RuoYi-Vue-Plus-oracle](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/tree/oracle/) ## 关注作者(扫码请备注: "加群") -![](https://images.gitee.com/uploads/images/2021/0508/235345_5503356a_1766278.jpeg) +![作者图片](https://images.gitee.com/uploads/images/2021/0508/235345_5503356a_1766278.jpeg) ## 捐献作者 作者为兼职做开源,平时还需要工作,如果帮到了您可以请作者吃个盒饭 diff --git a/pom.xml b/pom.xml index a17897433..f50e460e5 100644 --- a/pom.xml +++ b/pom.xml @@ -13,7 +13,7 @@ RuoYi-Vue-Plus后台管理系统 - 2.3.0 + 2.3.1 2.3.11.RELEASE UTF-8 UTF-8 diff --git a/ruoyi-admin/src/main/resources/application-dev.yml b/ruoyi-admin/src/main/resources/application-dev.yml index 9a8cbe631..4712f27e2 100644 --- a/ruoyi-admin/src/main/resources/application-dev.yml +++ b/ruoyi-admin/src/main/resources/application-dev.yml @@ -80,7 +80,7 @@ redisson: # 单节点配置 singleServerConfig: # 客户端名称 - clientName: ${ruoyi-vue-plus.name} + clientName: ${ruoyi.name} # 最小空闲连接数 connectionMinimumIdleSize: 32 # 连接池大小 diff --git a/ruoyi-admin/src/main/resources/application-prod.yml b/ruoyi-admin/src/main/resources/application-prod.yml index eba8a8981..2ebdcbdc6 100644 --- a/ruoyi-admin/src/main/resources/application-prod.yml +++ b/ruoyi-admin/src/main/resources/application-prod.yml @@ -81,7 +81,7 @@ redisson: # 单节点配置 singleServerConfig: # 客户端名称 - clientName: ${ruoyi-vue-plus.name} + clientName: ${ruoyi.name} # 最小空闲连接数 connectionMinimumIdleSize: 32 # 连接池大小 diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml index 0c18ecca3..9dc13c220 100644 --- a/ruoyi-admin/src/main/resources/application.yml +++ b/ruoyi-admin/src/main/resources/application.yml @@ -8,8 +8,8 @@ ruoyi: copyrightYear: 2021 # 实例演示开关 demoEnabled: true - # 文件路径,使用jvm系统变量,兼容windows和linux; - profile: ${user.dir}/ruoyi/uploadPath + # 文件路径 + profile: ./ruoyi/uploadPath # 获取ip地址开关 addressEnabled: false diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RedisLock.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RedisLock.java new file mode 100644 index 000000000..7b3c912f1 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RedisLock.java @@ -0,0 +1,27 @@ +package com.ruoyi.common.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 分布式锁(注解模式,不推荐使用,最好用锁的工具类) + * + * @author shenxinquan + */ + +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface RedisLock { + + /** + * 锁过期时间 默认30秒 + */ + int expireTime() default 30; + + /** + * 锁key值 + */ + String key() default "redisLockKey"; +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java index 534291991..137969a8b 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java @@ -2,7 +2,7 @@ package com.ruoyi.common.constant; /** * 通用常量信息 - * + * * @author ruoyi */ public class Constants @@ -126,4 +126,9 @@ public class Constants * 资源映射路径 前缀 */ public static final String RESOURCE_PREFIX = "/profile"; + + /** + * 资源映射路径 前缀 + */ + public static final String REDIS_LOCK_KEY = "redis_lock:"; } diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/redis/RedisCache.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/redis/RedisCache.java index 6c4c2393e..3c8bc9233 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/core/redis/RedisCache.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/redis/RedisCache.java @@ -96,8 +96,12 @@ public class RedisCache { * @param collection 多个对象 * @return */ - public long deleteObject(final Collection collection) { - return redissonClient.getKeys().delete(Arrays.toString(collection.toArray())); + public void deleteObject(final Collection collection) { + RBatch batch = redissonClient.createBatch(); + collection.forEach(t->{ + batch.getBucket(t.toString()).deleteAsync(); + }); + batch.execute(); } /** diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/PageUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/PageUtils.java index cf3f886d7..d5b72f77c 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/PageUtils.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/PageUtils.java @@ -43,9 +43,9 @@ public class PageUtils { public static final int DEFAULT_PAGE_NUM = 1; /** - * 每页显示记录数 默认值 + * 每页显示记录数 默认值 默认查全部 */ - public static final int DEFAULT_PAGE_SIZE = 10; + public static final int DEFAULT_PAGE_SIZE = Integer.MAX_VALUE; /** * 构建 plus 分页对象 diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java index cb4a225fb..22d53c7fa 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java @@ -1,5 +1,6 @@ package com.ruoyi.common.utils.file; +import cn.hutool.core.io.FileUtil; import cn.hutool.core.lang.Validator; import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.StrUtil; @@ -113,7 +114,8 @@ public class FileUploadUtils String fileName = extractFilename(file); File desc = getAbsoluteFile(baseDir, fileName); - file.transferTo(desc); + desc = FileUtil.touch(desc); + FileUtil.writeFromStream(file.getInputStream(), desc); String pathFileName = getPathFileName(baseDir, fileName); return pathFileName; } diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/ImageUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/ImageUtils.java index d918a48b5..94dcf456f 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/ImageUtils.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/ImageUtils.java @@ -95,6 +95,7 @@ public class ImageUtils } finally { + IOUtils.closeQuietly(in); IOUtils.closeQuietly(baos); } } diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/RedisLockController.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/RedisLockController.java new file mode 100644 index 000000000..7792784a1 --- /dev/null +++ b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/RedisLockController.java @@ -0,0 +1,35 @@ +package com.ruoyi.demo.controller; + +import com.ruoyi.common.annotation.RedisLock; +import com.ruoyi.common.core.domain.AjaxResult; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + + +/** + * 测试分布式锁的样例 + * + * @author shenxinquan + */ +@RestController +@RequestMapping("/demo/redisLock") +public class RedisLockController { + + /** + * #p0 标识取第一个参数为redis锁的key + */ + @GetMapping("/getLock") + @RedisLock(expireTime = 10, key = "#p0") + public AjaxResult getLock(String key, String value) { + try { + // 同时请求排队 +// Thread.sleep(5000); + // 锁超时测试 + Thread.sleep(11000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + return AjaxResult.success("操作成功",value); + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java index 7e6e9b1d3..999f47a99 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java @@ -8,6 +8,7 @@ import com.ruoyi.common.core.domain.entity.SysRole; import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.core.domain.model.LoginUser; import com.ruoyi.common.utils.ServletUtils; +import com.ruoyi.common.utils.reflect.ReflectUtils; import com.ruoyi.common.utils.spring.SpringUtils; import com.ruoyi.framework.web.service.TokenService; import org.aspectj.lang.JoinPoint; @@ -166,13 +167,8 @@ public class DataScopeAspect { BaseEntity baseEntity = (BaseEntity) params; baseEntity.getParams().put(DATA_SCOPE, sql); } else { - try { - Method getParams = params.getClass().getDeclaredMethod("getParams", null); - Map invoke = (Map) getParams.invoke(params, null); - invoke.put(DATA_SCOPE, sql); - } catch (Exception e) { - // 方法未找到 不处理 - } + Map invoke = ReflectUtils.invokeGetter(params, "params"); + invoke.put(DATA_SCOPE, sql); } } } diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/RedisLockAspect.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/RedisLockAspect.java new file mode 100644 index 000000000..0af3844ff --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/RedisLockAspect.java @@ -0,0 +1,164 @@ +package com.ruoyi.framework.aspectj; + + +import com.ruoyi.common.annotation.RedisLock; +import com.ruoyi.common.constant.Constants; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.reflect.MethodSignature; +import org.redisson.api.RLock; +import org.redisson.api.RedissonClient; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; + +/** + * 分布式锁(注解实现版本) + * + * @author shenxinquan + */ + +@Slf4j +@Aspect +@Order(9) +@Component +public class RedisLockAspect { + + @Autowired + private RedissonClient redissonClient; + + @Pointcut("@annotation(com.ruoyi.common.annotation.RedisLock)") + public void annotationPointcut() { + } + + @Around("annotationPointcut()") + public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable { + // 获得当前访问的class + Class className = joinPoint.getTarget().getClass(); + // 获得访问的方法名 + String methodName = joinPoint.getSignature().getName(); + // 得到方法的参数的类型 + Class[] argClass = ((MethodSignature) joinPoint.getSignature()).getParameterTypes(); + Object[] args = joinPoint.getArgs(); + String key = ""; + // 默认30秒过期时间 + int expireTime = 30; + + try { + // 得到访问的方法对象 + Method method = className.getMethod(methodName, argClass); + method.setAccessible(true); + // 判断是否存在@RedisLock注解 + if (method.isAnnotationPresent(RedisLock.class)) { + RedisLock annotation = method.getAnnotation(RedisLock.class); + key = getRedisKey(args, annotation.key()); + expireTime = getExpireTime(annotation); + } + } catch (Exception e) { + throw new RuntimeException("redis分布式锁注解参数异常", e); + } + + // 声明锁名称 + key = Constants.REDIS_LOCK_KEY + key; + Object res; + try { + if (acquire(key, expireTime, TimeUnit.SECONDS)) { + try { + res = joinPoint.proceed(); + return res; + } catch (Exception e) { + throw new RuntimeException(e); + } finally { + release(key); + } + } else { + throw new RuntimeException("redis分布式锁注解参数异常"); + } + } catch (IllegalMonitorStateException e) { + log.error("lock timeout => key : " + key + " , ThreadName : " + Thread.currentThread().getName()); + throw new RuntimeException("lock timeout => key : " + key); + } catch (Exception e) { + throw new Exception("redis分布式未知异常", e); + } + } + + private int getExpireTime(RedisLock annotation) { + return annotation.expireTime(); + } + + private String getRedisKey(Object[] args, String primalKey) { + if (args.length == 0) { + return primalKey; + } + // 获取#p0...集合 + List keyList = getKeyParsList(primalKey); + for (String keyName : keyList) { + int keyIndex = Integer.parseInt(keyName.toLowerCase().replace("#p", "")); + Object parValue = args[keyIndex]; + primalKey = primalKey.replace(keyName, String.valueOf(parValue)); + } + return primalKey.replace("+", "").replace("'", ""); + } + + /** + * 获取key中#p0中的参数名称 + */ + private static List getKeyParsList(String key) { + List listPar = new ArrayList<>(); + if (key.contains("#")) { + int plusIndex = key.substring(key.indexOf("#")).indexOf("+"); + int indexNext = 0; + String parName; + int indexPre = key.indexOf("#"); + if (plusIndex > 0) { + indexNext = key.indexOf("#") + plusIndex; + parName = key.substring(indexPre, indexNext); + } else { + parName = key.substring(indexPre); + } + listPar.add(parName.trim()); + key = key.substring(indexNext + 1); + if (key.contains("#")) { + listPar.addAll(getKeyParsList(key)); + } + } + return listPar; + } + + /** + * 加锁(RLock)带超时时间的 + */ + private boolean acquire(String key, long expire, TimeUnit expireUnit) { + try { + //获取锁对象 + RLock mylock = redissonClient.getLock(key); + //加锁,并且设置锁过期时间,防止死锁的产生 + mylock.tryLock(expire, expire, expireUnit); + } catch (InterruptedException e) { + return false; + } + log.info("lock => key : " + key + " , ThreadName : " + Thread.currentThread().getName()); + //加锁成功 + return true; + } + + /** + * 锁的释放 + */ + private void release(String lockName) { + //获取所对象 + RLock mylock = redissonClient.getLock(lockName); + //释放锁(解锁) + mylock.unlock(); + log.info("unlock => key : " + lockName + " , ThreadName : " + Thread.currentThread().getName()); + } + +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java index b86872985..e86f5bc03 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java @@ -1,5 +1,6 @@ package com.ruoyi.framework.config; +import cn.hutool.core.util.StrUtil; import com.ruoyi.framework.config.properties.RedissonProperties; import org.redisson.Redisson; import org.redisson.api.RedissonClient; @@ -52,7 +53,7 @@ public class RedisConfig extends CachingConfigurerSupport { .setAddress(prefix + redisProperties.getHost() + ":" + redisProperties.getPort()) .setConnectTimeout(((Long) redisProperties.getTimeout().toMillis()).intValue()) .setDatabase(redisProperties.getDatabase()) - .setPassword(redisProperties.getPassword()) + .setPassword(StrUtil.isNotBlank(redisProperties.getPassword()) ? redisProperties.getPassword() : null) .setTimeout(singleServerConfig.getTimeout()) .setRetryAttempts(singleServerConfig.getRetryAttempts()) .setRetryInterval(singleServerConfig.getRetryInterval()) diff --git a/ruoyi-generator/src/main/resources/vm/java/vo.java.vm b/ruoyi-generator/src/main/resources/vm/java/vo.java.vm index 87f72090f..4641d7808 100644 --- a/ruoyi-generator/src/main/resources/vm/java/vo.java.vm +++ b/ruoyi-generator/src/main/resources/vm/java/vo.java.vm @@ -29,7 +29,7 @@ public class ${ClassName}Vo { private ${pkColumn.javaType} ${pkColumn.javaField}; #foreach ($column in $columns) -#if($column.isList) +#if($column.isList && $column.isPk!=1) /** $column.columnComment */ #set($parentheseIndex=$column.columnComment.indexOf("(")) #if($parentheseIndex != -1) diff --git a/ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm b/ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm index 969dba855..f1247aba3 100644 --- a/ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm +++ b/ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm @@ -247,7 +247,7 @@ #end @@ -302,6 +302,8 @@ export default { }, data() { return { + //按钮loading + buttonLoading: false, // 遮罩层 loading: true, // 显示搜索条件 @@ -480,12 +482,14 @@ export default { }, /** 修改按钮操作 */ handleUpdate(row) { + this.loading = true; this.reset(); this.getTreeselect(); if (row != null) { this.form.${treeParentCode} = row.${treeCode}; } get${BusinessName}(row.${pkColumn.javaField}).then(response => { + this.loading = false; this.form = response.data; #foreach ($column in $columns) #if($column.htmlType == "checkbox") @@ -500,6 +504,7 @@ export default { submitForm() { this.#[[$]]#refs["form"].validate(valid => { if (valid) { + this.buttonLoading = true; #foreach ($column in $columns) #if($column.htmlType == "checkbox") this.form.$column.javaField = this.form.${column.javaField}.join(","); @@ -507,12 +512,14 @@ export default { #end if (this.form.${pkColumn.javaField} != null) { update${BusinessName}(this.form).then(response => { + this.buttonLoading = false; this.msgSuccess("修改成功"); this.open = false; this.getList(); }); } else { add${BusinessName}(this.form).then(response => { + this.buttonLoading = false; this.msgSuccess("新增成功"); this.open = false; this.getList(); @@ -527,9 +534,11 @@ export default { confirmButtonText: "确定", cancelButtonText: "取消", type: "warning" - }).then(function() { + }).then(() => { + this.loading = true; return del${BusinessName}(row.${pkColumn.javaField}); }).then(() => { + this.loading = false; this.getList(); this.msgSuccess("删除成功"); }) diff --git a/ruoyi-generator/src/main/resources/vm/vue/index.vue.vm b/ruoyi-generator/src/main/resources/vm/vue/index.vue.vm index b384ba5ee..9f58575bd 100644 --- a/ruoyi-generator/src/main/resources/vm/vue/index.vue.vm +++ b/ruoyi-generator/src/main/resources/vm/vue/index.vue.vm @@ -301,7 +301,7 @@ #end @@ -353,6 +353,8 @@ export default { }, data() { return { + //按钮loading + buttonLoading: false, // 遮罩层 loading: true, // 导出遮罩层 @@ -534,9 +536,11 @@ export default { }, /** 修改按钮操作 */ handleUpdate(row) { + this.loading = true; this.reset(); const ${pkColumn.javaField} = row.${pkColumn.javaField} || this.ids get${BusinessName}(${pkColumn.javaField}).then(response => { + this.loading = false; this.form = response.data; #foreach ($column in $columns) #if($column.htmlType == "checkbox") @@ -554,6 +558,7 @@ export default { submitForm() { this.#[[$]]#refs["form"].validate(valid => { if (valid) { + this.buttonLoading = true; #foreach ($column in $columns) #if($column.htmlType == "checkbox") this.form.$column.javaField = this.form.${column.javaField}.join(","); @@ -564,12 +569,14 @@ export default { #end if (this.form.${pkColumn.javaField} != null) { update${BusinessName}(this.form).then(response => { + this.buttonLoading = false; this.msgSuccess("修改成功"); this.open = false; this.getList(); }); } else { add${BusinessName}(this.form).then(response => { + this.buttonLoading = false; this.msgSuccess("新增成功"); this.open = false; this.getList(); @@ -585,9 +592,11 @@ export default { confirmButtonText: "确定", cancelButtonText: "取消", type: "warning" - }).then(function() { + }).then(() => { + this.loading = true; return del${BusinessName}(${pkColumn.javaField}s); }).then(() => { + this.loading = false; this.getList(); this.msgSuccess("删除成功"); }) diff --git a/ruoyi-ui/package.json b/ruoyi-ui/package.json index 2fc1921b9..52551a4cc 100644 --- a/ruoyi-ui/package.json +++ b/ruoyi-ui/package.json @@ -1,6 +1,6 @@ { "name": "ruoyi-vue-plus", - "version": "2.3.0", + "version": "2.3.1", "description": "RuoYi-Vue-Plus后台管理系统", "author": "LionLi", "license": "MIT", diff --git a/ruoyi-ui/src/views/demo/demo/index.vue b/ruoyi-ui/src/views/demo/demo/index.vue index b831ad9b3..48fa36819 100644 --- a/ruoyi-ui/src/views/demo/demo/index.vue +++ b/ruoyi-ui/src/views/demo/demo/index.vue @@ -152,7 +152,7 @@ @@ -168,6 +168,8 @@ export default { }, data() { return { + //按钮loading + buttonLoading: false, // 遮罩层 loading: true, // 导出遮罩层 @@ -277,9 +279,11 @@ export default { }, /** 修改按钮操作 */ handleUpdate(row) { + this.loading = true; this.reset(); const id = row.id || this.ids getDemo(id).then(response => { + this.loading = false; this.form = response.data; this.open = true; this.title = "修改测试单表"; @@ -289,14 +293,17 @@ export default { submitForm() { this.$refs["form"].validate(valid => { if (valid) { + this.buttonLoading = true; if (this.form.id != null) { updateDemo(this.form).then(response => { + this.buttonLoading = false; this.msgSuccess("修改成功"); this.open = false; this.getList(); }); } else { addDemo(this.form).then(response => { + this.buttonLoading = false; this.msgSuccess("新增成功"); this.open = false; this.getList(); @@ -312,9 +319,11 @@ export default { confirmButtonText: "确定", cancelButtonText: "取消", type: "warning" - }).then(function() { + }).then(() => { + this.loading = true; return delDemo(ids); }).then(() => { + this.loading = false; this.getList(); this.msgSuccess("删除成功"); }) diff --git a/ruoyi-ui/src/views/demo/tree/index.vue b/ruoyi-ui/src/views/demo/tree/index.vue index ddf767777..afe96c4ae 100644 --- a/ruoyi-ui/src/views/demo/tree/index.vue +++ b/ruoyi-ui/src/views/demo/tree/index.vue @@ -102,7 +102,7 @@ @@ -121,6 +121,8 @@ export default { }, data() { return { + //按钮loading + buttonLoading: false, // 遮罩层 loading: true, // 显示搜索条件 @@ -233,12 +235,14 @@ export default { }, /** 修改按钮操作 */ handleUpdate(row) { + this.loading = true; this.reset(); this.getTreeselect(); if (row != null) { this.form.parentId = row.id; } getTree(row.id).then(response => { + this.loading = false; this.form = response.data; this.open = true; this.title = "修改测试树表"; @@ -248,14 +252,17 @@ export default { submitForm() { this.$refs["form"].validate(valid => { if (valid) { + this.buttonLoading = true; if (this.form.id != null) { updateTree(this.form).then(response => { + this.buttonLoading = false; this.msgSuccess("修改成功"); this.open = false; this.getList(); }); } else { addTree(this.form).then(response => { + this.buttonLoading = false; this.msgSuccess("新增成功"); this.open = false; this.getList(); @@ -270,9 +277,11 @@ export default { confirmButtonText: "确定", cancelButtonText: "取消", type: "warning" - }).then(function() { + }).then(() => { + this.loading = true; return delTree(row.id); }).then(() => { + this.loading = false; this.getList(); this.msgSuccess("删除成功"); }) diff --git a/ruoyi-ui/src/views/index.vue b/ruoyi-ui/src/views/index.vue index 29d4dbb5c..d904f3098 100644 --- a/ruoyi-ui/src/views/index.vue +++ b/ruoyi-ui/src/views/index.vue @@ -80,6 +80,18 @@ 更新日志 + +
    +
  1. add 增加 redisson 分布式锁 注解与demo案例
  2. +
  3. add 增加 Oracle 分支
  4. +
  5. update 优化 redis 空密码兼容性
  6. +
  7. update 优化前端代码生成按钮增加 loading
  8. +
  9. fix 修复 redisson 不能批量删除的bug
  10. +
  11. fix 修复表单构建选择下拉选择控制台报错问题
  12. +
  13. fix 修复 vo 代码生成 主键列表显示 重复生成bug
  14. +
  15. fix 修复上传路径 win 打包编译为 win 路径, linux 报错bug
  16. +
+
  1. add 升级 luttuce 为 redisson 性能更强 工具更全
  2. @@ -195,12 +207,14 @@