From 1dfeae6a031d07f90280ef9c2561130803543299 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A8=9A=E5=B1=BF?= <1491182878@qq.com> Date: Thu, 24 Jun 2021 00:27:37 +0000 Subject: [PATCH 01/62] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=97=A5=E5=BF=97?= =?UTF-8?q?=E5=88=97=E8=A1=A8=E5=8F=96=E6=B6=88=E5=AD=97=E6=AE=B5=E6=8E=92?= =?UTF-8?q?=E5=BA=8F=E6=97=B6=E7=9A=84=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 --- .../ruoyi/common/core/page/PageDomain.java | 164 +++++++++--------- 1 file changed, 83 insertions(+), 81 deletions(-) diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/page/PageDomain.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/page/PageDomain.java index 119b385f..40a97326 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/core/page/PageDomain.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/page/PageDomain.java @@ -1,81 +1,83 @@ -package com.ruoyi.common.core.page; - -import com.ruoyi.common.utils.StringUtils; - -/** - * 分页数据 - * - * @author ruoyi - */ -public class PageDomain -{ - /** 当前记录起始索引 */ - private Integer pageNum; - - /** 每页显示记录数 */ - private Integer pageSize; - - /** 排序列 */ - private String orderByColumn; - - /** 排序的方向desc或者asc */ - private String isAsc = "asc"; - - public String getOrderBy() - { - if (StringUtils.isEmpty(orderByColumn)) - { - return ""; - } - return StringUtils.toUnderScoreCase(orderByColumn) + " " + isAsc; - } - - public Integer getPageNum() - { - return pageNum; - } - - public void setPageNum(Integer pageNum) - { - this.pageNum = pageNum; - } - - public Integer getPageSize() - { - return pageSize; - } - - public void setPageSize(Integer pageSize) - { - this.pageSize = pageSize; - } - - public String getOrderByColumn() - { - return orderByColumn; - } - - public void setOrderByColumn(String orderByColumn) - { - this.orderByColumn = orderByColumn; - } - - public String getIsAsc() - { - return isAsc; - } - - public void setIsAsc(String isAsc) - { - // 兼容前端排序类型 - if ("ascending".equals(isAsc)) - { - isAsc = "asc"; - } - else if ("descending".equals(isAsc)) - { - isAsc = "desc"; - } - this.isAsc = isAsc; - } -} +package com.ruoyi.common.core.page; + +import com.ruoyi.common.utils.StringUtils; + +/** + * 分页数据 + * + * @author ruoyi + */ +public class PageDomain +{ + /** 当前记录起始索引 */ + private Integer pageNum; + + /** 每页显示记录数 */ + private Integer pageSize; + + /** 排序列 */ + private String orderByColumn; + + /** 排序的方向desc或者asc */ + private String isAsc = "asc"; + + public String getOrderBy() + { + if (StringUtils.isEmpty(orderByColumn)) + { + return ""; + } + return StringUtils.toUnderScoreCase(orderByColumn) + " " + isAsc; + } + + public Integer getPageNum() + { + return pageNum; + } + + public void setPageNum(Integer pageNum) + { + this.pageNum = pageNum; + } + + public Integer getPageSize() + { + return pageSize; + } + + public void setPageSize(Integer pageSize) + { + this.pageSize = pageSize; + } + + public String getOrderByColumn() + { + return orderByColumn; + } + + public void setOrderByColumn(String orderByColumn) + { + this.orderByColumn = orderByColumn; + } + + public String getIsAsc() + { + return isAsc; + } + + public void setIsAsc(String isAsc) + { + if (StringUtils.isNotEmpty(isAsc)) { + // 兼容前端排序类型 + if ("ascending".equals(isAsc)) + { + isAsc = "asc"; + } + else if ("descending".equals(isAsc)) + { + isAsc = "desc"; + } + this.isAsc = isAsc; + } + } +} From 9b76b5ac98164f38e57df50d277b03599b66d02e 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, 24 Jun 2021 09:39:14 +0800 Subject: [PATCH 02/62] =?UTF-8?q?update=20=E6=9B=B4=E6=96=B0=E6=96=87?= =?UTF-8?q?=E6=A1=A3=E7=89=88=E6=9C=AC?= 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 cd4863db..3a24d047 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [![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-Plus](https://img.shields.io/badge/RuoYi_Vue_Plus-2.3.2-success.svg)](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus) +[![RuoYi-Vue-Plus](https://img.shields.io/badge/RuoYi_Vue_Plus-2.4.0-success.svg)](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus) [![Spring Boot](https://img.shields.io/badge/Spring%20Boot-2.4-blue.svg)]() [![JDK-8+](https://img.shields.io/badge/JDK-8+-green.svg)]() [![JDK-11](https://img.shields.io/badge/JDK-11-green.svg)]() From 66f453452e3fd0985c581d762d63feccaef08d8e 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, 24 Jun 2021 15:41:16 +0800 Subject: [PATCH 03/62] =?UTF-8?q?fix=20=E7=9B=B8=E5=AF=B9=E8=B7=AF?= =?UTF-8?q?=E5=BE=84=E4=B8=8B=E8=BD=BD=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ruoyi/web/controller/common/CommonController.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java index 38913f50..d61f99f2 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java @@ -18,6 +18,7 @@ import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import java.io.File; import java.util.HashMap; import java.util.Map; @@ -51,13 +52,13 @@ public class CommonController } String realFileName = System.currentTimeMillis() + fileName.substring(fileName.indexOf("_") + 1); String filePath = RuoYiConfig.getDownloadPath() + fileName; - + File file = new File(filePath); response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE); FileUtils.setAttachmentResponseHeader(response, realFileName); - FileUtils.writeToStream(filePath, response.getOutputStream()); + FileUtils.writeToStream(file, response.getOutputStream()); if (delete) { - FileUtils.del(filePath); + FileUtils.del(file); } } catch (Exception e) @@ -110,8 +111,9 @@ public class CommonController // 下载名称 String downloadName = StrUtil.subAfter(downloadPath, "/",true); response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE); + File file = new File(downloadPath); FileUtils.setAttachmentResponseHeader(response, downloadName); - FileUtils.writeToStream(downloadPath, response.getOutputStream()); + FileUtils.writeToStream(file, response.getOutputStream()); } catch (Exception e) { From 676ecd90525e72b3865bf4f8f7f27bfb390cc37d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=B1=E6=9D=B0?= <693337446@qq.com> Date: Thu, 24 Jun 2021 16:49:04 +0800 Subject: [PATCH 04/62] =?UTF-8?q?update=20=E4=BF=AE=E6=94=B9readme?= =?UTF-8?q?=E5=8A=A0=E5=85=A5=E6=8F=90=E9=97=AE=E5=9B=9B=E9=83=A8=E6=9B=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 3a24d047..f6aba400 100644 --- a/README.md +++ b/README.md @@ -35,9 +35,25 @@ [初始化项目 必看](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/关于初始化项目?sort_id=4164117)
[参考文档 Wiki](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages) +## 提问四部曲 +### 一、查阅wiki +优先在`wiki->重点事项`,查找是否有相关问题及解决方案,尤其是框架更新后产生的问题,多会在wiki中提及 +> [参考文档 Wiki](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages) +### 二、借助issues +尝试issues中搜索问题关键字(记得选择已完成),看看是否有其他人提出相同问题 +- `如果有`那么依据评论中的解决方案自行尝试解决 +- `如果没有`那么提交一个新的issues描述清楚你的问题,需要包含以下内容(优质的issues,能够帮助作则更高效的帮你解决问题): + - 出现问题的模块或功能或类,总之你要说清楚在哪出的问题 + - 描述产生问题的相关操作流程,以便复现快速解决 + - 报错的日志截图,一定是截图,不要复制一堆报错的文本 +> [issues](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/issues) +### 三、百度 +大家都懂,不多描述,将关键的报错信息CC->CV到百度中看看大佬们怎么解决的 +> [百度](http://www.baidu.com) +### 四、加群 +以上三点已经能解决大家绝大部分问题了,如果还有问题没能通过这几种方式解决,那么加群,大家一起在群里探讨一下 ## 修改RuoYi功能 - ### 依赖改动 * ORM框架 使用 Mybatis-Plus 简化CRUD (不支持主子表) From beef02a4b61ea8bddaef331cc13932c706599741 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, 24 Jun 2021 17:10:03 +0800 Subject: [PATCH 05/62] =?UTF-8?q?update=20=E6=9B=B4=E6=96=B0=E6=96=87?= =?UTF-8?q?=E6=A1=A3=20=E6=8F=90=E9=97=AE=E5=9B=9B=E9=83=A8=E6=9B=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index f6aba400..d1606232 100644 --- a/README.md +++ b/README.md @@ -32,27 +32,32 @@ 使用框架前请仔细阅读文档重点注意事项
-[初始化项目 必看](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/关于初始化项目?sort_id=4164117) +>[初始化项目 必看](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/关于初始化项目?sort_id=4164117)
-[参考文档 Wiki](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages) +>[参考文档 Wiki](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages) + ## 提问四部曲 ### 一、查阅wiki 优先在`wiki->重点事项`,查找是否有相关问题及解决方案,尤其是框架更新后产生的问题,多会在wiki中提及 > [参考文档 Wiki](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages) + ### 二、借助issues 尝试issues中搜索问题关键字(记得选择已完成),看看是否有其他人提出相同问题 - `如果有`那么依据评论中的解决方案自行尝试解决 -- `如果没有`那么提交一个新的issues描述清楚你的问题,需要包含以下内容(优质的issues,能够帮助作则更高效的帮你解决问题): +- `如果没有`那么提交一个新的issues描述清楚你的问题,需要包含以下内容(优质的issues,能够帮助作者更高效的帮你解决问题): - 出现问题的模块或功能或类,总之你要说清楚在哪出的问题 - 描述产生问题的相关操作流程,以便复现快速解决 - 报错的日志截图,一定是截图,不要复制一堆报错的文本 > [issues](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/issues) + ### 三、百度 大家都懂,不多描述,将关键的报错信息CC->CV到百度中看看大佬们怎么解决的 > [百度](http://www.baidu.com) + ### 四、加群 以上三点已经能解决大家绝大部分问题了,如果还有问题没能通过这几种方式解决,那么加群,大家一起在群里探讨一下 + ## 修改RuoYi功能 ### 依赖改动 From 96507d37099024609fb01459b6033321a097f0d7 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, 24 Jun 2021 17:12:48 +0800 Subject: [PATCH 06/62] =?UTF-8?q?update=20=E6=9B=B4=E6=96=B0=E6=96=87?= =?UTF-8?q?=E6=A1=A3=20=E6=8F=90=E9=97=AE=E5=9B=9B=E9=83=A8=E6=9B=B2?= 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 d1606232..688da088 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ 使用框架前请仔细阅读文档重点注意事项
>[初始化项目 必看](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/关于初始化项目?sort_id=4164117) -
+> >[参考文档 Wiki](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages) ## 提问四部曲 From b73a67455d06d58ae221909bdaf674ea8872c706 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 Jun 2021 08:01:54 +0000 Subject: [PATCH 07/62] update README.md. --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 688da088..5fc29ab7 100644 --- a/README.md +++ b/README.md @@ -95,9 +95,8 @@ * 单模块 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/0625/160026_11d949aa_1766278.jpeg "07f7121fab14e57e03e5f6a35eff6ce.jpg") ## 捐献作者 作者为兼职做开源,平时还需要工作,如果帮到了您可以请作者吃个盒饭 From 04f5a93aa86ed2ce884696cb4490e67af54e871b Mon Sep 17 00:00:00 2001 From: RuoYi Date: Fri, 25 Jun 2021 17:25:49 +0800 Subject: [PATCH 08/62] =?UTF-8?q?=E5=8D=87=E7=BA=A7pagehelper=E5=88=B0?= =?UTF-8?q?=E6=9C=80=E6=96=B0=E7=89=881.3.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 2 +- .../src/main/java/com/ruoyi/common/core/page/PageDomain.java | 3 ++- ruoyi-ui/vue.config.js | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 526c269b..456b1480 100644 --- a/pom.xml +++ b/pom.xml @@ -23,7 +23,7 @@ 3.0.0 2.3.2 2.1.4 - 1.3.0 + 1.3.1 1.2.76 5.7.4 5.8.0 diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/page/PageDomain.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/page/PageDomain.java index 40a97326..b9d5e6e4 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/core/page/PageDomain.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/page/PageDomain.java @@ -67,7 +67,8 @@ public class PageDomain public void setIsAsc(String isAsc) { - if (StringUtils.isNotEmpty(isAsc)) { + if (StringUtils.isNotEmpty(isAsc)) + { // 兼容前端排序类型 if ("ascending".equals(isAsc)) { diff --git a/ruoyi-ui/vue.config.js b/ruoyi-ui/vue.config.js index f119c43a..76707460 100644 --- a/ruoyi-ui/vue.config.js +++ b/ruoyi-ui/vue.config.js @@ -109,7 +109,7 @@ module.exports = { config.optimization.runtimeChunk('single'), { from: path.resolve(__dirname, './public/robots.txt'), //防爬虫文件 - to: './', //到根目录下 + to: './' //到根目录下 } } ) From 99de90a015fb0494950f6f52f03ab5c34d192eee 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 Jun 2021 19:23:02 +0800 Subject: [PATCH 09/62] =?UTF-8?q?update=20=E6=9B=B4=E6=96=B0=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E6=B3=A8=E9=87=8A(=E8=A7=84=E8=8C=83=E4=BD=BF?= =?UTF-8?q?=E7=94=A8=E6=96=B9=E6=B3=95)?= 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 e153d194..047c45f9 100644 --- a/ruoyi-admin/src/main/resources/application.yml +++ b/ruoyi-admin/src/main/resources/application.yml @@ -110,6 +110,7 @@ token: # MyBatisPlus配置 # https://baomidou.com/config/ mybatis-plus: + # 不支持多包, 如有需要请在注解配置 mapperPackage: com.ruoyi.**.mapper # 对应的 XML 文件位置 mapperLocations: classpath*:mapper/**/*Mapper.xml @@ -244,6 +245,7 @@ thread-pool: # feign 相关配置 feign: + # 不支持多包, 如有需要请在注解配置 package: com.ruoyi.**.feign # 开启压缩 compression: From 10a6a9192db791e771755936d5650e1a0012c7c5 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 Jun 2021 09:57:45 +0800 Subject: [PATCH 10/62] =?UTF-8?q?update=20=E6=9B=B4=E6=96=B0=20MP=20?= =?UTF-8?q?=E8=AF=A6=E7=BB=86=E6=97=A5=E5=BF=97=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ruoyi-admin/src/main/resources/application.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml index 047c45f9..9fec4ae7 100644 --- a/ruoyi-admin/src/main/resources/application.yml +++ b/ruoyi-admin/src/main/resources/application.yml @@ -110,7 +110,8 @@ token: # MyBatisPlus配置 # https://baomidou.com/config/ mybatis-plus: - # 不支持多包, 如有需要请在注解配置 + # 不支持多包, 如有需要可在注解配置 或 提升扫包等级 + # 例如 com.**.**.mapper mapperPackage: com.ruoyi.**.mapper # 对应的 XML 文件位置 mapperLocations: classpath*:mapper/**/*Mapper.xml @@ -158,6 +159,8 @@ mybatis-plus: localCacheScope: SESSION # 开启Mybatis二级缓存,默认为 true cacheEnabled: true + # 更详细的日志输出 会有性能损耗 + # logImpl: org.apache.ibatis.logging.stdout.StdOutImpl global-config: # 是否打印 Logo banner banner: true @@ -245,7 +248,8 @@ thread-pool: # feign 相关配置 feign: - # 不支持多包, 如有需要请在注解配置 + # 不支持多包, 如有需要可在注解配置 或 提升扫包等级 + # 例如 com.**.**.feign package: com.ruoyi.**.feign # 开启压缩 compression: From 200170e5f3cd25c16bb9a891b96320af96f8edb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=86=E7=BB=A7=E4=BF=9D?= Date: Tue, 29 Jun 2021 07:04:25 +0000 Subject: [PATCH 11/62] update ruoyi-common/src/main/java/com/ruoyi/common/utils/DictUtils.java. --- .../src/main/java/com/ruoyi/common/utils/DictUtils.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/DictUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/DictUtils.java index 7da0c669..5d1fef18 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/DictUtils.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/DictUtils.java @@ -88,7 +88,7 @@ public class DictUtils StringBuilder propertyString = new StringBuilder(); List datas = getDictCache(dictType); - if (StrUtil.containsAny(separator, dictValue) && CollUtil.isNotEmpty(datas)) + if (StrUtil.containsAny(dictValue, separator) && CollUtil.isNotEmpty(datas)) { for (SysDictData dict : datas) { @@ -128,7 +128,7 @@ public class DictUtils StringBuilder propertyString = new StringBuilder(); List datas = getDictCache(dictType); - if (StrUtil.containsAny(separator, dictLabel) && CollUtil.isNotEmpty(datas)) + if (StrUtil.containsAny(dictLabel, separator) && CollUtil.isNotEmpty(datas)) { for (SysDictData dict : datas) { From d92560b64b5ec5ad48d62304e4a04b2fd60ead22 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 Jun 2021 15:22:45 +0800 Subject: [PATCH 12/62] =?UTF-8?q?fix=20=E4=BF=AE=E5=A4=8D=20hutool=20StrUt?= =?UTF-8?q?il.containsAny=20=E4=BC=A0=E5=85=A5=E5=8F=82=E6=95=B0=E5=90=8E?= =?UTF-8?q?=E8=BF=94=E5=9B=9E=E7=BB=93=E6=9E=9C=E4=B8=8D=E4=B8=80=E8=87=B4?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/ruoyi/common/utils/poi/ExcelUtil.java | 2144 ++++++++--------- .../service/GenTableServiceImpl.java | 2 +- 2 files changed, 1073 insertions(+), 1073 deletions(-) diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java index 619ec80c..96843d18 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java @@ -1,1072 +1,1072 @@ -package com.ruoyi.common.utils.poi; - -import cn.hutool.core.convert.Convert; -import cn.hutool.core.lang.Validator; -import cn.hutool.core.util.StrUtil; -import com.ruoyi.common.annotation.Excel; -import com.ruoyi.common.annotation.Excel.ColumnType; -import com.ruoyi.common.annotation.Excel.Type; -import com.ruoyi.common.annotation.Excels; -import com.ruoyi.common.config.RuoYiConfig; -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.exception.CustomException; -import com.ruoyi.common.utils.DateUtils; -import com.ruoyi.common.utils.DictUtils; -import com.ruoyi.common.utils.file.FileTypeUtils; -import com.ruoyi.common.utils.file.ImageUtils; -import com.ruoyi.common.utils.reflect.ReflectUtils; -import org.apache.poi.ss.usermodel.*; -import org.apache.poi.ss.util.CellRangeAddressList; -import org.apache.poi.xssf.streaming.SXSSFWorkbook; -import org.apache.poi.xssf.usermodel.XSSFClientAnchor; -import org.apache.poi.xssf.usermodel.XSSFDataValidation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.*; -import java.lang.reflect.Field; -import java.math.BigDecimal; -import java.text.DecimalFormat; -import java.util.*; -import java.util.stream.Collectors; - -/** - * Excel相关处理 - * - * @author ruoyi - */ -public class ExcelUtil -{ - private static final Logger log = LoggerFactory.getLogger(ExcelUtil.class); - - /** - * Excel sheet最大行数,默认65536 - */ - public static final int sheetSize = 65536; - - /** - * 工作表名称 - */ - private String sheetName; - - /** - * 导出类型(EXPORT:导出数据;IMPORT:导入模板) - */ - private Type type; - - /** - * 工作薄对象 - */ - private Workbook wb; - - /** - * 工作表对象 - */ - private Sheet sheet; - - /** - * 样式列表 - */ - private Map styles; - - /** - * 导入导出数据列表 - */ - private List list; - - /** - * 注解列表 - */ - private List fields; - - /** - * 最大高度 - */ - private short maxHeight; - - /** - * 统计列表 - */ - private Map statistics = new HashMap(); - - /** - * 数字格式 - */ - private static final DecimalFormat DOUBLE_FORMAT = new DecimalFormat("######0.00"); - - /** - * 实体对象 - */ - public Class clazz; - - public ExcelUtil(Class clazz) - { - this.clazz = clazz; - } - - public void init(List list, String sheetName, Type type) - { - if (list == null) - { - list = new ArrayList(); - } - this.list = list; - this.sheetName = sheetName; - this.type = type; - createExcelField(); - createWorkbook(); - } - - /** - * 对excel表单默认第一个索引名转换成list - * - * @param is 输入流 - * @return 转换后集合 - */ - public List importExcel(InputStream is) throws Exception - { - return importExcel(StrUtil.EMPTY, is); - } - - /** - * 对excel表单指定表格索引名转换成list - * - * @param sheetName 表格索引名 - * @param is 输入流 - * @return 转换后集合 - */ - public List importExcel(String sheetName, InputStream is) throws Exception - { - this.type = Type.IMPORT; - this.wb = WorkbookFactory.create(is); - List list = new ArrayList(); - Sheet sheet = null; - if (Validator.isNotEmpty(sheetName)) - { - // 如果指定sheet名,则取指定sheet中的内容. - sheet = wb.getSheet(sheetName); - } - else - { - // 如果传入的sheet名不存在则默认指向第1个sheet. - sheet = wb.getSheetAt(0); - } - - if (sheet == null) - { - throw new IOException("文件sheet不存在"); - } - - int rows = sheet.getPhysicalNumberOfRows(); - - if (rows > 0) - { - // 定义一个map用于存放excel列的序号和field. - Map cellMap = new HashMap(); - // 获取表头 - Row heard = sheet.getRow(0); - for (int i = 0; i < heard.getPhysicalNumberOfCells(); i++) - { - Cell cell = heard.getCell(i); - if (Validator.isNotNull(cell)) - { - String value = this.getCellValue(heard, i).toString(); - cellMap.put(value, i); - } - else - { - cellMap.put(null, i); - } - } - // 有数据时才处理 得到类的所有field. - Field[] allFields = clazz.getDeclaredFields(); - // 定义一个map用于存放列的序号和field. - Map fieldsMap = new HashMap(); - for (int col = 0; col < allFields.length; col++) - { - Field field = allFields[col]; - Excel attr = field.getAnnotation(Excel.class); - if (attr != null && (attr.type() == Type.ALL || attr.type() == type)) - { - // 设置类的私有字段属性可访问. - field.setAccessible(true); - Integer column = cellMap.get(attr.name()); - if (column != null) - { - fieldsMap.put(column, field); - } - } - } - for (int i = 1; i < rows; i++) - { - // 从第2行开始取数据,默认第一行是表头. - Row row = sheet.getRow(i); - if(row == null) - { - continue; - } - T entity = null; - for (Map.Entry entry : fieldsMap.entrySet()) - { - Object val = this.getCellValue(row, entry.getKey()); - - // 如果不存在实例则新建. - entity = (entity == null ? clazz.newInstance() : entity); - // 从map中得到对应列的field. - Field field = fieldsMap.get(entry.getKey()); - // 取得类型,并根据对象类型设置值. - Class fieldType = field.getType(); - if (String.class == fieldType) - { - String s = Convert.toStr(val); - if (StrUtil.endWith(s, ".0")) - { - val = StrUtil.subBefore(s, ".0",false); - } - else - { - String dateFormat = field.getAnnotation(Excel.class).dateFormat(); - if (Validator.isNotEmpty(dateFormat)) - { - val = DateUtils.parseDateToStr(dateFormat, (Date) val); - } - else - { - val = Convert.toStr(val); - } - } - } - else if ((Integer.TYPE == fieldType || Integer.class == fieldType) && Validator.isNumber(Convert.toStr(val))) - { - val = Convert.toInt(val); - } - else if (Long.TYPE == fieldType || Long.class == fieldType) - { - val = Convert.toLong(val); - } - else if (Double.TYPE == fieldType || Double.class == fieldType) - { - val = Convert.toDouble(val); - } - else if (Float.TYPE == fieldType || Float.class == fieldType) - { - val = Convert.toFloat(val); - } - else if (BigDecimal.class == fieldType) - { - val = Convert.toBigDecimal(val); - } - else if (Date.class == fieldType) - { - if (val instanceof String) - { - val = DateUtils.parseDate(val); - } - else if (val instanceof Double) - { - val = DateUtil.getJavaDate((Double) val); - } - } - else if (Boolean.TYPE == fieldType || Boolean.class == fieldType) - { - val = Convert.toBool(val, false); - } - if (Validator.isNotNull(fieldType)) - { - Excel attr = field.getAnnotation(Excel.class); - String propertyName = field.getName(); - if (Validator.isNotEmpty(attr.targetAttr())) - { - propertyName = field.getName() + "." + attr.targetAttr(); - } - else if (Validator.isNotEmpty(attr.readConverterExp())) - { - val = reverseByExp(Convert.toStr(val), attr.readConverterExp(), attr.separator()); - } - else if (Validator.isNotEmpty(attr.dictType())) - { - val = reverseDictByExp(Convert.toStr(val), attr.dictType(), attr.separator()); - } - ReflectUtils.invokeSetter(entity, propertyName, val); - } - } - list.add(entity); - } - } - return list; - } - - /** - * 对list数据源将其里面的数据导入到excel表单 - * - * @param list 导出数据集合 - * @param sheetName 工作表的名称 - * @return 结果 - */ - public AjaxResult exportExcel(List list, String sheetName) - { - this.init(list, sheetName, Type.EXPORT); - return exportExcel(); - } - - /** - * 对list数据源将其里面的数据导入到excel表单 - * - * @param sheetName 工作表的名称 - * @return 结果 - */ - public AjaxResult importTemplateExcel(String sheetName) - { - this.init(null, sheetName, Type.IMPORT); - return exportExcel(); - } - - /** - * 对list数据源将其里面的数据导入到excel表单 - * - * @return 结果 - */ - public AjaxResult exportExcel() - { - OutputStream out = null; - try - { - // 取出一共有多少个sheet. - double sheetNo = Math.ceil(list.size() / sheetSize); - for (int index = 0; index <= sheetNo; index++) - { - createSheet(sheetNo, index); - - // 产生一行 - Row row = sheet.createRow(0); - int column = 0; - // 写入各个字段的列头名称 - for (Object[] os : fields) - { - Excel excel = (Excel) os[1]; - this.createCell(excel, row, column++); - } - if (Type.EXPORT.equals(type)) - { - fillExcelData(index, row); - addStatisticsRow(); - } - } - String filename = encodingFilename(sheetName); - out = new FileOutputStream(getAbsoluteFile(filename)); - wb.write(out); - return AjaxResult.success(filename); - } - catch (Exception e) - { - log.error("导出Excel异常{}", e.getMessage()); - throw new CustomException("导出Excel失败,请联系网站管理员!"); - } - finally - { - if (wb != null) - { - try - { - wb.close(); - } - catch (IOException e1) - { - e1.printStackTrace(); - } - } - if (out != null) - { - try - { - out.close(); - } - catch (IOException e1) - { - e1.printStackTrace(); - } - } - } - } - - /** - * 填充excel数据 - * - * @param index 序号 - * @param row 单元格行 - */ - public void fillExcelData(int index, Row row) - { - int startNo = index * sheetSize; - int endNo = Math.min(startNo + sheetSize, list.size()); - for (int i = startNo; i < endNo; i++) - { - row = sheet.createRow(i + 1 - startNo); - // 得到导出对象. - T vo = (T) list.get(i); - int column = 0; - for (Object[] os : fields) - { - Field field = (Field) os[0]; - Excel excel = (Excel) os[1]; - // 设置实体类私有属性可访问 - field.setAccessible(true); - this.addCell(excel, row, vo, field, column++); - } - } - } - - /** - * 创建表格样式 - * - * @param wb 工作薄对象 - * @return 样式列表 - */ - private Map createStyles(Workbook wb) - { - // 写入各条记录,每条记录对应excel表中的一行 - Map styles = new HashMap(); - CellStyle style = wb.createCellStyle(); - style.setAlignment(HorizontalAlignment.CENTER); - style.setVerticalAlignment(VerticalAlignment.CENTER); - style.setBorderRight(BorderStyle.THIN); - style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); - style.setBorderLeft(BorderStyle.THIN); - style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); - style.setBorderTop(BorderStyle.THIN); - style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); - style.setBorderBottom(BorderStyle.THIN); - style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); - Font dataFont = wb.createFont(); - dataFont.setFontName("Arial"); - dataFont.setFontHeightInPoints((short) 10); - style.setFont(dataFont); - styles.put("data", style); - - style = wb.createCellStyle(); - style.cloneStyleFrom(styles.get("data")); - style.setAlignment(HorizontalAlignment.CENTER); - style.setVerticalAlignment(VerticalAlignment.CENTER); - style.setFillForegroundColor(IndexedColors.GREY_50_PERCENT.getIndex()); - style.setFillPattern(FillPatternType.SOLID_FOREGROUND); - Font headerFont = wb.createFont(); - headerFont.setFontName("Arial"); - headerFont.setFontHeightInPoints((short) 10); - headerFont.setBold(true); - headerFont.setColor(IndexedColors.WHITE.getIndex()); - style.setFont(headerFont); - styles.put("header", style); - - style = wb.createCellStyle(); - style.setAlignment(HorizontalAlignment.CENTER); - style.setVerticalAlignment(VerticalAlignment.CENTER); - Font totalFont = wb.createFont(); - totalFont.setFontName("Arial"); - totalFont.setFontHeightInPoints((short) 10); - style.setFont(totalFont); - styles.put("total", style); - - style = wb.createCellStyle(); - style.cloneStyleFrom(styles.get("data")); - style.setAlignment(HorizontalAlignment.LEFT); - styles.put("data1", style); - - style = wb.createCellStyle(); - style.cloneStyleFrom(styles.get("data")); - style.setAlignment(HorizontalAlignment.CENTER); - styles.put("data2", style); - - style = wb.createCellStyle(); - style.cloneStyleFrom(styles.get("data")); - style.setAlignment(HorizontalAlignment.RIGHT); - styles.put("data3", style); - - return styles; - } - - /** - * 创建单元格 - */ - public Cell createCell(Excel attr, Row row, int column) - { - // 创建列 - Cell cell = row.createCell(column); - // 写入列信息 - cell.setCellValue(attr.name()); - setDataValidation(attr, row, column); - cell.setCellStyle(styles.get("header")); - return cell; - } - - /** - * 设置单元格信息 - * - * @param value 单元格值 - * @param attr 注解相关 - * @param cell 单元格信息 - */ - public void setCellVo(Object value, Excel attr, Cell cell) - { - if (ColumnType.STRING == attr.cellType()) - { - cell.setCellValue(Validator.isNull(value) ? attr.defaultValue() : value + attr.suffix()); - } - else if (ColumnType.NUMERIC == attr.cellType()) - { - if (Validator.isNotNull(value)) - { - cell.setCellValue(StrUtil.contains(Convert.toStr(value), ".") ? Convert.toDouble(value) : Convert.toInt(value)); - } - } - else if (ColumnType.IMAGE == attr.cellType()) - { - ClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, (short) cell.getColumnIndex(), cell.getRow().getRowNum(), (short) (cell.getColumnIndex() + 1), - cell.getRow().getRowNum() + 1); - String imagePath = Convert.toStr(value); - if (Validator.isNotEmpty(imagePath)) - { - byte[] data = ImageUtils.getImage(imagePath); - getDrawingPatriarch(cell.getSheet()).createPicture(anchor, - cell.getSheet().getWorkbook().addPicture(data, getImageType(data))); - } - } - } - - /** - * 获取画布 - */ - public static Drawing getDrawingPatriarch(Sheet sheet) - { - if (sheet.getDrawingPatriarch() == null) - { - sheet.createDrawingPatriarch(); - } - return sheet.getDrawingPatriarch(); - } - - /** - * 获取图片类型,设置图片插入类型 - */ - public int getImageType(byte[] value) - { - String type = FileTypeUtils.getFileExtendName(value); - if ("JPG".equalsIgnoreCase(type)) - { - return Workbook.PICTURE_TYPE_JPEG; - } - else if ("PNG".equalsIgnoreCase(type)) - { - return Workbook.PICTURE_TYPE_PNG; - } - return Workbook.PICTURE_TYPE_JPEG; - } - - /** - * 创建表格样式 - */ - public void setDataValidation(Excel attr, Row row, int column) - { - if (attr.name().indexOf("注:") >= 0) - { - sheet.setColumnWidth(column, 6000); - } - else - { - // 设置列宽 - sheet.setColumnWidth(column, (int) ((attr.width() + 0.72) * 256)); - } - // 如果设置了提示信息则鼠标放上去提示. - if (Validator.isNotEmpty(attr.prompt())) - { - // 这里默认设了2-101列提示. - setXSSFPrompt(sheet, "", attr.prompt(), 1, 100, column, column); - } - // 如果设置了combo属性则本列只能选择不能输入 - if (attr.combo().length > 0) - { - // 这里默认设了2-101列只能选择不能输入. - setXSSFValidation(sheet, attr.combo(), 1, 100, column, column); - } - } - - /** - * 添加单元格 - */ - public Cell addCell(Excel attr, Row row, T vo, Field field, int column) - { - Cell cell = null; - try - { - // 设置行高 - row.setHeight(maxHeight); - // 根据Excel中设置情况决定是否导出,有些情况需要保持为空,希望用户填写这一列. - if (attr.isExport()) - { - // 创建cell - cell = row.createCell(column); - int align = attr.align().value(); - cell.setCellStyle(styles.get("data" + (align >= 1 && align <= 3 ? align : ""))); - - // 用于读取对象中的属性 - Object value = getTargetValue(vo, field, attr); - String dateFormat = attr.dateFormat(); - String readConverterExp = attr.readConverterExp(); - String separator = attr.separator(); - String dictType = attr.dictType(); - if (Validator.isNotEmpty(dateFormat) && Validator.isNotNull(value)) - { - cell.setCellValue(DateUtils.parseDateToStr(dateFormat, (Date) value)); - } - else if (Validator.isNotEmpty(readConverterExp) && Validator.isNotNull(value)) - { - cell.setCellValue(convertByExp(Convert.toStr(value), readConverterExp, separator)); - } - else if (Validator.isNotEmpty(dictType) && Validator.isNotNull(value)) - { - cell.setCellValue(convertDictByExp(Convert.toStr(value), dictType, separator)); - } - else if (value instanceof BigDecimal && -1 != attr.scale()) - { - cell.setCellValue((((BigDecimal) value).setScale(attr.scale(), attr.roundingMode())).toString()); - } - else - { - // 设置列类型 - setCellVo(value, attr, cell); - } - addStatisticsData(column, Convert.toStr(value), attr); - } - } - catch (Exception e) - { - log.error("导出Excel失败{}", e); - } - return cell; - } - - /** - * 设置 POI XSSFSheet 单元格提示 - * - * @param sheet 表单 - * @param promptTitle 提示标题 - * @param promptContent 提示内容 - * @param firstRow 开始行 - * @param endRow 结束行 - * @param firstCol 开始列 - * @param endCol 结束列 - */ - public void setXSSFPrompt(Sheet sheet, String promptTitle, String promptContent, int firstRow, int endRow, - int firstCol, int endCol) - { - DataValidationHelper helper = sheet.getDataValidationHelper(); - DataValidationConstraint constraint = helper.createCustomConstraint("DD1"); - CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol); - DataValidation dataValidation = helper.createValidation(constraint, regions); - dataValidation.createPromptBox(promptTitle, promptContent); - dataValidation.setShowPromptBox(true); - sheet.addValidationData(dataValidation); - } - - /** - * 设置某些列的值只能输入预制的数据,显示下拉框. - * - * @param sheet 要设置的sheet. - * @param textlist 下拉框显示的内容 - * @param firstRow 开始行 - * @param endRow 结束行 - * @param firstCol 开始列 - * @param endCol 结束列 - * @return 设置好的sheet. - */ - public void setXSSFValidation(Sheet sheet, String[] textlist, int firstRow, int endRow, int firstCol, int endCol) - { - DataValidationHelper helper = sheet.getDataValidationHelper(); - // 加载下拉列表内容 - DataValidationConstraint constraint = helper.createExplicitListConstraint(textlist); - // 设置数据有效性加载在哪个单元格上,四个参数分别是:起始行、终止行、起始列、终止列 - CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol); - // 数据有效性对象 - DataValidation dataValidation = helper.createValidation(constraint, regions); - // 处理Excel兼容性问题 - if (dataValidation instanceof XSSFDataValidation) - { - dataValidation.setSuppressDropDownArrow(true); - dataValidation.setShowErrorBox(true); - } - else - { - dataValidation.setSuppressDropDownArrow(false); - } - - sheet.addValidationData(dataValidation); - } - - /** - * 解析导出值 0=男,1=女,2=未知 - * - * @param propertyValue 参数值 - * @param converterExp 翻译注解 - * @param separator 分隔符 - * @return 解析后值 - */ - public static String convertByExp(String propertyValue, String converterExp, String separator) - { - StringBuilder propertyString = new StringBuilder(); - String[] convertSource = converterExp.split(","); - for (String item : convertSource) - { - String[] itemArray = item.split("="); - if (StrUtil.containsAny(separator, propertyValue)) - { - for (String value : propertyValue.split(separator)) - { - if (itemArray[0].equals(value)) - { - propertyString.append(itemArray[1] + separator); - break; - } - } - } - else - { - if (itemArray[0].equals(propertyValue)) - { - return itemArray[1]; - } - } - } - return StrUtil.strip(propertyString.toString(), null,separator); - } - - /** - * 反向解析值 男=0,女=1,未知=2 - * - * @param propertyValue 参数值 - * @param converterExp 翻译注解 - * @param separator 分隔符 - * @return 解析后值 - */ - public static String reverseByExp(String propertyValue, String converterExp, String separator) - { - StringBuilder propertyString = new StringBuilder(); - String[] convertSource = converterExp.split(","); - for (String item : convertSource) - { - String[] itemArray = item.split("="); - if (StrUtil.containsAny(separator, propertyValue)) - { - for (String value : propertyValue.split(separator)) - { - if (itemArray[1].equals(value)) - { - propertyString.append(itemArray[0] + separator); - break; - } - } - } - else - { - if (itemArray[1].equals(propertyValue)) - { - return itemArray[0]; - } - } - } - return StrUtil.strip(propertyString.toString(), null,separator); - } - - /** - * 解析字典值 - * - * @param dictValue 字典值 - * @param dictType 字典类型 - * @param separator 分隔符 - * @return 字典标签 - */ - public static String convertDictByExp(String dictValue, String dictType, String separator) - { - return DictUtils.getDictLabel(dictType, dictValue, separator); - } - - /** - * 反向解析值字典值 - * - * @param dictLabel 字典标签 - * @param dictType 字典类型 - * @param separator 分隔符 - * @return 字典值 - */ - public static String reverseDictByExp(String dictLabel, String dictType, String separator) - { - return DictUtils.getDictValue(dictType, dictLabel, separator); - } - - /** - * 合计统计信息 - */ - private void addStatisticsData(Integer index, String text, Excel entity) - { - if (entity != null && entity.isStatistics()) - { - Double temp = 0D; - if (!statistics.containsKey(index)) - { - statistics.put(index, temp); - } - try - { - temp = Double.valueOf(text); - } - catch (NumberFormatException e) - { - } - statistics.put(index, statistics.get(index) + temp); - } - } - - /** - * 创建统计行 - */ - public void addStatisticsRow() - { - if (statistics.size() > 0) - { - Cell cell = null; - Row row = sheet.createRow(sheet.getLastRowNum() + 1); - Set keys = statistics.keySet(); - cell = row.createCell(0); - cell.setCellStyle(styles.get("total")); - cell.setCellValue("合计"); - - for (Integer key : keys) - { - cell = row.createCell(key); - cell.setCellStyle(styles.get("total")); - cell.setCellValue(DOUBLE_FORMAT.format(statistics.get(key))); - } - statistics.clear(); - } - } - - /** - * 编码文件名 - */ - public String encodingFilename(String filename) - { - filename = UUID.randomUUID().toString() + "_" + filename + ".xlsx"; - return filename; - } - - /** - * 获取下载路径 - * - * @param filename 文件名称 - */ - public String getAbsoluteFile(String filename) - { - String downloadPath = RuoYiConfig.getDownloadPath() + filename; - File desc = new File(downloadPath); - if (!desc.getParentFile().exists()) - { - desc.getParentFile().mkdirs(); - } - return downloadPath; - } - - /** - * 获取bean中的属性值 - * - * @param vo 实体对象 - * @param field 字段 - * @param excel 注解 - * @return 最终的属性值 - * @throws Exception - */ - private Object getTargetValue(T vo, Field field, Excel excel) throws Exception - { - Object o = field.get(vo); - if (Validator.isNotEmpty(excel.targetAttr())) - { - String target = excel.targetAttr(); - if (target.contains(".")) - { - String[] targets = target.split("[.]"); - for (String name : targets) - { - o = getValue(o, name); - } - } - else - { - o = getValue(o, target); - } - } - return o; - } - - /** - * 以类的属性的get方法方法形式获取值 - * - * @param o - * @param name - * @return value - * @throws Exception - */ - private Object getValue(Object o, String name) throws Exception - { - if (Validator.isNotNull(o) && Validator.isNotEmpty(name)) - { - Class clazz = o.getClass(); - Field field = clazz.getDeclaredField(name); - field.setAccessible(true); - o = field.get(o); - } - return o; - } - - /** - * 得到所有定义字段 - */ - private void createExcelField() - { - this.fields = new ArrayList(); - List tempFields = new ArrayList<>(); - tempFields.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredFields())); - tempFields.addAll(Arrays.asList(clazz.getDeclaredFields())); - for (Field field : tempFields) - { - // 单注解 - if (field.isAnnotationPresent(Excel.class)) - { - putToField(field, field.getAnnotation(Excel.class)); - } - - // 多注解 - if (field.isAnnotationPresent(Excels.class)) - { - Excels attrs = field.getAnnotation(Excels.class); - Excel[] excels = attrs.value(); - for (Excel excel : excels) - { - putToField(field, excel); - } - } - } - this.fields = this.fields.stream().sorted(Comparator.comparing(objects -> ((Excel) objects[1]).sort())).collect(Collectors.toList()); - this.maxHeight = getRowHeight(); - } - - /** - * 根据注解获取最大行高 - */ - public short getRowHeight() - { - double maxHeight = 0; - for (Object[] os : this.fields) - { - Excel excel = (Excel) os[1]; - maxHeight = maxHeight > excel.height() ? maxHeight : excel.height(); - } - return (short) (maxHeight * 20); - } - - /** - * 放到字段集合中 - */ - private void putToField(Field field, Excel attr) - { - if (attr != null && (attr.type() == Type.ALL || attr.type() == type)) - { - this.fields.add(new Object[] { field, attr }); - } - } - - /** - * 创建一个工作簿 - */ - public void createWorkbook() - { - this.wb = new SXSSFWorkbook(500); - } - - /** - * 创建工作表 - * - * @param sheetNo sheet数量 - * @param index 序号 - */ - public void createSheet(double sheetNo, int index) - { - this.sheet = wb.createSheet(); - this.styles = createStyles(wb); - // 设置工作表的名称. - if (sheetNo == 0) - { - wb.setSheetName(index, sheetName); - } - else - { - wb.setSheetName(index, sheetName + index); - } - } - - /** - * 获取单元格值 - * - * @param row 获取的行 - * @param column 获取单元格列号 - * @return 单元格值 - */ - public Object getCellValue(Row row, int column) - { - if (row == null) - { - return row; - } - Object val = ""; - try - { - Cell cell = row.getCell(column); - if (Validator.isNotNull(cell)) - { - if (cell.getCellType() == CellType.NUMERIC || cell.getCellType() == CellType.FORMULA) - { - val = cell.getNumericCellValue(); - if (DateUtil.isCellDateFormatted(cell)) - { - val = DateUtil.getJavaDate((Double) val); // POI Excel 日期格式转换 - } - else - { - if ((Double) val % 1 != 0) - { - val = new BigDecimal(val.toString()); - } - else - { - val = new DecimalFormat("0").format(val); - } - } - } - else if (cell.getCellType() == CellType.STRING) - { - val = cell.getStringCellValue(); - } - else if (cell.getCellType() == CellType.BOOLEAN) - { - val = cell.getBooleanCellValue(); - } - else if (cell.getCellType() == CellType.ERROR) - { - val = cell.getErrorCellValue(); - } - - } - } - catch (Exception e) - { - return val; - } - return val; - } -} \ No newline at end of file +package com.ruoyi.common.utils.poi; + +import cn.hutool.core.convert.Convert; +import cn.hutool.core.lang.Validator; +import cn.hutool.core.util.StrUtil; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.annotation.Excel.ColumnType; +import com.ruoyi.common.annotation.Excel.Type; +import com.ruoyi.common.annotation.Excels; +import com.ruoyi.common.config.RuoYiConfig; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.exception.CustomException; +import com.ruoyi.common.utils.DateUtils; +import com.ruoyi.common.utils.DictUtils; +import com.ruoyi.common.utils.file.FileTypeUtils; +import com.ruoyi.common.utils.file.ImageUtils; +import com.ruoyi.common.utils.reflect.ReflectUtils; +import org.apache.poi.ss.usermodel.*; +import org.apache.poi.ss.util.CellRangeAddressList; +import org.apache.poi.xssf.streaming.SXSSFWorkbook; +import org.apache.poi.xssf.usermodel.XSSFClientAnchor; +import org.apache.poi.xssf.usermodel.XSSFDataValidation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.*; +import java.lang.reflect.Field; +import java.math.BigDecimal; +import java.text.DecimalFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * Excel相关处理 + * + * @author ruoyi + */ +public class ExcelUtil +{ + private static final Logger log = LoggerFactory.getLogger(ExcelUtil.class); + + /** + * Excel sheet最大行数,默认65536 + */ + public static final int sheetSize = 65536; + + /** + * 工作表名称 + */ + private String sheetName; + + /** + * 导出类型(EXPORT:导出数据;IMPORT:导入模板) + */ + private Type type; + + /** + * 工作薄对象 + */ + private Workbook wb; + + /** + * 工作表对象 + */ + private Sheet sheet; + + /** + * 样式列表 + */ + private Map styles; + + /** + * 导入导出数据列表 + */ + private List list; + + /** + * 注解列表 + */ + private List fields; + + /** + * 最大高度 + */ + private short maxHeight; + + /** + * 统计列表 + */ + private Map statistics = new HashMap(); + + /** + * 数字格式 + */ + private static final DecimalFormat DOUBLE_FORMAT = new DecimalFormat("######0.00"); + + /** + * 实体对象 + */ + public Class clazz; + + public ExcelUtil(Class clazz) + { + this.clazz = clazz; + } + + public void init(List list, String sheetName, Type type) + { + if (list == null) + { + list = new ArrayList(); + } + this.list = list; + this.sheetName = sheetName; + this.type = type; + createExcelField(); + createWorkbook(); + } + + /** + * 对excel表单默认第一个索引名转换成list + * + * @param is 输入流 + * @return 转换后集合 + */ + public List importExcel(InputStream is) throws Exception + { + return importExcel(StrUtil.EMPTY, is); + } + + /** + * 对excel表单指定表格索引名转换成list + * + * @param sheetName 表格索引名 + * @param is 输入流 + * @return 转换后集合 + */ + public List importExcel(String sheetName, InputStream is) throws Exception + { + this.type = Type.IMPORT; + this.wb = WorkbookFactory.create(is); + List list = new ArrayList(); + Sheet sheet = null; + if (Validator.isNotEmpty(sheetName)) + { + // 如果指定sheet名,则取指定sheet中的内容. + sheet = wb.getSheet(sheetName); + } + else + { + // 如果传入的sheet名不存在则默认指向第1个sheet. + sheet = wb.getSheetAt(0); + } + + if (sheet == null) + { + throw new IOException("文件sheet不存在"); + } + + int rows = sheet.getPhysicalNumberOfRows(); + + if (rows > 0) + { + // 定义一个map用于存放excel列的序号和field. + Map cellMap = new HashMap(); + // 获取表头 + Row heard = sheet.getRow(0); + for (int i = 0; i < heard.getPhysicalNumberOfCells(); i++) + { + Cell cell = heard.getCell(i); + if (Validator.isNotNull(cell)) + { + String value = this.getCellValue(heard, i).toString(); + cellMap.put(value, i); + } + else + { + cellMap.put(null, i); + } + } + // 有数据时才处理 得到类的所有field. + Field[] allFields = clazz.getDeclaredFields(); + // 定义一个map用于存放列的序号和field. + Map fieldsMap = new HashMap(); + for (int col = 0; col < allFields.length; col++) + { + Field field = allFields[col]; + Excel attr = field.getAnnotation(Excel.class); + if (attr != null && (attr.type() == Type.ALL || attr.type() == type)) + { + // 设置类的私有字段属性可访问. + field.setAccessible(true); + Integer column = cellMap.get(attr.name()); + if (column != null) + { + fieldsMap.put(column, field); + } + } + } + for (int i = 1; i < rows; i++) + { + // 从第2行开始取数据,默认第一行是表头. + Row row = sheet.getRow(i); + if(row == null) + { + continue; + } + T entity = null; + for (Map.Entry entry : fieldsMap.entrySet()) + { + Object val = this.getCellValue(row, entry.getKey()); + + // 如果不存在实例则新建. + entity = (entity == null ? clazz.newInstance() : entity); + // 从map中得到对应列的field. + Field field = fieldsMap.get(entry.getKey()); + // 取得类型,并根据对象类型设置值. + Class fieldType = field.getType(); + if (String.class == fieldType) + { + String s = Convert.toStr(val); + if (StrUtil.endWith(s, ".0")) + { + val = StrUtil.subBefore(s, ".0",false); + } + else + { + String dateFormat = field.getAnnotation(Excel.class).dateFormat(); + if (Validator.isNotEmpty(dateFormat)) + { + val = DateUtils.parseDateToStr(dateFormat, (Date) val); + } + else + { + val = Convert.toStr(val); + } + } + } + else if ((Integer.TYPE == fieldType || Integer.class == fieldType) && Validator.isNumber(Convert.toStr(val))) + { + val = Convert.toInt(val); + } + else if (Long.TYPE == fieldType || Long.class == fieldType) + { + val = Convert.toLong(val); + } + else if (Double.TYPE == fieldType || Double.class == fieldType) + { + val = Convert.toDouble(val); + } + else if (Float.TYPE == fieldType || Float.class == fieldType) + { + val = Convert.toFloat(val); + } + else if (BigDecimal.class == fieldType) + { + val = Convert.toBigDecimal(val); + } + else if (Date.class == fieldType) + { + if (val instanceof String) + { + val = DateUtils.parseDate(val); + } + else if (val instanceof Double) + { + val = DateUtil.getJavaDate((Double) val); + } + } + else if (Boolean.TYPE == fieldType || Boolean.class == fieldType) + { + val = Convert.toBool(val, false); + } + if (Validator.isNotNull(fieldType)) + { + Excel attr = field.getAnnotation(Excel.class); + String propertyName = field.getName(); + if (Validator.isNotEmpty(attr.targetAttr())) + { + propertyName = field.getName() + "." + attr.targetAttr(); + } + else if (Validator.isNotEmpty(attr.readConverterExp())) + { + val = reverseByExp(Convert.toStr(val), attr.readConverterExp(), attr.separator()); + } + else if (Validator.isNotEmpty(attr.dictType())) + { + val = reverseDictByExp(Convert.toStr(val), attr.dictType(), attr.separator()); + } + ReflectUtils.invokeSetter(entity, propertyName, val); + } + } + list.add(entity); + } + } + return list; + } + + /** + * 对list数据源将其里面的数据导入到excel表单 + * + * @param list 导出数据集合 + * @param sheetName 工作表的名称 + * @return 结果 + */ + public AjaxResult exportExcel(List list, String sheetName) + { + this.init(list, sheetName, Type.EXPORT); + return exportExcel(); + } + + /** + * 对list数据源将其里面的数据导入到excel表单 + * + * @param sheetName 工作表的名称 + * @return 结果 + */ + public AjaxResult importTemplateExcel(String sheetName) + { + this.init(null, sheetName, Type.IMPORT); + return exportExcel(); + } + + /** + * 对list数据源将其里面的数据导入到excel表单 + * + * @return 结果 + */ + public AjaxResult exportExcel() + { + OutputStream out = null; + try + { + // 取出一共有多少个sheet. + double sheetNo = Math.ceil(list.size() / sheetSize); + for (int index = 0; index <= sheetNo; index++) + { + createSheet(sheetNo, index); + + // 产生一行 + Row row = sheet.createRow(0); + int column = 0; + // 写入各个字段的列头名称 + for (Object[] os : fields) + { + Excel excel = (Excel) os[1]; + this.createCell(excel, row, column++); + } + if (Type.EXPORT.equals(type)) + { + fillExcelData(index, row); + addStatisticsRow(); + } + } + String filename = encodingFilename(sheetName); + out = new FileOutputStream(getAbsoluteFile(filename)); + wb.write(out); + return AjaxResult.success(filename); + } + catch (Exception e) + { + log.error("导出Excel异常{}", e.getMessage()); + throw new CustomException("导出Excel失败,请联系网站管理员!"); + } + finally + { + if (wb != null) + { + try + { + wb.close(); + } + catch (IOException e1) + { + e1.printStackTrace(); + } + } + if (out != null) + { + try + { + out.close(); + } + catch (IOException e1) + { + e1.printStackTrace(); + } + } + } + } + + /** + * 填充excel数据 + * + * @param index 序号 + * @param row 单元格行 + */ + public void fillExcelData(int index, Row row) + { + int startNo = index * sheetSize; + int endNo = Math.min(startNo + sheetSize, list.size()); + for (int i = startNo; i < endNo; i++) + { + row = sheet.createRow(i + 1 - startNo); + // 得到导出对象. + T vo = (T) list.get(i); + int column = 0; + for (Object[] os : fields) + { + Field field = (Field) os[0]; + Excel excel = (Excel) os[1]; + // 设置实体类私有属性可访问 + field.setAccessible(true); + this.addCell(excel, row, vo, field, column++); + } + } + } + + /** + * 创建表格样式 + * + * @param wb 工作薄对象 + * @return 样式列表 + */ + private Map createStyles(Workbook wb) + { + // 写入各条记录,每条记录对应excel表中的一行 + Map styles = new HashMap(); + CellStyle style = wb.createCellStyle(); + style.setAlignment(HorizontalAlignment.CENTER); + style.setVerticalAlignment(VerticalAlignment.CENTER); + style.setBorderRight(BorderStyle.THIN); + style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); + style.setBorderLeft(BorderStyle.THIN); + style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); + style.setBorderTop(BorderStyle.THIN); + style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); + style.setBorderBottom(BorderStyle.THIN); + style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); + Font dataFont = wb.createFont(); + dataFont.setFontName("Arial"); + dataFont.setFontHeightInPoints((short) 10); + style.setFont(dataFont); + styles.put("data", style); + + style = wb.createCellStyle(); + style.cloneStyleFrom(styles.get("data")); + style.setAlignment(HorizontalAlignment.CENTER); + style.setVerticalAlignment(VerticalAlignment.CENTER); + style.setFillForegroundColor(IndexedColors.GREY_50_PERCENT.getIndex()); + style.setFillPattern(FillPatternType.SOLID_FOREGROUND); + Font headerFont = wb.createFont(); + headerFont.setFontName("Arial"); + headerFont.setFontHeightInPoints((short) 10); + headerFont.setBold(true); + headerFont.setColor(IndexedColors.WHITE.getIndex()); + style.setFont(headerFont); + styles.put("header", style); + + style = wb.createCellStyle(); + style.setAlignment(HorizontalAlignment.CENTER); + style.setVerticalAlignment(VerticalAlignment.CENTER); + Font totalFont = wb.createFont(); + totalFont.setFontName("Arial"); + totalFont.setFontHeightInPoints((short) 10); + style.setFont(totalFont); + styles.put("total", style); + + style = wb.createCellStyle(); + style.cloneStyleFrom(styles.get("data")); + style.setAlignment(HorizontalAlignment.LEFT); + styles.put("data1", style); + + style = wb.createCellStyle(); + style.cloneStyleFrom(styles.get("data")); + style.setAlignment(HorizontalAlignment.CENTER); + styles.put("data2", style); + + style = wb.createCellStyle(); + style.cloneStyleFrom(styles.get("data")); + style.setAlignment(HorizontalAlignment.RIGHT); + styles.put("data3", style); + + return styles; + } + + /** + * 创建单元格 + */ + public Cell createCell(Excel attr, Row row, int column) + { + // 创建列 + Cell cell = row.createCell(column); + // 写入列信息 + cell.setCellValue(attr.name()); + setDataValidation(attr, row, column); + cell.setCellStyle(styles.get("header")); + return cell; + } + + /** + * 设置单元格信息 + * + * @param value 单元格值 + * @param attr 注解相关 + * @param cell 单元格信息 + */ + public void setCellVo(Object value, Excel attr, Cell cell) + { + if (ColumnType.STRING == attr.cellType()) + { + cell.setCellValue(Validator.isNull(value) ? attr.defaultValue() : value + attr.suffix()); + } + else if (ColumnType.NUMERIC == attr.cellType()) + { + if (Validator.isNotNull(value)) + { + cell.setCellValue(StrUtil.contains(Convert.toStr(value), ".") ? Convert.toDouble(value) : Convert.toInt(value)); + } + } + else if (ColumnType.IMAGE == attr.cellType()) + { + ClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, (short) cell.getColumnIndex(), cell.getRow().getRowNum(), (short) (cell.getColumnIndex() + 1), + cell.getRow().getRowNum() + 1); + String imagePath = Convert.toStr(value); + if (Validator.isNotEmpty(imagePath)) + { + byte[] data = ImageUtils.getImage(imagePath); + getDrawingPatriarch(cell.getSheet()).createPicture(anchor, + cell.getSheet().getWorkbook().addPicture(data, getImageType(data))); + } + } + } + + /** + * 获取画布 + */ + public static Drawing getDrawingPatriarch(Sheet sheet) + { + if (sheet.getDrawingPatriarch() == null) + { + sheet.createDrawingPatriarch(); + } + return sheet.getDrawingPatriarch(); + } + + /** + * 获取图片类型,设置图片插入类型 + */ + public int getImageType(byte[] value) + { + String type = FileTypeUtils.getFileExtendName(value); + if ("JPG".equalsIgnoreCase(type)) + { + return Workbook.PICTURE_TYPE_JPEG; + } + else if ("PNG".equalsIgnoreCase(type)) + { + return Workbook.PICTURE_TYPE_PNG; + } + return Workbook.PICTURE_TYPE_JPEG; + } + + /** + * 创建表格样式 + */ + public void setDataValidation(Excel attr, Row row, int column) + { + if (attr.name().indexOf("注:") >= 0) + { + sheet.setColumnWidth(column, 6000); + } + else + { + // 设置列宽 + sheet.setColumnWidth(column, (int) ((attr.width() + 0.72) * 256)); + } + // 如果设置了提示信息则鼠标放上去提示. + if (Validator.isNotEmpty(attr.prompt())) + { + // 这里默认设了2-101列提示. + setXSSFPrompt(sheet, "", attr.prompt(), 1, 100, column, column); + } + // 如果设置了combo属性则本列只能选择不能输入 + if (attr.combo().length > 0) + { + // 这里默认设了2-101列只能选择不能输入. + setXSSFValidation(sheet, attr.combo(), 1, 100, column, column); + } + } + + /** + * 添加单元格 + */ + public Cell addCell(Excel attr, Row row, T vo, Field field, int column) + { + Cell cell = null; + try + { + // 设置行高 + row.setHeight(maxHeight); + // 根据Excel中设置情况决定是否导出,有些情况需要保持为空,希望用户填写这一列. + if (attr.isExport()) + { + // 创建cell + cell = row.createCell(column); + int align = attr.align().value(); + cell.setCellStyle(styles.get("data" + (align >= 1 && align <= 3 ? align : ""))); + + // 用于读取对象中的属性 + Object value = getTargetValue(vo, field, attr); + String dateFormat = attr.dateFormat(); + String readConverterExp = attr.readConverterExp(); + String separator = attr.separator(); + String dictType = attr.dictType(); + if (Validator.isNotEmpty(dateFormat) && Validator.isNotNull(value)) + { + cell.setCellValue(DateUtils.parseDateToStr(dateFormat, (Date) value)); + } + else if (Validator.isNotEmpty(readConverterExp) && Validator.isNotNull(value)) + { + cell.setCellValue(convertByExp(Convert.toStr(value), readConverterExp, separator)); + } + else if (Validator.isNotEmpty(dictType) && Validator.isNotNull(value)) + { + cell.setCellValue(convertDictByExp(Convert.toStr(value), dictType, separator)); + } + else if (value instanceof BigDecimal && -1 != attr.scale()) + { + cell.setCellValue((((BigDecimal) value).setScale(attr.scale(), attr.roundingMode())).toString()); + } + else + { + // 设置列类型 + setCellVo(value, attr, cell); + } + addStatisticsData(column, Convert.toStr(value), attr); + } + } + catch (Exception e) + { + log.error("导出Excel失败{}", e); + } + return cell; + } + + /** + * 设置 POI XSSFSheet 单元格提示 + * + * @param sheet 表单 + * @param promptTitle 提示标题 + * @param promptContent 提示内容 + * @param firstRow 开始行 + * @param endRow 结束行 + * @param firstCol 开始列 + * @param endCol 结束列 + */ + public void setXSSFPrompt(Sheet sheet, String promptTitle, String promptContent, int firstRow, int endRow, + int firstCol, int endCol) + { + DataValidationHelper helper = sheet.getDataValidationHelper(); + DataValidationConstraint constraint = helper.createCustomConstraint("DD1"); + CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol); + DataValidation dataValidation = helper.createValidation(constraint, regions); + dataValidation.createPromptBox(promptTitle, promptContent); + dataValidation.setShowPromptBox(true); + sheet.addValidationData(dataValidation); + } + + /** + * 设置某些列的值只能输入预制的数据,显示下拉框. + * + * @param sheet 要设置的sheet. + * @param textlist 下拉框显示的内容 + * @param firstRow 开始行 + * @param endRow 结束行 + * @param firstCol 开始列 + * @param endCol 结束列 + * @return 设置好的sheet. + */ + public void setXSSFValidation(Sheet sheet, String[] textlist, int firstRow, int endRow, int firstCol, int endCol) + { + DataValidationHelper helper = sheet.getDataValidationHelper(); + // 加载下拉列表内容 + DataValidationConstraint constraint = helper.createExplicitListConstraint(textlist); + // 设置数据有效性加载在哪个单元格上,四个参数分别是:起始行、终止行、起始列、终止列 + CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol); + // 数据有效性对象 + DataValidation dataValidation = helper.createValidation(constraint, regions); + // 处理Excel兼容性问题 + if (dataValidation instanceof XSSFDataValidation) + { + dataValidation.setSuppressDropDownArrow(true); + dataValidation.setShowErrorBox(true); + } + else + { + dataValidation.setSuppressDropDownArrow(false); + } + + sheet.addValidationData(dataValidation); + } + + /** + * 解析导出值 0=男,1=女,2=未知 + * + * @param propertyValue 参数值 + * @param converterExp 翻译注解 + * @param separator 分隔符 + * @return 解析后值 + */ + public static String convertByExp(String propertyValue, String converterExp, String separator) + { + StringBuilder propertyString = new StringBuilder(); + String[] convertSource = converterExp.split(","); + for (String item : convertSource) + { + String[] itemArray = item.split("="); + if (StrUtil.containsAny(propertyValue, separator)) + { + for (String value : propertyValue.split(separator)) + { + if (itemArray[0].equals(value)) + { + propertyString.append(itemArray[1] + separator); + break; + } + } + } + else + { + if (itemArray[0].equals(propertyValue)) + { + return itemArray[1]; + } + } + } + return StrUtil.strip(propertyString.toString(), null,separator); + } + + /** + * 反向解析值 男=0,女=1,未知=2 + * + * @param propertyValue 参数值 + * @param converterExp 翻译注解 + * @param separator 分隔符 + * @return 解析后值 + */ + public static String reverseByExp(String propertyValue, String converterExp, String separator) + { + StringBuilder propertyString = new StringBuilder(); + String[] convertSource = converterExp.split(","); + for (String item : convertSource) + { + String[] itemArray = item.split("="); + if (StrUtil.containsAny(propertyValue, separator)) + { + for (String value : propertyValue.split(separator)) + { + if (itemArray[1].equals(value)) + { + propertyString.append(itemArray[0] + separator); + break; + } + } + } + else + { + if (itemArray[1].equals(propertyValue)) + { + return itemArray[0]; + } + } + } + return StrUtil.strip(propertyString.toString(), null,separator); + } + + /** + * 解析字典值 + * + * @param dictValue 字典值 + * @param dictType 字典类型 + * @param separator 分隔符 + * @return 字典标签 + */ + public static String convertDictByExp(String dictValue, String dictType, String separator) + { + return DictUtils.getDictLabel(dictType, dictValue, separator); + } + + /** + * 反向解析值字典值 + * + * @param dictLabel 字典标签 + * @param dictType 字典类型 + * @param separator 分隔符 + * @return 字典值 + */ + public static String reverseDictByExp(String dictLabel, String dictType, String separator) + { + return DictUtils.getDictValue(dictType, dictLabel, separator); + } + + /** + * 合计统计信息 + */ + private void addStatisticsData(Integer index, String text, Excel entity) + { + if (entity != null && entity.isStatistics()) + { + Double temp = 0D; + if (!statistics.containsKey(index)) + { + statistics.put(index, temp); + } + try + { + temp = Double.valueOf(text); + } + catch (NumberFormatException e) + { + } + statistics.put(index, statistics.get(index) + temp); + } + } + + /** + * 创建统计行 + */ + public void addStatisticsRow() + { + if (statistics.size() > 0) + { + Cell cell = null; + Row row = sheet.createRow(sheet.getLastRowNum() + 1); + Set keys = statistics.keySet(); + cell = row.createCell(0); + cell.setCellStyle(styles.get("total")); + cell.setCellValue("合计"); + + for (Integer key : keys) + { + cell = row.createCell(key); + cell.setCellStyle(styles.get("total")); + cell.setCellValue(DOUBLE_FORMAT.format(statistics.get(key))); + } + statistics.clear(); + } + } + + /** + * 编码文件名 + */ + public String encodingFilename(String filename) + { + filename = UUID.randomUUID().toString() + "_" + filename + ".xlsx"; + return filename; + } + + /** + * 获取下载路径 + * + * @param filename 文件名称 + */ + public String getAbsoluteFile(String filename) + { + String downloadPath = RuoYiConfig.getDownloadPath() + filename; + File desc = new File(downloadPath); + if (!desc.getParentFile().exists()) + { + desc.getParentFile().mkdirs(); + } + return downloadPath; + } + + /** + * 获取bean中的属性值 + * + * @param vo 实体对象 + * @param field 字段 + * @param excel 注解 + * @return 最终的属性值 + * @throws Exception + */ + private Object getTargetValue(T vo, Field field, Excel excel) throws Exception + { + Object o = field.get(vo); + if (Validator.isNotEmpty(excel.targetAttr())) + { + String target = excel.targetAttr(); + if (target.contains(".")) + { + String[] targets = target.split("[.]"); + for (String name : targets) + { + o = getValue(o, name); + } + } + else + { + o = getValue(o, target); + } + } + return o; + } + + /** + * 以类的属性的get方法方法形式获取值 + * + * @param o + * @param name + * @return value + * @throws Exception + */ + private Object getValue(Object o, String name) throws Exception + { + if (Validator.isNotNull(o) && Validator.isNotEmpty(name)) + { + Class clazz = o.getClass(); + Field field = clazz.getDeclaredField(name); + field.setAccessible(true); + o = field.get(o); + } + return o; + } + + /** + * 得到所有定义字段 + */ + private void createExcelField() + { + this.fields = new ArrayList(); + List tempFields = new ArrayList<>(); + tempFields.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredFields())); + tempFields.addAll(Arrays.asList(clazz.getDeclaredFields())); + for (Field field : tempFields) + { + // 单注解 + if (field.isAnnotationPresent(Excel.class)) + { + putToField(field, field.getAnnotation(Excel.class)); + } + + // 多注解 + if (field.isAnnotationPresent(Excels.class)) + { + Excels attrs = field.getAnnotation(Excels.class); + Excel[] excels = attrs.value(); + for (Excel excel : excels) + { + putToField(field, excel); + } + } + } + this.fields = this.fields.stream().sorted(Comparator.comparing(objects -> ((Excel) objects[1]).sort())).collect(Collectors.toList()); + this.maxHeight = getRowHeight(); + } + + /** + * 根据注解获取最大行高 + */ + public short getRowHeight() + { + double maxHeight = 0; + for (Object[] os : this.fields) + { + Excel excel = (Excel) os[1]; + maxHeight = maxHeight > excel.height() ? maxHeight : excel.height(); + } + return (short) (maxHeight * 20); + } + + /** + * 放到字段集合中 + */ + private void putToField(Field field, Excel attr) + { + if (attr != null && (attr.type() == Type.ALL || attr.type() == type)) + { + this.fields.add(new Object[] { field, attr }); + } + } + + /** + * 创建一个工作簿 + */ + public void createWorkbook() + { + this.wb = new SXSSFWorkbook(500); + } + + /** + * 创建工作表 + * + * @param sheetNo sheet数量 + * @param index 序号 + */ + public void createSheet(double sheetNo, int index) + { + this.sheet = wb.createSheet(); + this.styles = createStyles(wb); + // 设置工作表的名称. + if (sheetNo == 0) + { + wb.setSheetName(index, sheetName); + } + else + { + wb.setSheetName(index, sheetName + index); + } + } + + /** + * 获取单元格值 + * + * @param row 获取的行 + * @param column 获取单元格列号 + * @return 单元格值 + */ + public Object getCellValue(Row row, int column) + { + if (row == null) + { + return row; + } + Object val = ""; + try + { + Cell cell = row.getCell(column); + if (Validator.isNotNull(cell)) + { + if (cell.getCellType() == CellType.NUMERIC || cell.getCellType() == CellType.FORMULA) + { + val = cell.getNumericCellValue(); + if (DateUtil.isCellDateFormatted(cell)) + { + val = DateUtil.getJavaDate((Double) val); // POI Excel 日期格式转换 + } + else + { + if ((Double) val % 1 != 0) + { + val = new BigDecimal(val.toString()); + } + else + { + val = new DecimalFormat("0").format(val); + } + } + } + else if (cell.getCellType() == CellType.STRING) + { + val = cell.getStringCellValue(); + } + else if (cell.getCellType() == CellType.BOOLEAN) + { + val = cell.getBooleanCellValue(); + } + else if (cell.getCellType() == CellType.ERROR) + { + val = cell.getErrorCellValue(); + } + + } + } + catch (Exception e) + { + return val; + } + return val; + } +} diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java index 4da27e87..a2bc2f42 100644 --- a/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java +++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java @@ -258,7 +258,7 @@ public class GenTableServiceImpl extends ServicePlusImpl templates = VelocityUtils.getTemplateList(table.getTplCategory()); for (String template : templates) { - if (!StrUtil.containsAny(template, "sql.vm", "api.js.vm", "index.vue.vm", "index-tree.vue.vm")) { + if (!StrUtil.containsAny("sql.vm", "api.js.vm", "index.vue.vm", "index-tree.vue.vm", template)) { // 渲染模板 StringWriter sw = new StringWriter(); Template tpl = Velocity.getTemplate(template, Constants.UTF8); From d4be4df8717250b2aa42eecf757a102687d10aeb 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 Jun 2021 13:37:11 +0800 Subject: [PATCH 13/62] =?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=E5=99=A8=20=E6=89=B9=E9=87=8F?= =?UTF-8?q?=E5=AF=BC=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ruoyi/generator/service/GenTableServiceImpl.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java index a2bc2f42..5fcdd3b3 100644 --- a/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java +++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java @@ -182,9 +182,9 @@ public class GenTableServiceImpl extends ServicePlusImpl genTableColumns = genTableColumnMapper.selectDbTableColumnsByName(tableName); for (GenTableColumn column : genTableColumns) { GenUtils.initColumnField(column, table); - genTableColumnMapper.insert(column); } - } + genTableColumnMapper.insertAll(genTableColumns); + } } } catch (Exception e) { throw new CustomException("导入失败:" + e.getMessage()); @@ -290,9 +290,9 @@ public class GenTableServiceImpl extends ServicePlusImpl { if (!tableColumnNames.contains(column.getColumnName())) { GenUtils.initColumnField(column, table); - genTableColumnMapper.insert(column); - } - }); + } + }); + genTableColumnMapper.insertAll(tableColumns); List delColumns = tableColumns.stream().filter(column -> !dbTableColumnNames.contains(column.getColumnName())).collect(Collectors.toList()); if (CollUtil.isNotEmpty(delColumns)) { From 5647cf7a7e038dec7d9064ee5714768bb8e90178 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, 1 Jul 2021 10:42:24 +0800 Subject: [PATCH 14/62] =?UTF-8?q?update=20=E8=A7=84=E8=8C=83maven=E5=86=99?= =?UTF-8?q?=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 2 +- ruoyi-admin/pom.xml | 2 +- ruoyi-common/pom.xml | 2 +- ruoyi-demo/pom.xml | 4 ++-- ruoyi-framework/pom.xml | 2 +- ruoyi-generator/pom.xml | 2 +- ruoyi-quartz/pom.xml | 2 +- ruoyi-system/pom.xml | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/pom.xml b/pom.xml index 2a8521c4..538b4267 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.ruoyi ruoyi-vue-plus - ${ruoyi-vue-plus.version} + 2.4.0 RuoYi-Vue-Plus https://gitee.com/JavaLionLi/RuoYi-Vue-Plus diff --git a/ruoyi-admin/pom.xml b/ruoyi-admin/pom.xml index 031427fc..f33a5d4c 100644 --- a/ruoyi-admin/pom.xml +++ b/ruoyi-admin/pom.xml @@ -5,7 +5,7 @@ ruoyi-vue-plus com.ruoyi - ${ruoyi-vue-plus.version} + 2.4.0 4.0.0 jar diff --git a/ruoyi-common/pom.xml b/ruoyi-common/pom.xml index e2cbd39f..aeafac81 100644 --- a/ruoyi-common/pom.xml +++ b/ruoyi-common/pom.xml @@ -5,7 +5,7 @@ ruoyi-vue-plus com.ruoyi - ${ruoyi-vue-plus.version} + 2.4.0 4.0.0 diff --git a/ruoyi-demo/pom.xml b/ruoyi-demo/pom.xml index 49049244..756f3d17 100644 --- a/ruoyi-demo/pom.xml +++ b/ruoyi-demo/pom.xml @@ -5,7 +5,7 @@ ruoyi-vue-plus com.ruoyi - ${ruoyi-vue-plus.version} + 2.4.0 4.0.0 @@ -25,4 +25,4 @@ - \ No newline at end of file + diff --git a/ruoyi-framework/pom.xml b/ruoyi-framework/pom.xml index 4313ce55..40c84799 100644 --- a/ruoyi-framework/pom.xml +++ b/ruoyi-framework/pom.xml @@ -5,7 +5,7 @@ ruoyi-vue-plus com.ruoyi - ${ruoyi-vue-plus.version} + 2.4.0 4.0.0 diff --git a/ruoyi-generator/pom.xml b/ruoyi-generator/pom.xml index 80737062..4774cfff 100644 --- a/ruoyi-generator/pom.xml +++ b/ruoyi-generator/pom.xml @@ -5,7 +5,7 @@ ruoyi-vue-plus com.ruoyi - ${ruoyi-vue-plus.version} + 2.4.0 4.0.0 diff --git a/ruoyi-quartz/pom.xml b/ruoyi-quartz/pom.xml index cfcbffcb..a92933f7 100644 --- a/ruoyi-quartz/pom.xml +++ b/ruoyi-quartz/pom.xml @@ -5,7 +5,7 @@ ruoyi-vue-plus com.ruoyi - ${ruoyi-vue-plus.version} + 2.4.0 4.0.0 diff --git a/ruoyi-system/pom.xml b/ruoyi-system/pom.xml index 2f5579f4..37b57de8 100644 --- a/ruoyi-system/pom.xml +++ b/ruoyi-system/pom.xml @@ -5,7 +5,7 @@ ruoyi-vue-plus com.ruoyi - ${ruoyi-vue-plus.version} + 2.4.0 4.0.0 From 945b6c1e5968f1ca11b3ef41232ea9d8bf29ff55 Mon Sep 17 00:00:00 2001 From: sxq <812980466@qq.com> Date: Thu, 1 Jul 2021 14:03:29 +0800 Subject: [PATCH 15/62] =?UTF-8?q?redis=E8=8E=B7=E5=8F=96map=E5=B1=9E?= =?UTF-8?q?=E6=80=A7bug=E4=BF=AE=E5=A4=8D=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/ruoyi/common/core/redis/RedisCache.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 3c8bc923..f46a2157 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 @@ -205,9 +205,9 @@ public class RedisCache { * @param hKeys Hash键集合 * @return Hash对象集合 */ - public List getMultiCacheMapValue(final String key, final Collection hKeys) { - RListMultimap rListMultimap = redissonClient.getListMultimap(key); - return rListMultimap.getAll(hKeys); + public Map getMultiCacheMapValue(final String key, final Set hKeys) { + RMap rMap = redissonClient.getMap(key); + return rMap.getAll(hKeys); } /** From 9c7901f526aa1fefd35da044b73c1a77e4d67ff0 Mon Sep 17 00:00:00 2001 From: RuoYi Date: Thu, 1 Jul 2021 18:01:36 +0800 Subject: [PATCH 16/62] =?UTF-8?q?=E7=94=A8=E6=88=B7=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=88=86=E9=85=8D=E8=A7=92=E8=89=B2=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/system/SysUserController.java | 27 ++++ .../ruoyi/system/service/ISysRoleService.java | 10 +- .../ruoyi/system/service/ISysUserService.java | 8 ++ .../service/impl/SysRoleServiceImpl.java | 25 ++++ .../service/impl/SysUserServiceImpl.java | 38 ++++++ ruoyi-ui/src/api/system/user.js | 17 +++ ruoyi-ui/src/assets/styles/ruoyi.scss | 18 +++ ruoyi-ui/src/router/index.js | 13 ++ ruoyi-ui/src/views/system/user/authRole.vue | 117 ++++++++++++++++++ ruoyi-ui/src/views/system/user/index.vue | 49 +++++--- 10 files changed, 306 insertions(+), 16 deletions(-) create mode 100644 ruoyi-ui/src/views/system/user/authRole.vue diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java index 03461ca9..692bd5cc 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java @@ -202,4 +202,31 @@ public class SysUserController extends BaseController user.setUpdateBy(SecurityUtils.getUsername()); return toAjax(userService.updateUserStatus(user)); } + + /** + * 根据用户编号获取授权角色 + */ + @PreAuthorize("@ss.hasPermi('system:user:query')") + @GetMapping("/authRole/{userId}") + public AjaxResult authRole(@PathVariable("userId") Long userId) + { + AjaxResult ajax = AjaxResult.success(); + SysUser user = userService.selectUserById(userId); + List roles = roleService.selectRolesByUserId(userId); + ajax.put("user", user); + ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList())); + return ajax; + } + + /** + * 用户授权角色 + */ + @PreAuthorize("@ss.hasPermi('system:user:edit')") + @Log(title = "用户管理", businessType = BusinessType.GRANT) + @PutMapping("/authRole") + public AjaxResult insertAuthRole(Long userId, Long[] roleIds) + { + userService.insertUserAuth(userId, roleIds); + return success(); + } } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java index 4a4bee26..846ef6e7 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java @@ -20,7 +20,15 @@ public interface ISysRoleService public List selectRoleList(SysRole role); /** - * 根据用户ID查询角色 + * 根据用户ID查询角色列表 + * + * @param userId 用户ID + * @return 角色列表 + */ + public List selectRolesByUserId(Long userId); + + /** + * 根据用户ID查询角色权限 * * @param userId 用户ID * @return 权限列表 diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java index 00afa001..5bf14880 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java @@ -96,6 +96,14 @@ public interface ISysUserService * @return 结果 */ public int updateUser(SysUser user); + + /** + * 用户授权角色 + * + * @param userId 用户ID + * @param roleIds 角色组 + */ + public void insertUserAuth(Long userId, Long[] roleIds); /** * 修改用户状态 diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java index cecc6a2c..409baf0a 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java @@ -55,6 +55,31 @@ public class SysRoleServiceImpl implements ISysRoleService return roleMapper.selectRoleList(role); } + /** + * 根据用户ID查询角色 + * + * @param userId 用户ID + * @return 角色列表 + */ + @Override + public List selectRolesByUserId(Long userId) + { + List userRoles = roleMapper.selectRolePermissionByUserId(userId); + List roles = selectRoleAll(); + for (SysRole role : roles) + { + for (SysRole userRole : userRoles) + { + if (role.getRoleId().longValue() == userRole.getRoleId().longValue()) + { + role.setFlag(true); + break; + } + } + } + return roles; + } + /** * 根据用户ID查询权限 * diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java index 065ae481..3da74904 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java @@ -242,6 +242,18 @@ public class SysUserServiceImpl implements ISysUserService return userMapper.updateUser(user); } + /** + * 用户授权角色 + * + * @param userId 用户ID + * @param roleIds 角色组 + */ + public void insertUserAuth(Long userId, Long[] roleIds) + { + userRoleMapper.deleteUserRoleByUserId(userId); + insertUserRole(userId, roleIds); + } + /** * 修改用户状态 * @@ -356,6 +368,32 @@ public class SysUserServiceImpl implements ISysUserService } } + /** + * 新增用户角色信息 + * + * @param userId 用户ID + * @param roleIds 角色组 + */ + public void insertUserRole(Long userId, Long[] roleIds) + { + if (StringUtils.isNotNull(roleIds)) + { + // 新增用户与角色管理 + List list = new ArrayList(); + for (Long roleId : roleIds) + { + SysUserRole ur = new SysUserRole(); + ur.setUserId(userId); + ur.setRoleId(roleId); + list.add(ur); + } + if (list.size() > 0) + { + userRoleMapper.batchUserRole(list); + } + } + } + /** * 通过用户ID删除用户 * diff --git a/ruoyi-ui/src/api/system/user.js b/ruoyi-ui/src/api/system/user.js index 7f8db39e..85bdc19c 100644 --- a/ruoyi-ui/src/api/system/user.js +++ b/ruoyi-ui/src/api/system/user.js @@ -125,3 +125,20 @@ export function importTemplate() { method: 'get' }) } + +// 查询授权角色 +export function getAuthRole(userId) { + return request({ + url: '/system/user/authRole/' + userId, + method: 'get' + }) +} + +// 保存授权角色 +export function updateAuthRole(data) { + return request({ + url: '/system/user/authRole', + method: 'put', + params: data + }) +} diff --git a/ruoyi-ui/src/assets/styles/ruoyi.scss b/ruoyi-ui/src/assets/styles/ruoyi.scss index c40c9fb0..5927b6c9 100644 --- a/ruoyi-ui/src/assets/styles/ruoyi.scss +++ b/ruoyi-ui/src/assets/styles/ruoyi.scss @@ -53,6 +53,13 @@ margin-left: 20px; } +.h1, .h2, .h3, .h4, .h5, .h6, h1, h2, h3, h4, h5, h6 { + font-family: inherit; + font-weight: 500; + line-height: 1.1; + color: inherit; +} + .el-dialog:not(.is-fullscreen){ margin-top: 6vh !important; } @@ -120,6 +127,17 @@ width: inherit; } +/** 表格更多操作下拉样式 */ +.el-table .el-dropdown-link { + cursor: pointer; + color: #1890ff; + margin-left: 5px; +} + +.el-table .el-dropdown, .el-icon-arrow-down { + font-size: 12px; +} + .el-tree-node__content > .el-checkbox { margin-right: 8px; } diff --git a/ruoyi-ui/src/router/index.js b/ruoyi-ui/src/router/index.js index 3f14fd3a..67fca82a 100644 --- a/ruoyi-ui/src/router/index.js +++ b/ruoyi-ui/src/router/index.js @@ -80,6 +80,19 @@ export const constantRoutes = [ } ] }, + { + path: '/auth', + component: Layout, + hidden: true, + children: [ + { + path: 'role/:userId(\\d+)', + component: (resolve) => require(['@/views/system/user/authRole'], resolve), + name: 'AuthRole', + meta: { title: '分配角色'} + } + ] + }, { path: '/dict', component: Layout, diff --git a/ruoyi-ui/src/views/system/user/authRole.vue b/ruoyi-ui/src/views/system/user/authRole.vue new file mode 100644 index 00000000..e0cd7bce --- /dev/null +++ b/ruoyi-ui/src/views/system/user/authRole.vue @@ -0,0 +1,117 @@ + + + \ No newline at end of file diff --git a/ruoyi-ui/src/views/system/user/index.vue b/ruoyi-ui/src/views/system/user/index.vue index b2c00eff..7f419c99 100644 --- a/ruoyi-ui/src/views/system/user/index.vue +++ b/ruoyi-ui/src/views/system/user/index.vue @@ -175,21 +175,19 @@ @click="handleUpdate(scope.row)" v-hasPermi="['system:user:edit']" >修改 - 删除 - 重置 + + + 更多操作 + + + 删除用户 + 重置密码 + 分配角色 + + @@ -561,6 +559,22 @@ export default { this.single = selection.length != 1; this.multiple = !selection.length; }, + // 更多操作触发 + handleCommand(command, row) { + switch (command) { + case "handleDelete": + this.handleDelete(row); + break; + case "handleResetPwd": + this.handleResetPwd(row); + break; + case "handleAuthRole": + this.handleAuthRole(row); + break; + default: + break; + } + }, /** 新增按钮操作 */ handleAdd() { this.reset(); @@ -603,6 +617,11 @@ export default { }); }).catch(() => {}); }, + /** 分配角色操作 */ + handleAuthRole: function(row) { + const userId = row.userId; + this.$router.push("/auth/role/" + userId); + }, /** 提交按钮 */ submitForm: function() { this.$refs["form"].validate(valid => { From 2d8f380b718d657c6e08aae06e909e5e544152ad 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, 2 Jul 2021 09:39:07 +0800 Subject: [PATCH 17/62] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0MP=E6=B3=A8=E5=85=A5=E5=BC=82=E5=B8=B8=E6=8B=A6?= =?UTF-8?q?=E6=88=AA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CreateAndUpdateMetaObjectHandler.java | 41 ++++++++++++------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/mybatisplus/CreateAndUpdateMetaObjectHandler.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/mybatisplus/CreateAndUpdateMetaObjectHandler.java index 4797a64b..2479293e 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/mybatisplus/CreateAndUpdateMetaObjectHandler.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/mybatisplus/CreateAndUpdateMetaObjectHandler.java @@ -1,6 +1,8 @@ package com.ruoyi.framework.mybatisplus; +import cn.hutool.http.HttpStatus; import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; +import com.ruoyi.common.exception.CustomException; import com.ruoyi.common.utils.SecurityUtils; import org.apache.ibatis.reflection.MetaObject; @@ -8,6 +10,7 @@ import java.util.Date; /** * MP注入处理器 + * * @author Lion Li * @date 2021/4/25 */ @@ -15,30 +18,38 @@ public class CreateAndUpdateMetaObjectHandler implements MetaObjectHandler { @Override public void insertFill(MetaObject metaObject) { - //根据属性名字设置要填充的值 - if (metaObject.hasGetter("createTime")) { - if (metaObject.getValue("createTime") == null) { - this.setFieldValByName("createTime", new Date(), metaObject); + try { + //根据属性名字设置要填充的值 + if (metaObject.hasGetter("createTime")) { + if (metaObject.getValue("createTime") == null) { + this.setFieldValByName("createTime", new Date(), metaObject); + } } - } - if (metaObject.hasGetter("createBy")) { - if (metaObject.getValue("createBy") == null) { - this.setFieldValByName("createBy", SecurityUtils.getUsername(), metaObject); + if (metaObject.hasGetter("createBy")) { + if (metaObject.getValue("createBy") == null) { + this.setFieldValByName("createBy", SecurityUtils.getUsername(), metaObject); + } } + } catch (Exception e) { + throw new CustomException("自动注入异常 => " + e.getMessage(), HttpStatus.HTTP_UNAUTHORIZED); } } @Override public void updateFill(MetaObject metaObject) { - if (metaObject.hasGetter("updateBy")) { - if (metaObject.getValue("updateBy") == null) { - this.setFieldValByName("updateBy", SecurityUtils.getUsername(), metaObject); + try { + if (metaObject.hasGetter("updateBy")) { + if (metaObject.getValue("updateBy") == null) { + this.setFieldValByName("updateBy", SecurityUtils.getUsername(), metaObject); + } } - } - if (metaObject.hasGetter("updateTime")) { - if (metaObject.getValue("updateTime") == null) { - this.setFieldValByName("updateTime", new Date(), metaObject); + if (metaObject.hasGetter("updateTime")) { + if (metaObject.getValue("updateTime") == null) { + this.setFieldValByName("updateTime", new Date(), metaObject); + } } + } catch (Exception e) { + throw new CustomException("自动注入异常 => " + e.getMessage(), HttpStatus.HTTP_UNAUTHORIZED); } } From b9128b60740617effeb2ea06b8bacfbbe62ded3e 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, 3 Jul 2021 23:52:39 +0800 Subject: [PATCH 18/62] =?UTF-8?q?update=20=E4=BE=9D=E8=B5=96=E5=8D=87?= =?UTF-8?q?=E7=BA=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 538b4267..cf20fa51 100644 --- a/pom.xml +++ b/pom.xml @@ -20,16 +20,16 @@ 1.8 3.1.1 1.2.6 - 3.0.2 + 3.0.3 4.1.2 1.7 0.9.1 3.4.3 - 5.7.2 + 5.7.3 3.0.3 11.0 - 2.4.1 - 3.15.2 + 2.4.3 + 3.16.0 2.2.1 3.4.0 From c26073afeb59ff898bb46a59031728fb99985a32 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, 4 Jul 2021 02:13:24 +0800 Subject: [PATCH 19/62] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=E7=BC=93?= =?UTF-8?q?=E5=AD=98=E9=85=8D=E7=BD=AE=20=E5=A2=9E=E5=8A=A0spring-cache?= =?UTF-8?q?=E6=BC=94=E7=A4=BA=E6=A1=88=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/application.yml | 15 ++++ .../demo/controller/RedisCacheController.java | 70 +++++++++++++++++++ .../ruoyi/framework/config/RedisConfig.java | 8 ++- .../config/properties/RedissonProperties.java | 34 ++++++++- 4 files changed, 125 insertions(+), 2 deletions(-) create mode 100644 ruoyi-demo/src/main/java/com/ruoyi/demo/controller/RedisCacheController.java diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml index 9fec4ae7..1d3415eb 100644 --- a/ruoyi-admin/src/main/resources/application.yml +++ b/ruoyi-admin/src/main/resources/application.yml @@ -262,6 +262,21 @@ feign: circuitbreaker: enabled: true +--- # redisson 缓存配置 +redisson: + cacheGroup: + # 用例: @Cacheable(cacheNames="groupId", key="#XXX") 方可使用缓存组配置 + - groupId: redissonCacheMap + # 组过期时间(脚本监控) + ttl: 60000 + # 组最大空闲时间(脚本监控) + maxIdleTime: 60000 + # 组最大长度 + maxSize: 0 + - groupId: testCache + ttl: 1000 + maxIdleTime: 500 + --- # 分布式锁 lock4j 全局配置 lock4j: # 获取分布式锁超时时间,默认为 3000 毫秒 diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/RedisCacheController.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/RedisCacheController.java new file mode 100644 index 00000000..4588f138 --- /dev/null +++ b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/RedisCacheController.java @@ -0,0 +1,70 @@ +package com.ruoyi.demo.controller; + +import com.ruoyi.common.core.domain.AjaxResult; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.CachePut; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * spring-cache 演示案例 + * + * @author Lion Li + */ +// 类级别 缓存统一配置 +//@CacheConfig(cacheNames = "redissonCacheMap") +@RequiredArgsConstructor(onConstructor_ = @Autowired) +@RestController +@RequestMapping("/demo/cache") +public class RedisCacheController { + + /** + * 测试 @Cacheable + * + * 表示这个方法有了缓存的功能,方法的返回值会被缓存下来 + * 下一次调用该方法前,会去检查是否缓存中已经有值 + * 如果有就直接返回,不调用方法 + * 如果没有,就调用方法,然后把结果缓存起来 + * 这个注解「一般用在查询方法上」 + * + * cacheNames 为配置文件内 groupId + */ + @Cacheable(cacheNames = "redissonCacheMap", key = "#key", condition = "#key != null") + @GetMapping("/test1") + public AjaxResult test1(String key, String value){ + return AjaxResult.success("操作成功", value); + } + + /** + * 测试 @CachePut + * + * 加了@CachePut注解的方法,会把方法的返回值put到缓存里面缓存起来,供其它地方使用 + * 它「通常用在新增方法上」 + * + * cacheNames 为 配置文件内 groupId + */ + @CachePut(cacheNames = "redissonCacheMap", key = "#key", condition = "#key != null") + @GetMapping("/test2") + public AjaxResult test2(String key, String value){ + return AjaxResult.success("操作成功", value); + } + + /** + * 测试 @CacheEvict + * + * 使用了CacheEvict注解的方法,会清空指定缓存 + * 「一般用在更新或者删除的方法上」 + * + * cacheNames 为 配置文件内 groupId + */ + @CacheEvict(cacheNames = "redissonCacheMap", key = "#key", condition = "#key != null") + @GetMapping("/test3") + public AjaxResult test3(String key, String value){ + return AjaxResult.success("操作成功", value); + } + +} 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 95c7572f..bc286574 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 @@ -19,6 +19,7 @@ import org.springframework.context.annotation.Configuration; import java.io.IOException; import java.util.HashMap; +import java.util.List; import java.util.Map; /** @@ -78,8 +79,13 @@ public class RedisConfig extends CachingConfigurerSupport { */ @Bean public CacheManager cacheManager(RedissonClient redissonClient) { + List cacheGroup = redissonProperties.getCacheGroup(); Map config = new HashMap<>(); - config.put("redissonCacheMap", new CacheConfig(30*60*1000, 10*60*1000)); + for (RedissonProperties.CacheGroup group : cacheGroup) { + CacheConfig cacheConfig = new CacheConfig(group.getTtl(), group.getMaxIdleTime()); + cacheConfig.setMaxSize(group.getMaxSize()); + config.put(group.getGroupId(), cacheConfig); + } return new RedissonSpringCacheManager(redissonClient, config, JsonJacksonCodec.INSTANCE); } diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/RedissonProperties.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/RedissonProperties.java index 99db89ef..b6e289d8 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/RedissonProperties.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/RedissonProperties.java @@ -2,11 +2,12 @@ package com.ruoyi.framework.config.properties; import lombok.Data; import lombok.NoArgsConstructor; -import org.redisson.client.codec.Codec; import org.redisson.config.TransportMode; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; +import java.util.List; + /** * Redisson 配置属性 * @@ -37,6 +38,11 @@ public class RedissonProperties { */ private SingleServerConfig singleServerConfig; + /** + * 缓存组 + */ + private List cacheGroup; + @Data @NoArgsConstructor public static class SingleServerConfig { @@ -98,4 +104,30 @@ public class RedissonProperties { } + @Data + @NoArgsConstructor + public static class CacheGroup { + + /** + * 组id + */ + private String groupId; + + /** + * 组过期时间 + */ + private long ttl; + + /** + * 组最大空闲时间 + */ + private long maxIdleTime; + + /** + * 组最大长度 + */ + private int maxSize; + + } + } From de194880ae912fcf46123f278529dbeaa3754c6f 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, 4 Jul 2021 02:21:04 +0800 Subject: [PATCH 20/62] =?UTF-8?q?update=20=E5=85=B3=E9=97=AD=E9=BB=98?= =?UTF-8?q?=E8=AE=A4=E4=BA=8C=E7=BA=A7=E7=BC=93=E5=AD=98=20=E6=8E=A8?= =?UTF-8?q?=E8=8D=90=E4=BD=BF=E7=94=A8=20spring-cache=20=E6=B3=A8=E8=A7=A3?= =?UTF-8?q?=E6=89=8B=E5=8A=A8=E7=BC=93=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ruoyi-admin/src/main/resources/application.yml | 2 +- .../common/core/mybatisplus/cache/MybatisPlusRedisCache.java | 3 +++ ruoyi-generator/src/main/resources/vm/java/mapper.java.vm | 2 -- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml index 1d3415eb..4d48a976 100644 --- a/ruoyi-admin/src/main/resources/application.yml +++ b/ruoyi-admin/src/main/resources/application.yml @@ -158,7 +158,7 @@ mybatis-plus: # STATEMENT 关闭一级缓存 localCacheScope: SESSION # 开启Mybatis二级缓存,默认为 true - cacheEnabled: true + cacheEnabled: false # 更详细的日志输出 会有性能损耗 # logImpl: org.apache.ibatis.logging.stdout.StdOutImpl global-config: diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/mybatisplus/cache/MybatisPlusRedisCache.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/mybatisplus/cache/MybatisPlusRedisCache.java index 0e21d70e..633a0b5a 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/core/mybatisplus/cache/MybatisPlusRedisCache.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/mybatisplus/cache/MybatisPlusRedisCache.java @@ -15,6 +15,9 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; /** * mybatis-redis 二级缓存 * + * 使用方法 配置文件开启 mybatis-plus 二级缓存 + * 在 XxxMapper.java 类上添加注解 @CacheNamespace(implementation = MybatisPlusRedisCache.class, eviction = MybatisPlusRedisCache.class) + * * @author Lion Li */ @Slf4j diff --git a/ruoyi-generator/src/main/resources/vm/java/mapper.java.vm b/ruoyi-generator/src/main/resources/vm/java/mapper.java.vm index 6d4f40fb..6f8ff7b9 100644 --- a/ruoyi-generator/src/main/resources/vm/java/mapper.java.vm +++ b/ruoyi-generator/src/main/resources/vm/java/mapper.java.vm @@ -11,8 +11,6 @@ import org.apache.ibatis.annotations.CacheNamespace; * @author ${author} * @date ${datetime} */ -// 如使需切换数据源 请勿使用缓存 会造成数据不一致现象 -@CacheNamespace(implementation = MybatisPlusRedisCache.class, eviction = MybatisPlusRedisCache.class) public interface ${ClassName}Mapper extends BaseMapperPlus<${ClassName}> { } From 99051916eb16183a6e7f994758f131a99d83efad 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, 4 Jul 2021 13:24:19 +0800 Subject: [PATCH 21/62] =?UTF-8?q?update=20=E5=8D=87=E7=BA=A7=20springboot?= =?UTF-8?q?=202.4.8?= 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 cf20fa51..10a35d2c 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ 2.4.0 - 2.4.7 + 2.4.8 UTF-8 UTF-8 1.8 From 2704e921c80baf212e74ddbf75a87c47e8a2679e 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, 4 Jul 2021 19:18:06 +0800 Subject: [PATCH 22/62] =?UTF-8?q?update=20=E5=A2=9E=E5=8A=A0=20feign=20?= =?UTF-8?q?=E7=86=94=E6=96=AD=20=E8=87=AA=E5=AE=9A=E4=B9=89=E7=BB=93?= =?UTF-8?q?=E6=9E=84=E4=BD=93=E8=A7=A3=E6=9E=90=E6=96=B9=E6=B3=95=20?= =?UTF-8?q?=E4=B8=8E=20demo=20=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../feign/fallback/FeignTestFallback.java | 3 ++ .../ruoyi/framework/config/FeignConfig.java | 36 +++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/feign/fallback/FeignTestFallback.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/feign/fallback/FeignTestFallback.java index 3b4dfd0c..0f9e4002 100644 --- a/ruoyi-demo/src/main/java/com/ruoyi/demo/feign/fallback/FeignTestFallback.java +++ b/ruoyi-demo/src/main/java/com/ruoyi/demo/feign/fallback/FeignTestFallback.java @@ -7,7 +7,10 @@ import org.springframework.stereotype.Component; /** * feign测试fallback + * 自定义封装结构体熔断 + * 需重写解码器 根据自定义实体 自行解析熔断 * + * @see {com.ruoyi.framework.config.FeignConfig#errorDecoder()} * @author Lion Li */ @Slf4j diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/FeignConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/FeignConfig.java index f10769bc..14db1c95 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/FeignConfig.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/FeignConfig.java @@ -54,4 +54,40 @@ public class FeignConfig { return new Retryer.Default(); } +// /** +// * 自定义异常解码器 +// * 用于自定义返回体异常熔断 +// */ +// @Bean +// public ErrorDecoder errorDecoder() { +// return new CustomErrorDecoder(); +// } +// +// +// /** +// * 自定义返回体解码器 +// */ +// @Slf4j +// public static class CustomErrorDecoder implements ErrorDecoder { +// +// @Override +// public Exception decode(String methodKey, Response response) { +// Exception exception = null; +// try { +// // 获取原始的返回内容 +// String json = JsonUtils.toJsonString(response.body().asReader(StandardCharsets.UTF_8)); +// exception = new RuntimeException(json); +// // 将返回内容反序列化为Result,这里应根据自身项目作修改 +// AjaxResult result = JsonUtils.parseObject(json, AjaxResult.class); +// // 业务异常抛出简单的 RuntimeException,保留原来错误信息 +// if (result.getCode() != 200) { +// exception = new RuntimeException(result.getMsg()); +// } +// } catch (IOException e) { +// log.error(e.getMessage(), e); +// } +// return exception; +// } +// } + } From dfb4d9f04947cbfb2bf966e80f088f2d9cd989b0 Mon Sep 17 00:00:00 2001 From: Nguyendream <728115857@qq.com> Date: Mon, 5 Jul 2021 00:39:29 +0000 Subject: [PATCH 23/62] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20=E6=8C=89=E9=92=AElo?= =?UTF-8?q?ading=E5=8D=A1=E6=AD=BB=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/resources/vm/vue/index-tree.vue.vm | 10 ++++++---- ruoyi-generator/src/main/resources/vm/vue/index.vue.vm | 10 ++++++---- 2 files changed, 12 insertions(+), 8 deletions(-) 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 d43c2ce2..de04567f 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 @@ -300,8 +300,8 @@ export default { }, data() { return { - //按钮loading - buttonLoading: false, + // 按钮loading + buttonLoading: false, // 遮罩层 loading: true, // 显示搜索条件 @@ -510,17 +510,19 @@ 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(); + }).finally(() => { + this.buttonLoading = false; }); } else { add${BusinessName}(this.form).then(response => { - this.buttonLoading = false; this.msgSuccess("新增成功"); this.open = false; this.getList(); + }).finally(() => { + this.buttonLoading = false; }); } } 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 abc799e2..12bb288d 100644 --- a/ruoyi-generator/src/main/resources/vm/vue/index.vue.vm +++ b/ruoyi-generator/src/main/resources/vm/vue/index.vue.vm @@ -351,8 +351,8 @@ export default { }, data() { return { - //按钮loading - buttonLoading: false, + // 按钮loading + buttonLoading: false, // 遮罩层 loading: true, // 导出遮罩层 @@ -567,17 +567,19 @@ 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(); + }).finally(() => { + this.buttonLoading = false; }); } else { add${BusinessName}(this.form).then(response => { - this.buttonLoading = false; this.msgSuccess("新增成功"); this.open = false; this.getList(); + }).finally(() => { + this.buttonLoading = false; }); } } From ce6bea4ba0660495eb8e72d4bb883a673d05bd3a Mon Sep 17 00:00:00 2001 From: RuoYi Date: Mon, 5 Jul 2021 09:57:15 +0800 Subject: [PATCH 24/62] =?UTF-8?q?=E9=99=90=E5=88=B6=E8=B6=85=E7=BA=A7?= =?UTF-8?q?=E7=AE=A1=E7=90=86=E5=91=98=E4=B8=8D=E5=85=81=E8=AE=B8=E6=93=8D?= =?UTF-8?q?=E4=BD=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ruoyi-ui/src/views/system/role/index.vue | 2 +- ruoyi-ui/src/views/system/user/index.vue | 16 +++++++++------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/ruoyi-ui/src/views/system/role/index.vue b/ruoyi-ui/src/views/system/role/index.vue index 8f0d4333..70c1dc4b 100644 --- a/ruoyi-ui/src/views/system/role/index.vue +++ b/ruoyi-ui/src/views/system/role/index.vue @@ -124,7 +124,7 @@ -