zhao.renji hai 1 mes
pai
achega
68d0fcf2f3
Modificáronse 100 ficheiros con 12439 adicións e 0 borrados
  1. 19 0
      .gitignore
  2. 21 0
      LICENSE
  3. 70 0
      doc/垃圾代码.txt
  4. 51 0
      docker-compose-server.yml
  5. 42 0
      docker-compose.yml
  6. 21 0
      jeecg-boot-base/jeecg-boot-base-api/jeecg-system-cloud-api/pom.xml
  7. 427 0
      jeecg-boot-base/jeecg-boot-base-api/jeecg-system-cloud-api/src/main/java/org/jeecg/common/system/api/ISysBaseAPI.java
  8. 17 0
      jeecg-boot-base/jeecg-boot-base-api/jeecg-system-cloud-api/src/main/java/org/jeecg/common/system/api/factory/SysBaseAPIFallbackFactory.java
  9. 272 0
      jeecg-boot-base/jeecg-boot-base-api/jeecg-system-cloud-api/src/main/java/org/jeecg/common/system/api/fallback/SysBaseAPIFallback.java
  10. 156 0
      jeecg-boot-base/jeecg-boot-base-api/jeecg-system-cloud-api/src/main/java/org/jeecg/config/FeignConfig.java
  11. 14 0
      jeecg-boot-base/jeecg-boot-base-api/jeecg-system-local-api/pom.xml
  12. 98 0
      jeecg-boot-base/jeecg-boot-base-api/jeecg-system-local-api/src/main/java/jtznyj/common/api/ICommonApi.java
  13. 46 0
      jeecg-boot-base/jeecg-boot-base-api/jeecg-system-local-api/src/main/java/jtznyj/common/api/vo/AFocusWarn.java
  14. 35 0
      jeecg-boot-base/jeecg-boot-base-api/jeecg-system-local-api/src/main/java/jtznyj/engineer/api/IEngineerApi.java
  15. 23 0
      jeecg-boot-base/jeecg-boot-base-api/jeecg-system-local-api/src/main/java/jtznyj/engineer/dto/WarnItemDto.java
  16. 1124 0
      jeecg-boot-base/jeecg-boot-base-api/jeecg-system-local-api/src/main/java/jtznyj/engineer/vo/LtdRecord.java
  17. 292 0
      jeecg-boot-base/jeecg-boot-base-api/jeecg-system-local-api/src/main/java/org/jeecg/common/system/api/ISysBaseAPI.java
  18. 26 0
      jeecg-boot-base/jeecg-boot-base-api/pom.xml
  19. 243 0
      jeecg-boot-base/jeecg-boot-base-core/pom.xml
  20. 97 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/api/CommonAPI.java
  21. 24 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/api/IWpsBaseAPI.java
  22. 47 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/api/desform/ISysTranslateAPI.java
  23. 30 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/api/dto/FileDownDTO.java
  24. 55 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/api/dto/FileUploadDTO.java
  25. 68 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/api/dto/LogDTO.java
  26. 41 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/api/dto/OnlineAuthDTO.java
  27. 43 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/api/dto/message/BusMessageDTO.java
  28. 45 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/api/dto/message/BusTemplateMessageDTO.java
  29. 74 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/api/dto/message/MessageDTO.java
  30. 37 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/api/dto/message/TemplateDTO.java
  31. 48 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/api/dto/message/TemplateMessageDTO.java
  32. 107 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/api/vo/OaWpsModel.java
  33. 153 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/api/vo/Result.java
  34. 270 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/aspect/AutoLogAspect.java
  35. 188 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/aspect/DictAspect.java
  36. 119 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/aspect/PermissionDataAspect.java
  37. 58 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/aspect/UrlMatchEnum.java
  38. 46 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/aspect/annotation/AutoLog.java
  39. 42 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/aspect/annotation/Dict.java
  40. 18 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/aspect/annotation/OnlineAuth.java
  41. 29 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/aspect/annotation/PermissionData.java
  42. 330 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/constant/CommonConstant.java
  43. 26 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/constant/CommonSendStatus.java
  44. 130 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/constant/DataBaseConstant.java
  45. 25 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/constant/FillRuleConstant.java
  46. 131 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/constant/ProvinceCityArea.java
  47. 38 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/constant/ServiceNameConstants.java
  48. 30 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/constant/VXESocketConst.java
  49. 61 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/constant/WebsocketConst.java
  50. 150 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/constant/enums/CgformEnum.java
  51. 17 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/constant/enums/ModuleType.java
  52. 515 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/es/JeecgElasticsearchTemplate.java
  53. 98 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/es/QueryStringBuilder.java
  54. 19 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/exception/JeecgBootException.java
  55. 106 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/exception/JeecgBootExceptionHandler.java
  56. 21 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/handler/IFillRuleHandler.java
  57. 194 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/system/base/controller/JeecgController.java
  58. 52 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/system/base/entity/JeecgEntity.java
  59. 12 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/system/base/service/JeecgService.java
  60. 19 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/system/base/service/impl/JeecgServiceImpl.java
  61. 43 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/system/query/MatchTypeEnum.java
  62. 55 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/system/query/QueryCondition.java
  63. 1097 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/system/query/QueryGenerator.java
  64. 73 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/system/query/QueryRuleEnum.java
  65. 104 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/system/util/JeecgDataAutorUtils.java
  66. 233 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/system/util/JwtUtil.java
  67. 36 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/system/vo/ComboModel.java
  68. 43 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/system/vo/DictModel.java
  69. 34 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/system/vo/DictQuery.java
  70. 52 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/system/vo/DynamicDataSourceModel.java
  71. 127 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/system/vo/LoginUser.java
  72. 52 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/system/vo/SysCategoryModel.java
  73. 147 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/system/vo/SysDepartModel.java
  74. 151 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/system/vo/SysPermissionDataRuleModel.java
  75. 67 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/system/vo/SysUserCacheInfo.java
  76. 10 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/BrowserType.java
  77. 206 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/BrowserUtils.java
  78. 215 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/CommonUtils.java
  79. 654 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/DateUtils.java
  80. 70 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/DySmsEnum.java
  81. 122 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/DySmsHelper.java
  82. 57 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/FillRuleUtil.java
  83. 29 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/HTMLUtils.java
  84. 58 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/IPUtils.java
  85. 96 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/ImportExcelUtil.java
  86. 43 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/MD5Util.java
  87. 213 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/MinioUtil.java
  88. 92 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/MyClassLoader.java
  89. 180 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/PasswordUtil.java
  90. 84 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/PathMatcherUtil.java
  91. 61 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/PmsUtil.java
  92. 248 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/ReflectHelper.java
  93. 121 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/RestDesformUtil.java
  94. 257 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/RestUtil.java
  95. 94 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/SpringContextUtils.java
  96. 139 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/SqlInjectionUtil.java
  97. 70 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/SysAnnmentTypeEnum.java
  98. 128 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/TokenUtils.java
  99. 95 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/UUIDGenerator.java
  100. 173 0
      jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/YouBianCodeUtil.java

+ 19 - 0
.gitignore

@@ -0,0 +1,19 @@
+/jeecg-boot-base/jeecg-boot-base-tools/target
+/jeecg-boot-base/jeecg-boot-base-core/target
+/jeecg-boot-base/jeecg-boot-base-api/jeecg-system-local-api/target
+/jeecg-boot-base/jeecg-boot-base-api/jeecg-system-cloud-api/target
+/jeecg-boot-module-system/target
+/.idea
+/jeecg-boot-base/jeecg-boot-base-api/*.iml
+/jeecg-boot-base/jeecg-boot-base-api/jeecg-system-cloud-api/*.iml
+/jeecg-boot-base/jeecg-boot-base-api/jeecg-system-local-api/*.iml
+/jeecg-boot-base/jeecg-boot-base-core/*.iml
+/jeecg-boot-base/jeecg-boot-base-tools/*.iml
+/jeecg-boot-base/*.iml
+/jeecg-boot-module-system/*.iml
+/*.iml
+/module-engineer/target
+/jeecg-boot-module-system/src/main/resources/static/generic/
+/jeecg-boot-module-system/src/main/resources/static/js/
+/jeecg-boot-module-system/src/main/resources/static/view/
+/jeecg-boot-module-system/src/main/resources/static/demo1.html

+ 21 - 0
LICENSE

@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2019 jeecg-boot
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.

+ 70 - 0
doc/垃圾代码.txt

@@ -0,0 +1,70 @@
+
+org.jeecg.modules.dataVue.task.FocusWarnJob
+
+    //复杂情况
+    private void getCassByJs(String jh, String distance,String js){
+
+        BigDecimal jsNum=new BigDecimal(js);
+        String warnHisSql="select * from (select * from A_FOCUS_WARN where JH='%s' and SOURCE='临井复杂' order by WARN_TIME desc) where rownum=1";
+        warnHisSql=String.format(warnHisSql,jh);
+        List<Map<String, Object>> warnHisList= iaFocusWarnService.querySql(warnHisSql,null);
+        if(warnHisList.size()>0){
+            BigDecimal dsjsHis=new BigDecimal(warnHisList.get(0).get("DSJS").toString());
+            if((dsjsHis.subtract(jsNum)).compareTo(new BigDecimal("1"))==-1&&(dsjsHis.subtract(jsNum)).compareTo(new BigDecimal("-1"))==1){
+                return;
+            }
+        }
+        long startTime = System.currentTimeMillis();
+        String sql = " select  xzb x, yzb y  "
+                + " from v_scdt_jwxx t " +
+                " where xzb is not null and yzb is not null "
+                + String.format(" and jh = '%s' ", jh);
+        List<Map<String, Object>> data = iLjrbService.querySql(sql, null);
+        if (data.size() == 0) {
+            sql = " select t2.sjjwzzbx x, t2.SJJWZZBY y from mv_azj01 t2 " +
+                    " where sjjwzzbx is not null and sjjwzzby is not null "
+                    + String.format(" and jh = '%s' ", jh);
+            data = iZjfzService.querySql(sql, null);
+        }
+        String[] x = new String[2];
+        if (data.size() > 0) {
+            x[0] = data.get(0).get("X").toString();
+            x[1] = data.get(0).get("Y").toString();
+        }
+
+        if (data.size() == 0) {
+            return;
+        }
+        String zzbX = x[0]; // 4xxxxxx
+        String hzbY = x[1]; // 2yyyyyyyy
+        sql = "select t1.ID,t1.JH, SGXH, SGMC, DSJS, t3.name as caselevel, t2.sjjwzzbx, t2.sjjwhzby\n" +
+                "                      from jsra t1\n" +
+                "                      left join jjbxx t2\n" +
+                "                        on t2.jh = t1.jh\n" +
+                "                      left join Text_cl t3\n" +
+                "                        on t3.id = t1.sgdjbh\n" +
+                "                     where sglbid is not null\n" +
+                "                       and sqrt(power((t2.sjjwzzbx - %s), 2) +\n" +
+                "                                power((t2.sjjwhzby - %s), 2)) < %s\n" +
+                "                     order by t1.dsjs ";
+        sql = String.format(sql, zzbX, hzbY, distance);
+        List<Map<String, Object>> list = iZjfzService.querySql(sql, null);
+        List<AFocusWarn> warnList=new ArrayList<>();
+
+        for(Map<String,Object> itemMap:list){
+            BigDecimal dsjs=new BigDecimal(itemMap.get("DSJS").toString());
+           if((dsjs.subtract(jsNum)).compareTo(new BigDecimal("1"))==-1&&(dsjs.subtract(jsNum)).compareTo(new BigDecimal("-1"))==1){
+               AFocusWarn record=new AFocusWarn();
+               record.setSource("邻井复杂");
+               record.setJh(jh);
+               record.setCatogary(itemMap.get("SGMC").toString());
+               record.setWarnTime(new Date());
+               record.setBjnr(itemMap.get("FSJGJYY").toString());
+               record.setServercost(System.currentTimeMillis() - startTime);
+               record.setDsjs(itemMap.get("DSJS").toString());
+               record.setKey(jh+jh);
+               warnList.add(record);
+           }
+        }
+        iaFocusWarnService.saveBatch(warnList);
+    }

+ 51 - 0
docker-compose-server.yml

@@ -0,0 +1,51 @@
+#### 镜像上传
+# 仓库私服: 81.70.17.111:5000
+# 第一步:上传镜像到docker仓库
+#docker tag jeecg-boot-mysql 81.70.17.111:5000/jeecg-boot-mysql:1.1
+#docker tag jeecg-boot-system 81.70.17.111:5000/jeecg-boot-system:1.0
+#docker tag nginxhtml:jeecgboot 81.70.17.111:5000/nginxhtml:1.2
+
+#docker push 81.70.17.111:5000/jeecg-boot-mysql:1.1
+#docker push 81.70.17.111:5000/jeecg-boot-system:1.0
+#docker push 81.70.17.111:5000/nginxhtml:1.2
+
+# 第二步:将此yml文件上传服务器,执行启动命令 docker-compose -f ./docker-compose-server.yml up
+version: '2'
+services:
+  jeecg-boot-mysql:
+    image: 81.70.17.111:5000/jeecg-boot-mysql:1.0
+    environment:
+      MYSQL_ROOT_PASSWORD: root
+    restart: always
+    container_name: jeecg-boot-mysql
+    command:
+      --character-set-server=utf8mb4
+      --collation-server=utf8mb4_general_ci
+      --explicit_defaults_for_timestamp=true
+      --lower_case_table_names=1
+      --max_allowed_packet=128M
+    ports:
+      - 3306:3306
+
+  jeecg-boot-redis:
+    image: redis:5.0
+    ports:
+      - 6379:6379
+    restart: always
+    container_name: jeecg-boot-redis
+
+  jeecg-boot-system:
+    image: 81.70.17.111:5000/jeecg-boot-system:1.0
+    restart: always
+    container_name: jeecg-boot-system
+    volumes:
+      - /data/config:/jeecg-boot/config
+    ports:
+      - 8080:8080
+
+  jeecg-boot-nginx:
+    image: 81.70.17.111:5000/nginxhtml
+    restart: always
+    container_name: jeecg-boot-nginx
+    ports:
+      - 80:80

+ 42 - 0
docker-compose.yml

@@ -0,0 +1,42 @@
+version: '2'
+services:
+  jeecg-boot-mysql:
+    build:
+      context: ./db
+    environment:
+      MYSQL_ROOT_PASSWORD: root
+      MYSQL_ROOT_HOST: '%'
+      TZ: Asia/Shanghai
+    restart: always
+    container_name: jeecg-boot-mysql
+    image: jeecg-boot-mysql
+    command:
+      --character-set-server=utf8mb4
+      --collation-server=utf8mb4_general_ci
+      --explicit_defaults_for_timestamp=true
+      --lower_case_table_names=1
+      --max_allowed_packet=128M
+      --default-authentication-plugin=caching_sha2_password
+    ports:
+      - 3306:3306
+
+  jeecg-boot-redis:
+    image: redis:5.0
+    ports:
+      - 6379:6379
+    restart: always
+    hostname: jeecg-boot-redis
+    container_name: jeecg-boot-redis
+
+  jeecg-boot-system:
+    build:
+      context: ./jeecg-boot-module-system
+    restart: on-failure
+    depends_on:
+      - jeecg-boot-mysql
+      - jeecg-boot-redis
+    container_name: jeecg-boot-system
+    image: jeecg-boot-system
+    hostname: jeecg-boot-system
+    ports:
+      - 8080:8080

+ 21 - 0
jeecg-boot-base/jeecg-boot-base-api/jeecg-system-cloud-api/pom.xml

@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>jeecg-boot-base-api</artifactId>
+        <groupId>org.jeecgframework.boot</groupId>
+        <version>2.4.5</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>jeecg-system-cloud-api</artifactId>
+
+    <dependencies>
+        <!-- feign -->
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-openfeign</artifactId>
+        </dependency>
+    </dependencies>
+</project>

+ 427 - 0
jeecg-boot-base/jeecg-boot-base-api/jeecg-system-cloud-api/src/main/java/org/jeecg/common/system/api/ISysBaseAPI.java

@@ -0,0 +1,427 @@
+package org.jeecg.common.system.api;
+
+import com.alibaba.fastjson.JSONObject;
+import org.jeecg.common.api.CommonAPI;
+import org.jeecg.common.api.dto.OnlineAuthDTO;
+import org.jeecg.common.api.dto.message.*;
+import org.jeecg.common.constant.ServiceNameConstants;
+import org.jeecg.common.system.api.factory.SysBaseAPIFallbackFactory;
+import org.jeecg.common.system.vo.*;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.stereotype.Component;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * 相比较local版
+ * 去掉了一些方法:
+ * addLog getDatabaseType queryAllDepart
+ * queryAllUser(Wrapper wrapper) queryAllUser(String[] userIds, int pageNo, int pageSize)
+ * 修改了一些方法:
+ * createLog
+ * sendSysAnnouncement 只保留了一个,其余全部干掉
+ *
+ * cloud接口数量43  local:35 common:9  额外一个特殊queryAllRole一个当两个用
+ */
+@Component
+@FeignClient(contextId = "sysBaseRemoteApi", value = ServiceNameConstants.SYSTEM_SERVICE, fallbackFactory = SysBaseAPIFallbackFactory.class)
+public interface ISysBaseAPI extends CommonAPI {
+
+    /**
+     * 1发送系统消息
+     * @param message 使用构造器赋值参数 如果不设置category(消息类型)则默认为2 发送系统消息
+     */
+    @PostMapping("/sys/api/sendSysAnnouncement")
+    void sendSysAnnouncement(@RequestBody MessageDTO message);
+
+    /**
+     * 2发送消息 附带业务参数
+     * @param message 使用构造器赋值参数
+     */
+    @PostMapping("/sys/api/sendBusAnnouncement")
+    void sendBusAnnouncement(@RequestBody BusMessageDTO message);
+
+    /**
+     * 3通过模板发送消息
+     * @param message 使用构造器赋值参数
+     */
+    @PostMapping("/sys/api/sendTemplateAnnouncement")
+    void sendTemplateAnnouncement(@RequestBody TemplateMessageDTO message);
+
+    /**
+     * 4通过模板发送消息 附带业务参数
+     * @param message 使用构造器赋值参数
+     */
+    @PostMapping("/sys/api/sendBusTemplateAnnouncement")
+    void sendBusTemplateAnnouncement(@RequestBody BusTemplateMessageDTO message);
+
+    /**
+     * 5通过消息中心模板,生成推送内容
+     * @param templateDTO 使用构造器赋值参数
+     * @return
+     */
+    @PostMapping("/sys/api/parseTemplateByCode")
+    String parseTemplateByCode(@RequestBody TemplateDTO templateDTO);
+
+    /**
+     * 6根据用户id查询用户信息
+     * @param id
+     * @return
+     */
+    @GetMapping("/sys/api/getUserById")
+    LoginUser getUserById(@RequestParam("id") String id);
+
+    /**
+     * 7通过用户账号查询角色集合
+     * @param username
+     * @return
+     */
+    @GetMapping("/sys/api/getRolesByUsername")
+    List<String> getRolesByUsername(@RequestParam("username") String username);
+
+    /**
+     * 8通过用户账号查询部门集合
+     * @param username
+     * @return 部门 id
+     */
+    @GetMapping("/sys/api/getDepartIdsByUsername")
+    List<String> getDepartIdsByUsername(@RequestParam("username") String username);
+
+    /**
+     * 9通过用户账号查询部门 name
+     * @param username
+     * @return 部门 name
+     */
+    @GetMapping("/sys/api/getDepartNamesByUsername")
+    List<String> getDepartNamesByUsername(@RequestParam("username") String username);
+
+    /**
+     * 10获取数据字典
+     * @param code
+     * @return
+     */
+    @GetMapping("/sys/api/queryDictItemsByCode")
+    List<DictModel> queryDictItemsByCode(@RequestParam("code") String code);
+
+    /** 11查询所有的父级字典,按照create_time排序 */
+    @GetMapping("/sys/api/queryAllDict")
+    List<DictModel> queryAllDict();
+
+    /**
+     * 12查询所有分类字典
+     * @return
+     */
+    @GetMapping("/sys/api/queryAllDSysCategory")
+    List<SysCategoryModel> queryAllDSysCategory();
+
+    /**
+     * 13获取表数据字典
+     * @param table
+     * @param text
+     * @param code
+     * @return
+     */
+    @GetMapping("/sys/api/queryTableDictItemsByCode")
+    List<DictModel> queryTableDictItemsByCode(@RequestParam("table") String table, @RequestParam("text") String text, @RequestParam("code") String code);
+
+    /**
+     * 14查询所有部门 作为字典信息 id -->value,departName -->text
+     * @return
+     */
+    @GetMapping("/sys/api/queryAllDepartBackDictModel")
+    List<DictModel> queryAllDepartBackDictModel();
+
+    /**
+     * 15根据业务类型 busType 及业务 busId 修改消息已读
+     */
+    @GetMapping("/sys/api/updateSysAnnounReadFlag")
+    public void updateSysAnnounReadFlag(@RequestParam("busType") String busType, @RequestParam("busId")String busId);
+
+    /**
+     * 16查询表字典 支持过滤数据
+     * @param table
+     * @param text
+     * @param code
+     * @param filterSql
+     * @return
+     */
+    @GetMapping("/sys/api/queryFilterTableDictInfo")
+    List<DictModel> queryFilterTableDictInfo(@RequestParam("table") String table, @RequestParam("text") String text, @RequestParam("code") String code, @RequestParam("filterSql") String filterSql);
+
+    /**
+     * 17查询指定table的 text code 获取字典,包含text和value
+     * @param table
+     * @param text
+     * @param code
+     * @param keyArray
+     * @return
+     */
+    @Deprecated
+    @GetMapping("/sys/api/queryTableDictByKeys")
+    public List<String> queryTableDictByKeys(@RequestParam("table") String table, @RequestParam("text") String text, @RequestParam("code") String code, @RequestParam("keyArray") String[] keyArray);
+
+    /**
+     * 18查询所有用户 返回ComboModel
+     * @return
+     */
+    @GetMapping("/sys/api/queryAllUserBackCombo")
+    public List<ComboModel> queryAllUserBackCombo();
+
+    /**
+     * 19分页查询用户 返回JSONObject
+     * @return
+     */
+    @GetMapping("/sys/api/queryAllUser")
+    public JSONObject queryAllUser(@RequestParam(name="userIds",required=false)String userIds, @RequestParam(name="pageNo",required=false) Integer pageNo,@RequestParam(name="pageSize",required=false) int pageSize);
+
+
+    /**
+     * 20获取所有角色 带参
+     * roleIds 默认选中角色
+     * @return
+     */
+    @GetMapping("/sys/api/queryAllRole")
+    public List<ComboModel> queryAllRole(@RequestParam(name = "roleIds",required = false)String[] roleIds);
+
+    /**
+     * 21通过用户账号查询角色Id集合
+     * @param username
+     * @return
+     */
+    @GetMapping("/sys/api/getRoleIdsByUsername")
+    public List<String> getRoleIdsByUsername(@RequestParam("username")String username);
+
+    /**
+     * 22通过部门编号查询部门id
+     * @param orgCode
+     * @return
+     */
+    @GetMapping("/sys/api/getDepartIdsByOrgCode")
+    public String getDepartIdsByOrgCode(@RequestParam("orgCode")String orgCode);
+
+    /**
+     * 23查询所有部门
+     * @return
+     */
+    @GetMapping("/sys/api/getAllSysDepart")
+    public List<SysDepartModel> getAllSysDepart();
+
+    /**
+     * 24查找父级部门
+     * @param departId
+     * @return
+     */
+    @GetMapping("/sys/api/getParentDepartId")
+    DictModel getParentDepartId(@RequestParam("departId")String departId);
+
+    /**
+     * 25根据部门Id获取部门负责人
+     * @param deptId
+     * @return
+     */
+    @GetMapping("/sys/api/getDeptHeadByDepId")
+    public List<String> getDeptHeadByDepId(@RequestParam("deptId") String deptId);
+
+    /**
+     * 26给指定用户发消息
+     * @param userIds
+     * @param cmd
+     */
+    @GetMapping("/sys/api/sendWebSocketMsg")
+    public void sendWebSocketMsg(@RequestParam("userIds")String[] userIds, @RequestParam("cmd") String cmd);
+
+    /**
+     * 27根据id获取所有参与用户
+     * userIds
+     * @return
+     */
+    @GetMapping("/sys/api/queryAllUserByIds")
+    public List<LoginUser> queryAllUserByIds(@RequestParam("userIds") String[] userIds);
+
+    /**
+     * 28将会议签到信息推动到预览
+     * userIds
+     * @return
+     * @param userId
+     */
+    @GetMapping("/sys/api/meetingSignWebsocket")
+    void meetingSignWebsocket(@RequestParam("userId")String userId);
+
+    /**
+     * 29根据name获取所有参与用户
+     * userNames
+     * @return
+     */
+    @GetMapping("/sys/api/queryUserByNames")
+    List<LoginUser> queryUserByNames(@RequestParam("userNames")String[] userNames);
+
+
+    /**
+     * 30获取用户的角色集合
+     * @param username
+     * @return
+     */
+    @GetMapping("/sys/api/getUserRoleSet")
+    Set<String> getUserRoleSet(@RequestParam("username")String username);
+
+    /**
+     * 31获取用户的权限集合
+     * @param username
+     * @return
+     */
+    @GetMapping("/sys/api/getUserPermissionSet")
+    Set<String> getUserPermissionSet(@RequestParam("username") String username);
+
+    /**
+     * 32判断是否有online访问的权限
+     * @param onlineAuthDTO
+     * @return
+     */
+    @PostMapping("/sys/api/hasOnlineAuth")
+    boolean hasOnlineAuth(@RequestBody OnlineAuthDTO onlineAuthDTO);
+
+    /**
+     * 33通过部门id获取部门全部信息
+     */
+    @GetMapping("/sys/api/selectAllById")
+    SysDepartModel selectAllById(@RequestParam("id") String id);
+
+    /**
+     * 34根据用户id查询用户所属公司下所有用户ids
+     * @param userId
+     * @return
+     */
+    @GetMapping("/sys/api/queryDeptUsersByUserId")
+    List<String> queryDeptUsersByUserId(@RequestParam("userId") String userId);
+
+
+    //---
+
+    /**
+     * 35查询用户角色信息
+     * @param username
+     * @return
+     */
+    @GetMapping("/sys/api/queryUserRoles")
+    Set<String> queryUserRoles(@RequestParam("username")String username);
+
+    /**
+     * 36查询用户权限信息
+     * @param username
+     * @return
+     */
+    @GetMapping("/sys/api/queryUserAuths")
+    Set<String> queryUserAuths(@RequestParam("username")String username);
+
+    /**
+     * 37根据 id 查询数据库中存储的 DynamicDataSourceModel
+     *
+     * @param dbSourceId
+     * @return
+     */
+    @GetMapping("/sys/api/getDynamicDbSourceById")
+    DynamicDataSourceModel getDynamicDbSourceById(@RequestParam("dbSourceId") String dbSourceId);
+
+    /**
+     * 38根据 code 查询数据库中存储的 DynamicDataSourceModel
+     *
+     * @param dbSourceCode
+     * @return
+     */
+    @GetMapping("/sys/api/getDynamicDbSourceByCode")
+    DynamicDataSourceModel getDynamicDbSourceByCode(@RequestParam("dbSourceCode") String dbSourceCode);
+
+    /**
+     * 39根据用户账号查询用户信息 CommonAPI中定义
+     * @param username
+     */
+    @GetMapping("/sys/api/getUserByName")
+    LoginUser getUserByName(@RequestParam("username") String username);
+
+    /**
+     * 40字典表的 翻译
+     * @param table
+     * @param text
+     * @param code
+     * @param key
+     * @return
+     */
+    @GetMapping("/sys/api/translateDictFromTable")
+    String translateDictFromTable(@RequestParam("table") String table, @RequestParam("text") String text, @RequestParam("code") String code, @RequestParam("key") String key);
+
+    /**
+     * 41普通字典的翻译
+     * @param code
+     * @param key
+     * @return
+     */
+    @GetMapping("/sys/api/translateDict")
+    String translateDict(@RequestParam("code") String code, @RequestParam("key") String key);
+
+    /**
+     * 42查询数据权限
+     * @return
+     */
+    @GetMapping("/sys/api/queryPermissionDataRule")
+    List<SysPermissionDataRuleModel> queryPermissionDataRule(@RequestParam("component") String component, @RequestParam("requestPath")String requestPath, @RequestParam("username") String username);
+
+    /**
+     * 43查询用户信息
+     * @param username
+     * @return
+     */
+    @GetMapping("/sys/api/getCacheUser")
+    SysUserCacheInfo getCacheUser(@RequestParam("username") String username);
+
+    /**
+     * 36根据多个用户账号(逗号分隔),查询返回多个用户信息
+     * @param usernames
+     * @return
+     */
+    @GetMapping("/sys/api/queryUsersByUsernames")
+    List<JSONObject> queryUsersByUsernames(String usernames);
+
+    /**
+     * 37根据多个用户ID(逗号分隔),查询返回多个用户信息
+     * @param ids
+     * @return
+     */
+    @GetMapping("/sys/api/queryUsersByIds")
+    List<JSONObject> queryUsersByIds(String ids);
+
+    /**
+     * 38根据多个部门编码(逗号分隔),查询返回多个部门信息
+     * @param orgCodes
+     * @return
+     */
+    @GetMapping("/sys/api/queryDepartsByOrgcodes")
+    List<JSONObject> queryDepartsByOrgcodes(String orgCodes);
+    /**
+     * 39根据多个部门编码(逗号分隔),查询返回多个部门信息
+     * @param ids
+     * @return
+     */
+    @GetMapping("/sys/api/queryDepartsByOrgIds")
+    List<JSONObject> queryDepartsByOrgIds(String ids);
+    
+    /**
+     * 40发送邮件消息
+     * @param email
+     * @param title
+     * @param content
+     */
+    @GetMapping("/sys/api/sendEmailMsg")
+    void sendEmailMsg(@RequestParam("email")String email,@RequestParam("title")String title,@RequestParam("content")String content);
+    /**
+     * 41 获取公司下级部门和公司下所有用户id
+     * @param orgCode
+     */
+    @GetMapping("/sys/api/getDeptUserByOrgCode")
+    List<Map> getDeptUserByOrgCode(@RequestParam("orgCode")String orgCode);
+}

+ 17 - 0
jeecg-boot-base/jeecg-boot-base-api/jeecg-system-cloud-api/src/main/java/org/jeecg/common/system/api/factory/SysBaseAPIFallbackFactory.java

@@ -0,0 +1,17 @@
+package org.jeecg.common.system.api.factory;
+
+import feign.hystrix.FallbackFactory;
+import org.jeecg.common.system.api.ISysBaseAPI;
+import org.jeecg.common.system.api.fallback.SysBaseAPIFallback;
+import org.springframework.stereotype.Component;
+
+@Component
+public class SysBaseAPIFallbackFactory implements FallbackFactory<ISysBaseAPI> {
+
+    @Override
+    public ISysBaseAPI create(Throwable throwable) {
+        SysBaseAPIFallback fallback = new SysBaseAPIFallback();
+        fallback.setCause(throwable);
+        return fallback;
+    }
+}

+ 272 - 0
jeecg-boot-base/jeecg-boot-base-api/jeecg-system-cloud-api/src/main/java/org/jeecg/common/system/api/fallback/SysBaseAPIFallback.java

@@ -0,0 +1,272 @@
+package org.jeecg.common.system.api.fallback;
+
+import com.alibaba.fastjson.JSONObject;
+import lombok.Setter;
+import lombok.extern.slf4j.Slf4j;
+import org.jeecg.common.api.dto.OnlineAuthDTO;
+import org.jeecg.common.api.dto.message.*;
+import org.jeecg.common.system.api.ISysBaseAPI;
+import org.jeecg.common.system.vo.*;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * 进入fallback的方法 检查是否token未设置
+ */
+@Slf4j
+public class SysBaseAPIFallback implements ISysBaseAPI {
+
+    @Setter
+    private Throwable cause;
+
+    @Override
+    public void sendSysAnnouncement(MessageDTO message) {
+        log.error("发送消息失败 {}", cause);
+    }
+
+    @Override
+    public void sendBusAnnouncement(BusMessageDTO message) {
+        log.error("发送消息失败 {}", cause);
+    }
+
+    @Override
+    public void sendTemplateAnnouncement(TemplateMessageDTO message) {
+        log.error("发送消息失败 {}", cause);
+    }
+
+    @Override
+    public void sendBusTemplateAnnouncement(BusTemplateMessageDTO message) {
+        log.error("发送消息失败 {}", cause);
+    }
+
+    @Override
+    public String parseTemplateByCode(TemplateDTO templateDTO) {
+        log.error("通过模板获取消息内容失败 {}", cause);
+        return null;
+    }
+
+    @Override
+    public LoginUser getUserById(String id) {
+        return null;
+    }
+
+    @Override
+    public List<String> getRolesByUsername(String username) {
+        return null;
+    }
+
+    @Override
+    public List<String> getDepartIdsByUsername(String username) {
+        return null;
+    }
+
+    @Override
+    public List<String> getDepartNamesByUsername(String username) {
+        return null;
+    }
+
+    @Override
+    public List<DictModel> queryDictItemsByCode(String code) {
+        return null;
+    }
+
+    @Override
+    public List<DictModel> queryAllDict() {
+        return null;
+    }
+
+    @Override
+    public List<SysCategoryModel> queryAllDSysCategory() {
+        return null;
+    }
+
+    @Override
+    public List<DictModel> queryTableDictItemsByCode(String table, String text, String code) {
+        return null;
+    }
+
+    @Override
+    public List<DictModel> queryAllDepartBackDictModel() {
+        return null;
+    }
+
+    @Override
+    public void updateSysAnnounReadFlag(String busType, String busId) {
+
+    }
+
+    @Override
+    public List<DictModel> queryFilterTableDictInfo(String table, String text, String code, String filterSql) {
+        return null;
+    }
+
+    @Override
+    public List<String> queryTableDictByKeys(String table, String text, String code, String[] keyArray) {
+        log.error("queryTableDictByKeys查询失败 {}", cause);
+        return null;
+    }
+
+    @Override
+    public List<ComboModel> queryAllUserBackCombo() {
+        return null;
+    }
+
+    @Override
+    public JSONObject queryAllUser(String userIds, Integer pageNo, int pageSize) {
+        return null;
+    }
+
+    @Override
+    public List<ComboModel> queryAllRole(String[] roleIds) {
+        log.error("获取角色信息失败 {}", cause);
+        return null;
+    }
+
+    @Override
+    public List<String> getRoleIdsByUsername(String username) {
+        return null;
+    }
+
+    @Override
+    public String getDepartIdsByOrgCode(String orgCode) {
+        return null;
+    }
+
+    @Override
+    public List<SysDepartModel> getAllSysDepart() {
+        return null;
+    }
+
+    @Override
+    public DictModel getParentDepartId(String departId) {
+        return null;
+    }
+
+    @Override
+    public List<String> getDeptHeadByDepId(String deptId) {
+        return null;
+    }
+
+    @Override
+    public void sendWebSocketMsg(String[] userIds, String cmd) {
+
+    }
+
+    @Override
+    public List<LoginUser> queryAllUserByIds(String[] userIds) {
+        return null;
+    }
+
+    @Override
+    public void meetingSignWebsocket(String userId) {
+
+    }
+
+    @Override
+    public List<LoginUser> queryUserByNames(String[] userNames) {
+        return null;
+    }
+
+    @Override
+    public Set<String> getUserRoleSet(String username) {
+        return null;
+    }
+
+    @Override
+    public Set<String> getUserPermissionSet(String username) {
+        return null;
+    }
+
+    @Override
+    public boolean hasOnlineAuth(OnlineAuthDTO onlineAuthDTO) {
+        return false;
+    }
+
+    @Override
+    public SysDepartModel selectAllById(String id) {
+        return null;
+    }
+
+    @Override
+    public List<String> queryDeptUsersByUserId(String userId) {
+        return null;
+    }
+
+    @Override
+    public Set<String> queryUserRoles(String username) {
+        return null;
+    }
+
+    @Override
+    public Set<String> queryUserAuths(String username) {
+        return null;
+    }
+
+    @Override
+    public DynamicDataSourceModel getDynamicDbSourceById(String dbSourceId) {
+        return null;
+    }
+
+    @Override
+    public DynamicDataSourceModel getDynamicDbSourceByCode(String dbSourceCode) {
+        return null;
+    }
+
+    @Override
+    public LoginUser getUserByName(String username) {
+        log.error("通过用户名获取当前登录用户信息 {}", cause);
+        return null;
+    }
+
+    @Override
+    public String translateDictFromTable(String table, String text, String code, String key) {
+        return null;
+    }
+
+    @Override
+    public String translateDict(String code, String key) {
+        return null;
+    }
+
+    @Override
+    public List<SysPermissionDataRuleModel> queryPermissionDataRule(String component, String requestPath, String username) {
+        return null;
+    }
+
+    @Override
+    public SysUserCacheInfo getCacheUser(String username) {
+        log.error("获取用户信息失败 {}", cause);
+        return null;
+    }
+
+    @Override
+    public List<JSONObject> queryUsersByUsernames(String usernames) {
+        return null;
+    }
+
+    @Override
+    public List<JSONObject> queryUsersByIds(String ids) {
+        return null;
+    }
+
+    @Override
+    public List<JSONObject> queryDepartsByOrgcodes(String orgCodes) {
+        return null;
+    }
+    @Override
+    public void sendEmailMsg(String email,String title,String content) {
+
+    }
+
+    @Override
+    public List<Map> getDeptUserByOrgCode(String orgCode) {
+        return null;
+    }
+
+    @Override
+    public List<JSONObject> queryDepartsByOrgIds(String ids) {
+        return null;
+    }
+}

+ 156 - 0
jeecg-boot-base/jeecg-boot-base-api/jeecg-system-cloud-api/src/main/java/org/jeecg/config/FeignConfig.java

@@ -0,0 +1,156 @@
+package org.jeecg.config;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.serializer.SerializerFeature;
+import com.alibaba.fastjson.support.config.FastJsonConfig;
+import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
+import com.alibaba.fastjson.support.springfox.SwaggerJsonSerializer;
+import feign.Feign;
+import feign.Logger;
+import feign.RequestInterceptor;
+import feign.codec.Decoder;
+import feign.codec.Encoder;
+import feign.form.spring.SpringFormEncoder;
+import lombok.extern.slf4j.Slf4j;
+import org.jeecg.common.constant.CommonConstant;
+import org.jeecg.common.util.DateUtils;
+import org.jeecg.common.util.PathMatcherUtil;
+import org.jeecg.config.sign.interceptor.SignAuthConfiguration;
+import org.jeecg.config.sign.util.HttpUtils;
+import org.jeecg.config.sign.util.SignUtil;
+import org.springframework.beans.factory.ObjectFactory;
+import org.springframework.boot.autoconfigure.AutoConfigureBefore;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
+import org.springframework.cloud.openfeign.FeignAutoConfiguration;
+import org.springframework.cloud.openfeign.support.SpringDecoder;
+import org.springframework.cloud.openfeign.support.SpringEncoder;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+import org.springframework.context.annotation.Scope;
+import org.springframework.http.MediaType;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import javax.servlet.http.HttpServletRequest;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.SortedMap;
+
+@ConditionalOnClass(Feign.class)
+@AutoConfigureBefore(FeignAutoConfiguration.class)
+@Slf4j
+@Configuration
+public class FeignConfig {
+
+    @Bean
+    public RequestInterceptor requestInterceptor() {
+        return requestTemplate -> {
+            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
+            if (null != attributes) {
+                HttpServletRequest request = attributes.getRequest();
+                log.info("Feign request: {}", request.getRequestURI());
+                // 将token信息放入header中
+                String token = request.getHeader(CommonConstant.X_ACCESS_TOKEN);
+                if(token==null || "".equals(token)){
+                    token = request.getParameter("token");
+                }
+                log.info("Feign request token: {}", token);
+                requestTemplate.header(CommonConstant.X_ACCESS_TOKEN, token);
+
+                //根据URL地址过滤请求 【字典表参数签名验证】
+                if (PathMatcherUtil.matches(Arrays.asList(SignAuthConfiguration.urlList),requestTemplate.path())) {
+                    try {
+                        log.info("============================ [begin] fegin api url ============================");
+                        log.info(requestTemplate.path());
+                        log.info(requestTemplate.method());
+                        String queryLine = requestTemplate.queryLine();
+                        if(queryLine!=null && queryLine.startsWith("?")){
+                            queryLine = queryLine.substring(1);
+                        }
+                        log.info(queryLine);
+                        if(requestTemplate.body()!=null){
+                            log.info(new String(requestTemplate.body()));
+                        }
+                        SortedMap<String, String> allParams = HttpUtils.getAllParams(requestTemplate.path(),queryLine,requestTemplate.body(),requestTemplate.method());
+                        String sign = SignUtil.getParamsSign(allParams);
+                        log.info(" Feign request params sign: {}",sign);
+                        log.info("============================ [end] fegin api url ============================");
+                        requestTemplate.header(CommonConstant.X_SIGN, sign);
+                        requestTemplate.header(CommonConstant.X_TIMESTAMP, DateUtils.getCurrentTimestamp().toString());
+                    } catch (IOException e) {
+                        e.printStackTrace();
+                    }
+                }
+            }
+        };
+    }
+
+
+
+    /**
+     * Feign 客户端的日志记录,默认级别为NONE
+     * Logger.Level 的具体级别如下:
+     * NONE:不记录任何信息
+     * BASIC:仅记录请求方法、URL以及响应状态码和执行时间
+     * HEADERS:除了记录 BASIC级别的信息外,还会记录请求和响应的头信息
+     * FULL:记录所有请求与响应的明细,包括头信息、请求体、元数据
+     */
+    @Bean
+    Logger.Level feignLoggerLevel() {
+        return Logger.Level.FULL;
+    }
+
+    /**
+     * Feign支持文件上传
+     * @param messageConverters
+     * @return
+     */
+    @Bean
+    @Primary
+    @Scope("prototype")
+    public Encoder multipartFormEncoder(ObjectFactory<HttpMessageConverters> messageConverters) {
+        return new SpringFormEncoder(new SpringEncoder(messageConverters));
+    }
+
+    // update-begin--Author:sunjianlei Date:20210604 for: 给 Feign 添加 FastJson 的解析支持 ----------
+    @Bean
+    public Encoder feignEncoder() {
+        return new SpringEncoder(feignHttpMessageConverter());
+    }
+
+    @Bean
+    public Decoder feignDecoder() {
+        return new SpringDecoder(feignHttpMessageConverter());
+    }
+
+    /**
+     * 设置解码器为fastjson
+     *
+     * @return
+     */
+    private ObjectFactory<HttpMessageConverters> feignHttpMessageConverter() {
+        final HttpMessageConverters httpMessageConverters = new HttpMessageConverters(this.getFastJsonConverter());
+        return () -> httpMessageConverters;
+    }
+
+    private FastJsonHttpMessageConverter getFastJsonConverter() {
+        FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
+
+        List<MediaType> supportedMediaTypes = new ArrayList<>();
+        MediaType mediaTypeJson = MediaType.valueOf(MediaType.APPLICATION_JSON_VALUE);
+        supportedMediaTypes.add(mediaTypeJson);
+        converter.setSupportedMediaTypes(supportedMediaTypes);
+        FastJsonConfig config = new FastJsonConfig();
+        config.getSerializeConfig().put(JSON.class, new SwaggerJsonSerializer());
+        config.setSerializerFeatures(SerializerFeature.DisableCircularReferenceDetect);
+        converter.setFastJsonConfig(config);
+
+        return converter;
+    }
+    // update-end--Author:sunjianlei Date:20210604 for: 给 Feign 添加 FastJson 的解析支持 ----------
+
+}

+ 14 - 0
jeecg-boot-base/jeecg-boot-base-api/jeecg-system-local-api/pom.xml

@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>jeecg-boot-base-api</artifactId>
+        <groupId>org.jeecgframework.boot</groupId>
+        <version>2.4.5</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>jeecg-system-local-api</artifactId>
+
+</project>

+ 98 - 0
jeecg-boot-base/jeecg-boot-base-api/jeecg-system-local-api/src/main/java/jtznyj/common/api/ICommonApi.java

@@ -0,0 +1,98 @@
+package jtznyj.common.api;
+
+import jtznyj.common.api.vo.AFocusWarn;
+import jtznyj.engineer.vo.LtdRecord;
+import org.springframework.stereotype.Service;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 智能预警module-system中需共用部分
+ */
+public interface ICommonApi {
+    /**
+     * 默认的工程预警算法
+     */
+    List<Map<String, Object>> queryDefaultEngineerLogic();
+
+    /**
+     * 井的工程预警算法
+     * @param jh
+     * @return
+     */
+    List<Map<String, Object>> queryWellEngineerLogic(String jh);
+
+    /**
+     * 根据井号名称获得表代码
+     * @param jh
+     * @return
+     */
+    String getTableCode(String jh);
+
+    /**
+     * 查询一段时间内的ltd数据
+     * @param end
+     * @param minutes
+     * @return
+     */
+    List<LtdRecord> queryLtdListInPeriod(String jh, Date end, Integer minutes);
+
+    /**
+     * 查询一段时间内的ltd数据, 倒序排列
+     * @param end
+     * @param minutes
+     * @return
+     */
+    List<LtdRecord> queryLtdListInPeriodDesc(String jh, Date end, Integer minutes);
+
+
+    /**
+     * 查询ltd中井有数据的最新一天
+     * @param jh
+     * @return
+     */
+    List<Map<String, Object>> queryJhLastDayOnLtd(String jh);
+
+    /**
+     * 查询钻井液中井有数据的最新一天
+     * @param jh
+     * @return
+     */
+    List<Map<String, Object>> queryJhLastDayOnZjy(String jh);
+
+    /**
+     * 保存一条 AFocusWarn
+     * @param src
+     * @return
+     */
+    Boolean saveOneAFocusWarn(AFocusWarn src);
+
+    /**
+     * 使用 sql 查询一条 AFcousWarn
+     * @param sql
+     * @return
+     */
+    AFocusWarn queryOneAFocusWarnWithSql(String sql);
+
+    /**
+     * 获取井最新时间的深度值
+     * @param jh
+     * @return
+     */
+    List<Map<String, Object>> queryDepthWithLastTime(String jh);
+
+    /**
+     * 获取表 A_JH 所有数据
+     * @return
+     */
+    List<Map<String, Object>> queryAllAJh();
+
+    /**
+     * 获取井 最新一条的 A_FOCUS_WARN数据
+     * @param jh
+     * @return
+     */
+    List<Map<String, Object>> queryWellAfocusWarnLast(String jh);
+}

+ 46 - 0
jeecg-boot-base/jeecg-boot-base-api/jeecg-system-local-api/src/main/java/jtznyj/common/api/vo/AFocusWarn.java

@@ -0,0 +1,46 @@
+package jtznyj.common.api.vo;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.util.Date;
+
+@Data
+@TableName("A_FOCUS_WARN")
+public class AFocusWarn {
+
+    @TableId(type = IdType.ASSIGN_ID)
+    private String id;
+
+    private String source;
+
+    private String catogary;
+
+    private String jh;
+
+    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date warnTime;
+
+    private String bjnr;
+
+    private Long servercost;
+
+    private String dsjs;
+
+    private String key;
+
+    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date updated;
+
+    private String judge;
+
+    private String remark;//备注
+
+    private String recorder;//操作者
+}

+ 35 - 0
jeecg-boot-base/jeecg-boot-base-api/jeecg-system-local-api/src/main/java/jtznyj/engineer/api/IEngineerApi.java

@@ -0,0 +1,35 @@
+package jtznyj.engineer.api;
+
+import jtznyj.engineer.dto.WarnItemDto;
+import org.springframework.stereotype.Service;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 工程预警算法中需公用部分
+ */
+public interface IEngineerApi {
+
+    /**
+     * 检测井规定时间区间内是否报警,并保存至AFocusWarn表
+     *
+     * @param jh               井号
+     * @param startTime        开始时间
+     * @param durationInMinute 检测数据样本持续时长(分钟)
+     * @param testAllData      是否检测所有样本数据
+     * @return
+     */
+    void testAndSaveWarnResult(String jh, Date startTime, int durationInMinute, boolean testAllData);
+
+
+    /**
+     * 计算 从endTime-30分钟到endTime之间工程预警的结果
+     * @param jh
+     * @param endTime
+     * @return
+     */
+    List<WarnItemDto> getHalfHourWarnResults(String jh, Date endTime);
+
+
+}

+ 23 - 0
jeecg-boot-base/jeecg-boot-base-api/jeecg-system-local-api/src/main/java/jtznyj/engineer/dto/WarnItemDto.java

@@ -0,0 +1,23 @@
+package jtznyj.engineer.dto;
+
+import lombok.Data;
+
+import java.util.Date;
+import java.util.Map;
+@Data
+public class WarnItemDto {
+    public String source;
+    public String catogary;
+    public Date requestStart;
+    public Date warnTime;
+    public Date jcrq;
+    public String bjnr;
+    public  String clfs;
+    public String sssj;
+    public String dsjs;
+    public String zjzh;
+    public Map<String, Object> extra;
+    public String jh;
+    public long serverCost;
+    public String key;
+}

+ 1124 - 0
jeecg-boot-base/jeecg-boot-base-api/jeecg-system-local-api/src/main/java/jtznyj/engineer/vo/LtdRecord.java

@@ -0,0 +1,1124 @@
+package jtznyj.engineer.vo;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+public class LtdRecord implements Serializable {
+    public String getJH() {
+        return JH;
+    }
+
+    public void setJH(String JH) {
+        this.JH = JH;
+    }
+
+    public String JH;
+
+    public String getTID() {
+        return TID;
+    }
+
+    public void setTID(String TID) {
+        this.TID = TID;
+    }
+    public String TID;
+    public String getTIME() {
+        return TIME;
+    }
+
+    public void setTIME(String TIME) {
+        this.TIME = TIME;
+    }
+    public  String TIME;
+
+    public double ID;
+
+    public BigDecimal getID() {
+        return new BigDecimal(ID);
+    }
+
+    public void setID(BigDecimal ID) {
+        this.ID = ID.doubleValue();
+    }
+    public double DEPTH;
+
+    public BigDecimal getDEPTH() {
+        return new BigDecimal(DEPTH);
+    }
+
+    public void setDEPTH(BigDecimal DEPTH) {
+        this.DEPTH = DEPTH.doubleValue();
+    }
+    public double VDEPTH;
+
+    public BigDecimal getVDEPTH() {
+        return new BigDecimal(VDEPTH);
+    }
+
+    public void setVDEPTH(BigDecimal VDEPTH) {
+        this.VDEPTH = VDEPTH.doubleValue();
+    }
+    public double STAT;
+
+    public BigDecimal getSTAT() {
+        return new BigDecimal(STAT);
+    }
+
+    public void setSTAT(BigDecimal STAT) {
+        this.STAT = STAT.doubleValue();
+    }
+    public double LAGTIME;
+
+    public BigDecimal getLAGTIME() {
+        return new BigDecimal(LAGTIME);
+    }
+
+    public void setLAGTIME(BigDecimal LAGTIME) {
+        this.LAGTIME = LAGTIME.doubleValue();
+    }
+    public double LAGSTROKES;
+
+    public BigDecimal getLAGSTROKES() {
+        return new BigDecimal(LAGSTROKES);
+    }
+
+    public void setLAGSTROKES(BigDecimal LAGSTROKES) {
+        this.LAGSTROKES = LAGSTROKES.doubleValue();
+    }
+    public double LAGDEPTH;
+
+    public BigDecimal getLAGDEPTH() {
+        return new BigDecimal(LAGDEPTH);
+    }
+
+    public void setLAGDEPTH(BigDecimal LAGDEPTH) {
+        this.LAGDEPTH = LAGDEPTH.doubleValue();
+    }
+    public double BITDEPTH;
+
+    public BigDecimal getBITDEPTH() {
+        return new BigDecimal(BITDEPTH);
+    }
+
+    public void setBITDEPTH(BigDecimal BITDEPTH) {
+        this.BITDEPTH = BITDEPTH.doubleValue();
+    }
+    public double BITOFF;
+
+    public BigDecimal getBITOFF() {
+        return new BigDecimal(BITOFF);
+    }
+
+    public void setBITOFF(BigDecimal BITOFF) {
+        this.BITOFF = BITOFF.doubleValue();
+    }
+    public double KELLYIN;
+
+    public BigDecimal getKELLYIN() {
+        return new BigDecimal(KELLYIN);
+    }
+
+    public void setKELLYIN(BigDecimal KELLYIN) {
+        this.KELLYIN = KELLYIN.doubleValue();
+    }
+    public double HKH;
+
+    public BigDecimal getHKH() {
+        return new BigDecimal(HKH);
+    }
+
+    public void setHKH(BigDecimal HKH) {
+        this.HKH = HKH.doubleValue();
+    }
+    public double HKS;
+
+    public BigDecimal getHKS() {
+        return new BigDecimal(HKS);
+    }
+
+    public void setHKS(BigDecimal HKS) {
+        this.HKS = HKS.doubleValue();
+    }
+    public double WOH;
+
+    public BigDecimal getWOH() {
+        return new BigDecimal(WOH);
+    }
+
+    public void setWOH(BigDecimal WOH) {
+        this.WOH = WOH.doubleValue();
+    }
+    public double WOH_CALC;
+
+    public BigDecimal getWOH_CALC() {
+        return new BigDecimal(WOH_CALC);
+    }
+
+    public void setWOH_CALC(BigDecimal WOH_CALC) {
+        this.WOH_CALC = WOH_CALC.doubleValue();
+    }
+    public double FLOAT_WEIGHT;
+
+    public BigDecimal getFLOAT_WEIGHT() {
+        return new BigDecimal(FLOAT_WEIGHT);
+    }
+
+    public void setFLOAT_WEIGHT(BigDecimal FLOAT_WEIGHT) {
+        this.FLOAT_WEIGHT = FLOAT_WEIGHT.doubleValue();
+    }
+    public double RPM;
+
+    public BigDecimal getRPM() {
+        return new BigDecimal(RPM);
+    }
+
+    public void setRPM(BigDecimal RPM) {
+        this.RPM = RPM.doubleValue();
+    }
+    public double ROP_INST;
+
+    public BigDecimal getROP_INST() {
+        return new BigDecimal(ROP_INST);
+    }
+
+    public void setROP_INST(BigDecimal ROP_INST) {
+        this.ROP_INST = ROP_INST.doubleValue();
+    }
+    public double ROP_MAVG;
+
+    public BigDecimal getROP_MAVG() {
+        return new BigDecimal(ROP_MAVG);
+    }
+
+    public void setROP_MAVG(BigDecimal ROP_MAVG) {
+        this.ROP_MAVG = ROP_MAVG.doubleValue();
+    }
+    public double WOB;
+
+    public BigDecimal getWOB() {
+        return new BigDecimal(WOB);
+    }
+
+    public void setWOB(BigDecimal WOB) {
+        this.WOB = WOB.doubleValue();
+    }
+    public double TORQUE;
+
+    public BigDecimal getTORQUE() {
+        return new BigDecimal(TORQUE);
+    }
+
+    public void setTORQUE(BigDecimal TORQUE) {
+        this.TORQUE = TORQUE.doubleValue();
+    }
+    public double TD_TORQUE;
+
+    public BigDecimal getTD_TORQUE() {
+        return new BigDecimal(TD_TORQUE);
+    }
+
+    public void setTD_TORQUE(BigDecimal TD_TORQUE) {
+        this.TD_TORQUE = TD_TORQUE.doubleValue();
+    }
+    public double SPP;
+
+    public BigDecimal getSPP() {
+        return new BigDecimal(SPP);
+    }
+
+    public void setSPP(BigDecimal SPP) {
+        this.SPP = SPP.doubleValue();
+    }
+    public double WHP;
+
+    public BigDecimal getWHP() {
+        return new BigDecimal(WHP);
+    }
+
+    public void setWHP(BigDecimal WHP) {
+        this.WHP = WHP.doubleValue();
+    }
+    public double PUMP1;
+
+    public BigDecimal getPUMP1() {
+        return new BigDecimal(PUMP1);
+    }
+
+    public void setPUMP1(BigDecimal PUMP1) {
+        this.PUMP1 = PUMP1.doubleValue();
+    }
+    public double PUMP2;
+
+    public BigDecimal getPUMP2() {
+        return new BigDecimal(PUMP2);
+    }
+
+    public void setPUMP2(BigDecimal PUMP2) {
+        this.PUMP2 = PUMP2.doubleValue();
+    }
+    public double PUMP3;
+
+    public BigDecimal getPUMP3() {
+        return new BigDecimal(PUMP3);
+    }
+
+    public void setPUMP3(BigDecimal PUMP3) {
+        this.PUMP3 = PUMP3.doubleValue();
+    }
+    public double PUMPTOTAL;
+
+    public BigDecimal getPUMPTOTAL() {
+        return new BigDecimal(PUMPTOTAL);
+    }
+
+    public void setPUMPTOTAL(BigDecimal PUMPTOTAL) {
+        this.PUMPTOTAL = PUMPTOTAL.doubleValue();
+    }
+    public double STROKES1;
+
+    public BigDecimal getSTROKES1() {
+        return new BigDecimal(STROKES1);
+    }
+
+    public void setSTROKES1(BigDecimal STROKES1) {
+        this.STROKES1 = STROKES1.doubleValue();
+    }
+    public double STROKES2;
+
+    public BigDecimal getSTROKES2() {
+        return new BigDecimal(STROKES2);
+    }
+
+    public void setSTROKES2(BigDecimal STROKES2) {
+        this.STROKES2 = STROKES2.doubleValue();
+    }
+    public double STROKES3;
+
+    public BigDecimal getSTROKES3() {
+        return new BigDecimal(STROKES3);
+    }
+
+    public void setSTROKES3(BigDecimal STROKES3) {
+        this.STROKES3 = STROKES3.doubleValue();
+    }
+    public double STROKESTOTAL;
+
+    public BigDecimal getSTROKESTOTAL() {
+        return new BigDecimal(STROKESTOTAL);
+    }
+
+    public void setSTROKESTOTAL(BigDecimal STROKESTOTAL) {
+        this.STROKESTOTAL = STROKESTOTAL.doubleValue();
+    }
+    public double VOP_INST;
+
+    public BigDecimal getVOP_INST() {
+        return new BigDecimal(VOP_INST);
+    }
+
+    public void setVOP_INST(BigDecimal VOP_INST) {
+        this.VOP_INST = VOP_INST.doubleValue();
+    }
+    public double VOP_MAVG;
+
+    public BigDecimal getVOP_MAVG() {
+        return new BigDecimal(VOP_MAVG);
+    }
+
+    public void setVOP_MAVG(BigDecimal VOP_MAVG) {
+        this.VOP_MAVG = VOP_MAVG.doubleValue();
+    }
+    public double FLOWIN;
+
+    public BigDecimal getFLOWIN() {
+        return new BigDecimal(FLOWIN);
+    }
+
+    public void setFLOWIN(BigDecimal FLOWIN) {
+        this.FLOWIN = FLOWIN.doubleValue();
+    }
+    public double FLOWOUT;
+
+    public BigDecimal getFLOWOUT() {
+        return new BigDecimal(FLOWOUT);
+    }
+
+    public void setFLOWOUT(BigDecimal FLOWOUT) {
+        this.FLOWOUT = FLOWOUT.doubleValue();
+    }
+    public double FLOWOUTPERCENT;
+
+    public BigDecimal getFLOWOUTPERCENT() {
+        return new BigDecimal(FLOWOUTPERCENT);
+    }
+
+    public void setFLOWOUTPERCENT(BigDecimal FLOWOUTPERCENT) {
+        this.FLOWOUTPERCENT = FLOWOUTPERCENT.doubleValue();
+    }
+    public double MWIN;
+
+    public BigDecimal getMWIN() {
+        return new BigDecimal(MWIN);
+    }
+
+    public void setMWIN(BigDecimal MWIN) {
+        this.MWIN = MWIN.doubleValue();
+    }
+    public double MWOUT;
+
+    public BigDecimal getMWOUT() {
+        return new BigDecimal(MWOUT);
+    }
+
+    public void setMWOUT(BigDecimal MWOUT) {
+        this.MWOUT = MWOUT.doubleValue();
+    }
+    public double TEMPIN;
+
+    public BigDecimal getTEMPIN() {
+        return new BigDecimal(TEMPIN);
+    }
+
+    public void setTEMPIN(BigDecimal TEMPIN) {
+        this.TEMPIN = TEMPIN.doubleValue();
+    }
+    public double TEMPOUT;
+
+    public BigDecimal getTEMPOUT() {
+        return new BigDecimal(TEMPOUT);
+    }
+
+    public void setTEMPOUT(BigDecimal TEMPOUT) {
+        this.TEMPOUT = TEMPOUT.doubleValue();
+    }
+    public double CONDIN;
+
+    public BigDecimal getCONDIN() {
+        return new BigDecimal(CONDIN);
+    }
+
+    public void setCONDIN(BigDecimal CONDIN) {
+        this.CONDIN = CONDIN.doubleValue();
+    }
+    public double CONDOUT;
+
+    public BigDecimal getCONDOUT() {
+        return new BigDecimal(CONDOUT);
+    }
+
+    public void setCONDOUT(BigDecimal CONDOUT) {
+        this.CONDOUT = CONDOUT.doubleValue();
+    }
+    public double ECD;
+
+    public BigDecimal getECD() {
+        return new BigDecimal(ECD);
+    }
+
+    public void setECD(BigDecimal ECD) {
+        this.ECD = ECD.doubleValue();
+    }
+    public double PIT1;
+
+    public BigDecimal getPIT1() {
+        return new BigDecimal(PIT1);
+    }
+
+    public void setPIT1(BigDecimal PIT1) {
+        this.PIT1 = PIT1.doubleValue();
+    }
+    public double PIT2;
+
+    public BigDecimal getPIT2() {
+        return new BigDecimal(PIT2);
+    }
+
+    public void setPIT2(BigDecimal PIT2) {
+        this.PIT2 = PIT2.doubleValue();
+    }
+    public double PIT3;
+
+    public BigDecimal getPIT3() {
+        return new BigDecimal(PIT3);
+    }
+
+    public void setPIT3(BigDecimal PIT3) {
+        this.PIT3 = PIT3.doubleValue();
+    }
+    public double PIT4;
+
+    public BigDecimal getPIT4() {
+        return new BigDecimal(PIT4);
+    }
+
+    public void setPIT4(BigDecimal PIT4) {
+        this.PIT4 = PIT4.doubleValue();
+    }
+    public double PIT5;
+
+    public BigDecimal getPIT5() {
+        return new BigDecimal(PIT5);
+    }
+
+    public void setPIT5(BigDecimal PIT5) {
+        this.PIT5 = PIT5.doubleValue();
+    }
+    public double PIT6;
+
+    public BigDecimal getPIT6() {
+        return new BigDecimal(PIT6);
+    }
+
+    public void setPIT6(BigDecimal PIT6) {
+        this.PIT6 = PIT6.doubleValue();
+    }
+    public double PIT7;
+
+    public BigDecimal getPIT7() {
+        return new BigDecimal(PIT7);
+    }
+
+    public void setPIT7(BigDecimal PIT7) {
+        this.PIT7 = PIT7.doubleValue();
+    }
+    public double PIT8;
+
+    public BigDecimal getPIT8() {
+        return new BigDecimal(PIT8);
+    }
+
+    public void setPIT8(BigDecimal PIT8) {
+        this.PIT8 = PIT8.doubleValue();
+    }
+    public double PIT9;
+
+    public BigDecimal getPIT9() {
+        return new BigDecimal(PIT9);
+    }
+
+    public void setPIT9(BigDecimal PIT9) {
+        this.PIT9 = PIT9.doubleValue();
+    }
+    public double PIT10;
+
+    public BigDecimal getPIT10() {
+        return new BigDecimal(PIT10);
+    }
+
+    public void setPIT10(BigDecimal PIT10) {
+        this.PIT10 = PIT10.doubleValue();
+    }
+    public double PIT11;
+
+    public BigDecimal getPIT11() {
+        return new BigDecimal(PIT11);
+    }
+
+    public void setPIT11(BigDecimal PIT11) {
+        this.PIT11 = PIT11.doubleValue();
+    }
+    public double PIT12;
+
+    public BigDecimal getPIT12() {
+        return new BigDecimal(PIT12);
+    }
+
+    public void setPIT12(BigDecimal PIT12) {
+        this.PIT12 = PIT12.doubleValue();
+    }
+    public double TRIPTANDVOL;
+
+    public BigDecimal getTRIPTANDVOL() {
+        return new BigDecimal(TRIPTANDVOL);
+    }
+
+    public void setTRIPTANDVOL(BigDecimal TRIPTANDVOL) {
+        this.TRIPTANDVOL = TRIPTANDVOL.doubleValue();
+    }
+    public double ACTPITTOTAL;
+
+    public BigDecimal getACTPITTOTAL() {
+        return new BigDecimal(ACTPITTOTAL);
+    }
+
+    public void setACTPITTOTAL(BigDecimal ACTPITTOTAL) {
+        this.ACTPITTOTAL = ACTPITTOTAL.doubleValue();
+    }
+    public double PITTOTAL;
+
+    public BigDecimal getPITTOTAL() {
+        return new BigDecimal(PITTOTAL);
+    }
+
+    public void setPITTOTAL(BigDecimal PITTOTAL) {
+        this.PITTOTAL = PITTOTAL.doubleValue();
+    }
+    public double GAINLOSSVOL;
+
+    public BigDecimal getGAINLOSSVOL() {
+        return new BigDecimal(GAINLOSSVOL);
+    }
+
+    public void setGAINLOSSVOL(BigDecimal GAINLOSSVOL) {
+        this.GAINLOSSVOL = GAINLOSSVOL.doubleValue();
+    }
+    public double C1;
+
+    public BigDecimal getC1() {
+        return new BigDecimal(C1);
+    }
+
+    public void setC1(BigDecimal C1) {
+        this.C1 = C1.doubleValue();
+    }
+    public double C2;
+
+    public BigDecimal getC2() {
+        return new BigDecimal(C2);
+    }
+
+    public void setC2(BigDecimal C2) {
+        this.C2 = C2.doubleValue();
+    }
+    public double C3;
+
+    public BigDecimal getC3() {
+        return new BigDecimal(C3);
+    }
+
+    public void setC3(BigDecimal C3) {
+        this.C3 = C3.doubleValue();
+    }
+    public double IC4;
+
+    public BigDecimal getIC4() {
+        return new BigDecimal(IC4);
+    }
+
+    public void setIC4(BigDecimal IC4) {
+        this.IC4 = IC4.doubleValue();
+    }
+    public double NC4;
+
+    public BigDecimal getNC4() {
+        return new BigDecimal(NC4);
+    }
+
+    public void setNC4(BigDecimal NC4) {
+        this.NC4 = NC4.doubleValue();
+    }
+    public double IC5;
+
+    public BigDecimal getIC5() {
+        return new BigDecimal(IC5);
+    }
+
+    public void setIC5(BigDecimal IC5) {
+        this.IC5 = IC5.doubleValue();
+    }
+    public double NC5;
+
+    public BigDecimal getNC5() {
+        return new BigDecimal(NC5);
+    }
+
+    public void setNC5(BigDecimal NC5) {
+        this.NC5 = NC5.doubleValue();
+    }
+    public double EC5;
+
+    public BigDecimal getEC5() {
+        return new BigDecimal(EC5);
+    }
+
+    public void setEC5(BigDecimal EC5) {
+        this.EC5 = EC5.doubleValue();
+    }
+    public double IC6;
+
+    public BigDecimal getIC6() {
+        return new BigDecimal(IC6);
+    }
+
+    public void setIC6(BigDecimal IC6) {
+        this.IC6 = IC6.doubleValue();
+    }
+    public double NC6;
+
+    public BigDecimal getNC6() {
+        return new BigDecimal(NC6);
+    }
+
+    public void setNC6(BigDecimal NC6) {
+        this.NC6 = NC6.doubleValue();
+    }
+    public double TG;
+
+    public BigDecimal getTG() {
+        return new BigDecimal(TG);
+    }
+
+    public void setTG(BigDecimal TG) {
+        this.TG = TG.doubleValue();
+    }
+    public double CO2;
+
+    public BigDecimal getCO2() {
+        return new BigDecimal(CO2);
+    }
+
+    public void setCO2(BigDecimal CO2) {
+        this.CO2 = CO2.doubleValue();
+    }
+    public double H2;
+
+    public BigDecimal getH2() {
+        return new BigDecimal(H2);
+    }
+
+    public void setH2(BigDecimal H2) {
+        this.H2 = H2.doubleValue();
+    }
+    public double H2S1;
+
+    public BigDecimal getH2S1() {
+        return new BigDecimal(H2S1);
+    }
+
+    public void setH2S1(BigDecimal H2S1) {
+        this.H2S1 = H2S1.doubleValue();
+    }
+    public double H2S2;
+
+    public BigDecimal getH2S2() {
+        return new BigDecimal(H2S2);
+    }
+
+    public void setH2S2(BigDecimal H2S2) {
+        this.H2S2 = H2S2.doubleValue();
+    }
+    public double H2S3;
+
+    public BigDecimal getH2S3() {
+        return new BigDecimal(H2S3);
+    }
+
+    public void setH2S3(BigDecimal H2S3) {
+        this.H2S3 = H2S3.doubleValue();
+    }
+    public double H2S4;
+
+    public BigDecimal getH2S4() {
+        return new BigDecimal(H2S4);
+    }
+
+    public void setH2S4(BigDecimal H2S4) {
+        this.H2S4 = H2S4.doubleValue();
+    }
+    public double H2S5;
+
+    public BigDecimal getH2S5() {
+        return new BigDecimal(H2S5);
+    }
+
+    public void setH2S5(BigDecimal H2S5) {
+        this.H2S5 = H2S5.doubleValue();
+    }
+    public double H2S6;
+
+    public BigDecimal getH2S6() {
+        return new BigDecimal(H2S6);
+    }
+
+    public void setH2S6(BigDecimal H2S6) {
+        this.H2S6 = H2S6.doubleValue();
+    }
+    public double H2S7;
+
+    public BigDecimal getH2S7() {
+        return new BigDecimal(H2S7);
+    }
+
+    public void setH2S7(BigDecimal H2S7) {
+        this.H2S7 = H2S7.doubleValue();
+    }
+    public double H2S8;
+
+    public BigDecimal getH2S8() {
+        return new BigDecimal(H2S8);
+    }
+
+    public void setH2S8(BigDecimal H2S8) {
+        this.H2S8 = H2S8.doubleValue();
+    }
+    public double STRINGLEN;
+
+    public BigDecimal getSTRINGLEN() {
+        return new BigDecimal(STRINGLEN);
+    }
+
+    public void setSTRINGLEN(BigDecimal STRINGLEN) {
+        this.STRINGLEN = STRINGLEN.doubleValue();
+    }
+    public double CURPIPE;
+
+    public BigDecimal getCURPIPE() {
+        return new BigDecimal(CURPIPE);
+    }
+
+    public void setCURPIPE(BigDecimal CURPIPE) {
+        this.CURPIPE = CURPIPE.doubleValue();
+    }
+    public double BITNO;
+
+    public BigDecimal getBITNO() {
+        return new BigDecimal(BITNO);
+    }
+
+    public void setBITNO(BigDecimal BITNO) {
+        this.BITNO = BITNO.doubleValue();
+    }
+    public double BITSIZE;
+
+    public BigDecimal getBITSIZE() {
+        return new BigDecimal(BITSIZE);
+    }
+
+    public void setBITSIZE(BigDecimal BITSIZE) {
+        this.BITSIZE = BITSIZE.doubleValue();
+    }
+    public double BITTYPE;
+
+    public BigDecimal getBITTYPE() {
+        return new BigDecimal(BITTYPE);
+    }
+
+    public void setBITTYPE(BigDecimal BITTYPE) {
+        this.BITTYPE = BITTYPE.doubleValue();
+    }
+    public double BITRUN;
+
+    public BigDecimal getBITRUN() {
+        return new BigDecimal(BITRUN);
+    }
+
+    public void setBITRUN(BigDecimal BITRUN) {
+        this.BITRUN = BITRUN.doubleValue();
+    }
+    public double BITTIME;
+
+    public BigDecimal getBITTIME() {
+        return new BigDecimal(BITTIME);
+    }
+
+    public void setBITTIME(BigDecimal BITTIME) {
+        this.BITTIME = BITTIME.doubleValue();
+    }
+    public double BITDRILLTIME;
+
+    public BigDecimal getBITDRILLTIME() {
+        return new BigDecimal(BITDRILLTIME);
+    }
+
+    public void setBITDRILLTIME(BigDecimal BITDRILLTIME) {
+        this.BITDRILLTIME = BITDRILLTIME.doubleValue();
+    }
+    public double BITCOST;
+
+    public BigDecimal getBITCOST() {
+        return new BigDecimal(BITCOST);
+    }
+
+    public void setBITCOST(BigDecimal BITCOST) {
+        this.BITCOST = BITCOST.doubleValue();
+    }
+    public double TOTALDAYS;
+
+    public BigDecimal getTOTALDAYS() {
+        return new BigDecimal(TOTALDAYS);
+    }
+
+    public void setTOTALDAYS(BigDecimal TOTALDAYS) {
+        this.TOTALDAYS = TOTALDAYS.doubleValue();
+    }
+    public double STANDSDONE;
+
+    public BigDecimal getSTANDSDONE() {
+        return new BigDecimal(STANDSDONE);
+    }
+
+    public void setSTANDSDONE(BigDecimal STANDSDONE) {
+        this.STANDSDONE = STANDSDONE.doubleValue();
+    }
+    public double STANDSTOGO;
+
+    public BigDecimal getSTANDSTOGO() {
+        return new BigDecimal(STANDSTOGO);
+    }
+
+    public void setSTANDSTOGO(BigDecimal STANDSTOGO) {
+        this.STANDSTOGO = STANDSTOGO.doubleValue();
+    }
+    public double TRIPOVERPULL;
+
+    public BigDecimal getTRIPOVERPULL() {
+        return new BigDecimal(TRIPOVERPULL);
+    }
+
+    public void setTRIPOVERPULL(BigDecimal TRIPOVERPULL) {
+        this.TRIPOVERPULL = TRIPOVERPULL.doubleValue();
+    }
+    public double DC;
+
+    public BigDecimal getDC() {
+        return new BigDecimal(DC);
+    }
+
+    public void setDC(BigDecimal DC) {
+        this.DC = DC.doubleValue();
+    }
+    public double SIGMA;
+
+    public BigDecimal getSIGMA() {
+        return new BigDecimal(SIGMA);
+    }
+
+    public void setSIGMA(BigDecimal SIGMA) {
+        this.SIGMA = SIGMA.doubleValue();
+    }
+    public double FREE95;
+
+    public BigDecimal getFREE95() {
+        return new BigDecimal(FREE95);
+    }
+
+    public void setFREE95(BigDecimal FREE95) {
+        this.FREE95 = FREE95.doubleValue();
+    }
+    public double FREE96;
+
+    public BigDecimal getFREE96() {
+        return new BigDecimal(FREE96);
+    }
+
+    public void setFREE96(BigDecimal FREE96) {
+        this.FREE96 = FREE96.doubleValue();
+    }
+    public double FREE97;
+
+    public BigDecimal getFREE97() {
+        return new BigDecimal(FREE97);
+    }
+
+    public void setFREE97(BigDecimal FREE97) {
+        this.FREE97 = FREE97.doubleValue();
+    }
+    public double FREE98;
+
+    public BigDecimal getFREE98() {
+        return new BigDecimal(FREE98);
+    }
+
+    public void setFREE98(BigDecimal FREE98) {
+        this.FREE98 = FREE98.doubleValue();
+    }
+    public double FREE99;
+
+    public BigDecimal getFREE99() {
+        return new BigDecimal(FREE99);
+    }
+
+    public void setFREE99(BigDecimal FREE99) {
+        this.FREE99 = FREE99.doubleValue();
+    }
+    public double FREE100;
+
+    public BigDecimal getFREE100() {
+        return new BigDecimal(FREE100);
+    }
+
+    public void setFREE100(BigDecimal FREE100) {
+        this.FREE100 = FREE100.doubleValue();
+    }
+    public double FREE101;
+
+    public BigDecimal getFREE101() {
+        return new BigDecimal(FREE101);
+    }
+
+    public void setFREE101(BigDecimal FREE101) {
+        this.FREE101 = FREE101.doubleValue();
+    }
+    public double FREE102;
+
+    public BigDecimal getFREE102() {
+        return new BigDecimal(FREE102);
+    }
+
+    public void setFREE102(BigDecimal FREE102) {
+        this.FREE102 = FREE102.doubleValue();
+    }
+    public double FREE103;
+
+    public BigDecimal getFREE103() {
+        return new BigDecimal(FREE103);
+    }
+
+    public void setFREE103(BigDecimal FREE103) {
+        this.FREE103 = FREE103.doubleValue();
+    }
+    public double FREE104;
+
+    public BigDecimal getFREE104() {
+        return new BigDecimal(FREE104);
+    }
+
+    public void setFREE104(BigDecimal FREE104) {
+        this.FREE104 = FREE104.doubleValue();
+    }
+    public double FREE105;
+
+    public BigDecimal getFREE105() {
+        return new BigDecimal(FREE105);
+    }
+
+    public void setFREE105(BigDecimal FREE105) {
+        this.FREE105 = FREE105.doubleValue();
+    }
+    public double FREE106;
+
+    public BigDecimal getFREE106() {
+        return new BigDecimal(FREE106);
+    }
+
+    public void setFREE106(BigDecimal FREE106) {
+        this.FREE106 = FREE106.doubleValue();
+    }
+    public double FREE107;
+
+    public BigDecimal getFREE107() {
+        return new BigDecimal(FREE107);
+    }
+
+    public void setFREE107(BigDecimal FREE107) {
+        this.FREE107 = FREE107.doubleValue();
+    }
+    public double FREE108;
+
+    public BigDecimal getFREE108() {
+        return new BigDecimal(FREE108);
+    }
+
+    public void setFREE108(BigDecimal FREE108) {
+        this.FREE108 = FREE108.doubleValue();
+    }
+    public double FREE109;
+
+    public BigDecimal getFREE109() {
+        return new BigDecimal(FREE109);
+    }
+
+    public void setFREE109(BigDecimal FREE109) {
+        this.FREE109 = FREE109.doubleValue();
+    }
+    public double FREE110;
+
+    public BigDecimal getFREE110() {
+        return new BigDecimal(FREE110);
+    }
+
+    public void setFREE110(BigDecimal FREE110) {
+        this.FREE110 = FREE110.doubleValue();
+    }
+    public double FREE111;
+
+    public BigDecimal getFREE111() {
+        return new BigDecimal(FREE111);
+    }
+
+    public void setFREE111(BigDecimal FREE111) {
+        this.FREE111 = FREE111.doubleValue();
+    }
+    public double FREE112;
+
+    public BigDecimal getFREE112() {
+        return new BigDecimal(FREE112);
+    }
+
+    public void setFREE112(BigDecimal FREE112) {
+        this.FREE112 = FREE112.doubleValue();
+    }
+    public double FREE113;
+
+    public BigDecimal getFREE113() {
+        return new BigDecimal(FREE113);
+    }
+
+    public void setFREE113(BigDecimal FREE113) {
+        this.FREE113 = FREE113.doubleValue();
+    }
+    public double FREE114;
+
+    public BigDecimal getFREE114() {
+        return new BigDecimal(FREE114);
+    }
+
+    public void setFREE114(BigDecimal FREE114) {
+        this.FREE114 = FREE114.doubleValue();
+    }
+    public double FREE115;
+
+    public BigDecimal getFREE115() {
+        return new BigDecimal(FREE115);
+    }
+
+    public void setFREE115(BigDecimal FREE115) {
+        this.FREE115 = FREE115.doubleValue();
+    }
+    public double FREE116;
+
+    public BigDecimal getFREE116() {
+        return new BigDecimal(FREE116);
+    }
+
+    public void setFREE116(BigDecimal FREE116) {
+        this.FREE116 = FREE116.doubleValue();
+    }
+    public double FREE117;
+
+    public BigDecimal getFREE117() {
+        return new BigDecimal(FREE117);
+    }
+
+    public void setFREE117(BigDecimal FREE117) {
+        this.FREE117 = FREE117.doubleValue();
+    }
+    public double FREE118;
+
+    public BigDecimal getFREE118() {
+        return new BigDecimal(FREE118);
+    }
+
+    public void setFREE118(BigDecimal FREE118) {
+        this.FREE118 = FREE118.doubleValue();
+    }
+    public double FREE119;
+
+    public BigDecimal getFREE119() {
+        return new BigDecimal(FREE119);
+    }
+
+    public void setFREE119(BigDecimal FREE119) {
+        this.FREE119 = FREE119.doubleValue();
+    }
+    public double FREE120;
+
+    public BigDecimal getFREE120() {
+        return new BigDecimal(FREE120);
+    }
+
+    public void setFREE120(BigDecimal FREE120) {
+        this.FREE120 = FREE120.doubleValue();
+    }
+
+}

+ 292 - 0
jeecg-boot-base/jeecg-boot-base-api/jeecg-system-local-api/src/main/java/org/jeecg/common/system/api/ISysBaseAPI.java

@@ -0,0 +1,292 @@
+package org.jeecg.common.system.api;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import org.jeecg.common.api.CommonAPI;
+import org.jeecg.common.api.dto.OnlineAuthDTO;
+import org.jeecg.common.api.dto.message.*;
+import org.jeecg.common.system.vo.*;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @Description  底层共通业务API,提供其他独立模块调用
+ * @Author  scott
+ * @Date 2019-4-20
+ * @Version V1.0
+ */
+public interface ISysBaseAPI extends CommonAPI {
+
+
+    /**
+     * 1发送系统消息
+     * @param message 使用构造器赋值参数 如果不设置category(消息类型)则默认为2 发送系统消息
+     */
+    void sendSysAnnouncement(MessageDTO message);
+
+    /**
+     * 2发送消息 附带业务参数
+     * @param message 使用构造器赋值参数
+     */
+    void sendBusAnnouncement(BusMessageDTO message);
+
+    /**
+     * 3通过模板发送消息
+     * @param message 使用构造器赋值参数
+     */
+    void sendTemplateAnnouncement(TemplateMessageDTO message);
+
+    /**
+     * 4通过模板发送消息 附带业务参数
+     * @param message 使用构造器赋值参数
+     */
+    void sendBusTemplateAnnouncement(BusTemplateMessageDTO message);
+
+    /**
+     * 5通过消息中心模板,生成推送内容
+     * @param templateDTO 使用构造器赋值参数
+     * @return
+     */
+    String parseTemplateByCode(TemplateDTO templateDTO);
+
+    /**
+     * 6根据用户id查询用户信息
+     * @param id
+     * @return
+     */
+    LoginUser getUserById(String id);
+
+    /**
+     * 7通过用户账号查询角色集合
+     * @param username
+     * @return
+     */
+    List<String> getRolesByUsername(String username);
+
+    /**
+     * 8通过用户账号查询部门集合
+     * @param username
+     * @return 部门 id
+     */
+    List<String> getDepartIdsByUsername(String username);
+
+    /**
+     * 9通过用户账号查询部门 name
+     * @param username
+     * @return 部门 name
+     */
+    List<String> getDepartNamesByUsername(String username);
+
+
+
+    /** 11查询所有的父级字典,按照create_time排序 */
+    public List<DictModel> queryAllDict();
+
+    /**
+     * 12查询所有分类字典
+     * @return
+     */
+    public List<SysCategoryModel> queryAllDSysCategory();
+
+
+    /**
+     * 14查询所有部门 作为字典信息 id -->value,departName -->text
+     * @return
+     */
+    public List<DictModel> queryAllDepartBackDictModel();
+
+    /**
+     * 15根据业务类型及业务id修改消息已读
+     * @param busType
+     * @param busId
+     */
+    public void updateSysAnnounReadFlag(String busType, String busId);
+
+    /**
+     * 16查询表字典 支持过滤数据
+     * @param table
+     * @param text
+     * @param code
+     * @param filterSql
+     * @return
+     */
+    public List<DictModel> queryFilterTableDictInfo(String table, String text, String code, String filterSql);
+
+    /**
+     * 17查询指定table的 text code 获取字典,包含text和value
+     * @param table
+     * @param text
+     * @param code
+     * @param keyArray
+     * @return
+     */
+    @Deprecated
+    public List<String> queryTableDictByKeys(String table, String text, String code, String[] keyArray);
+
+    /**
+     * 18查询所有用户 返回ComboModel
+     * @return
+     */
+    public List<ComboModel> queryAllUserBackCombo();
+
+    /**
+     * 19分页查询用户 返回JSONObject
+     * @return
+     */
+    public JSONObject queryAllUser(String userIds, Integer pageNo, Integer pageSize);
+
+    /**
+     * 20获取所有角色
+     * @return
+     */
+    public List<ComboModel> queryAllRole();
+
+    /**
+     * 21获取所有角色 带参
+     * roleIds 默认选中角色
+     * @return
+     */
+    public List<ComboModel> queryAllRole(String[] roleIds );
+
+    /**
+     * 22通过用户账号查询角色Id集合
+     * @param username
+     * @return
+     */
+    public List<String> getRoleIdsByUsername(String username);
+
+    /**
+     * 23通过部门编号查询部门id
+     * @param orgCode
+     * @return
+     */
+    public String getDepartIdsByOrgCode(String orgCode);
+
+    /**
+     * 24查询所有部门
+     * @return
+     */
+    public List<SysDepartModel> getAllSysDepart();
+
+    /**
+     * 25查找父级部门
+     * @param departId
+     * @return
+     */
+    DictModel getParentDepartId(String departId);
+
+    /**
+     * 26根据部门Id获取部门负责人
+     * @param deptId
+     * @return
+     */
+    public List<String> getDeptHeadByDepId(String deptId);
+
+    /**
+     * 27给指定用户发消息
+     * @param userIds
+     * @param cmd
+     */
+    public void sendWebSocketMsg(String[] userIds, String cmd);
+
+    /**
+     * 28根据id获取所有参与用户
+     * userIds
+     * @return
+     */
+    public List<LoginUser> queryAllUserByIds(String[] userIds);
+
+    /**
+     * 29将会议签到信息推动到预览
+     * userIds
+     * @return
+     * @param userId
+     */
+    void meetingSignWebsocket(String userId);
+
+    /**
+     * 30根据name获取所有参与用户
+     * userNames
+     * @return
+     */
+    List<LoginUser> queryUserByNames(String[] userNames);
+
+
+    /**
+     * 31获取用户的角色集合
+     * @param username
+     * @return
+     */
+    Set<String> getUserRoleSet(String username);
+
+    /**
+     * 32获取用户的权限集合
+     * @param username
+     * @return
+     */
+    Set<String> getUserPermissionSet(String username);
+
+    /**
+     * 33判断是否有online访问的权限
+     * @param onlineAuthDTO
+     * @return
+     */
+    boolean hasOnlineAuth(OnlineAuthDTO onlineAuthDTO);
+
+    /**
+     * 34通过部门id获取部门全部信息
+     */
+    SysDepartModel selectAllById(String id);
+
+    /**
+     * 35根据用户id查询用户所属公司下所有用户ids
+     * @param userId
+     * @return
+     */
+    List<String> queryDeptUsersByUserId(String userId);
+
+    /**
+     * 36根据多个用户账号(逗号分隔),查询返回多个用户信息
+     * @param usernames
+     * @return
+     */
+    List<JSONObject> queryUsersByUsernames(String usernames);
+
+    /**
+     * 37根据多个用户ID(逗号分隔),查询返回多个用户信息
+     * @param ids
+     * @return
+     */
+    List<JSONObject> queryUsersByIds(String ids);
+
+    /**
+     * 38根据多个部门编码(逗号分隔),查询返回多个部门信息
+     * @param orgCodes
+     * @return
+     */
+    List<JSONObject> queryDepartsByOrgcodes(String orgCodes);
+
+    /**
+     * 39根据多个部门id(逗号分隔),查询返回多个部门信息
+     * @param ids
+     * @return
+     */
+    List<JSONObject> queryDepartsByIds(String ids);
+
+    /**
+     * 40发送邮件消息
+     * @param email
+     * @param title
+     * @param content
+     */
+    void sendEmailMsg(String email,String title,String content);
+    /**
+     * 41 获取公司下级部门和公司下所有用户信息
+     * @param orgCode
+     */
+    List<Map> getDeptUserByOrgCode(String orgCode);
+}

+ 26 - 0
jeecg-boot-base/jeecg-boot-base-api/pom.xml

@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>jeecg-boot-base</artifactId>
+        <groupId>org.jeecgframework.boot</groupId>
+        <version>2.4.5</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>jeecg-boot-base-api</artifactId>
+    <packaging>pom</packaging>
+
+    <modules>
+        <module>jeecg-system-local-api</module>
+        <module>jeecg-system-cloud-api</module>
+    </modules>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.jeecgframework.boot</groupId>
+            <artifactId>jeecg-boot-base-core</artifactId>
+        </dependency>
+    </dependencies>
+</project>

+ 243 - 0
jeecg-boot-base/jeecg-boot-base-core/pom.xml

@@ -0,0 +1,243 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<parent>
+		<groupId>org.jeecgframework.boot</groupId>
+		<artifactId>jeecg-boot-base</artifactId>
+		<version>2.4.5</version>
+	</parent>
+	<modelVersion>4.0.0</modelVersion>
+
+	<artifactId>jeecg-boot-base-core</artifactId>
+
+	<repositories>
+		<repository>
+			<id>aliyun</id>
+			<name>aliyun Repository</name>
+			<url>http://maven.aliyun.com/nexus/content/groups/public</url>
+			<snapshots>
+				<enabled>false</enabled>
+			</snapshots>
+		</repository>
+		<repository>
+			<id>jeecg</id>
+			<name>jeecg Repository</name>
+			<url>http://maven.jeecg.org/nexus/content/repositories/jeecg</url>
+			<snapshots>
+				<enabled>false</enabled>
+			</snapshots>
+		</repository>
+	</repositories>
+
+
+	<dependencies>
+		<!--jeecg-tools-->
+		<dependency>
+			<groupId>org.jeecgframework.boot</groupId>
+			<artifactId>jeecg-boot-base-tools</artifactId>
+		</dependency>
+		<!--集成springmvc框架并实现自动配置 -->
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-web</artifactId>
+		</dependency>
+		<!-- websocket -->
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-websocket</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-mail</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-aop</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-actuator</artifactId>
+		</dependency>
+		<!--springboot2.3+ 需引入validation对应的包-->
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-validation</artifactId>
+		</dependency>
+
+		<!-- commons -->
+		<dependency>
+			<groupId>commons-io</groupId>
+			<artifactId>commons-io</artifactId>
+			<version>${commons.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>commons-lang</groupId>
+			<artifactId>commons-lang</artifactId>
+			<version>${commons.version}</version>
+		</dependency>
+		<!-- freemarker -->
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-freemarker</artifactId>
+		</dependency>
+
+		<!-- mybatis-plus -->
+		<dependency>
+			<groupId>com.baomidou</groupId>
+			<artifactId>mybatis-plus-boot-starter</artifactId>
+			<version>${mybatis-plus.version}</version>
+		</dependency>
+
+		<!-- druid -->
+		<dependency>
+			<groupId>com.alibaba</groupId>
+			<artifactId>druid-spring-boot-starter</artifactId>
+			<version>${druid.version}</version>
+		</dependency>
+
+		<!-- 动态数据源 -->
+		<dependency>
+			<groupId>com.baomidou</groupId>
+			<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
+			<version>${dynamic-datasource-spring-boot-starter.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>org.hibernate</groupId>
+			<artifactId>hibernate-core</artifactId>
+			<exclusions>
+				<exclusion>
+					<groupId>commons-collections</groupId>
+					<artifactId>commons-collections</artifactId>
+				</exclusion>
+			</exclusions>
+		</dependency>
+		<dependency>
+			<groupId>org.jeecgframework.boot</groupId>
+			<artifactId>hibernate-re</artifactId>
+			<version>2.4.5-RC</version>
+		</dependency>
+
+		<!--mysql-->
+		<dependency>
+			<groupId>mysql</groupId>
+			<artifactId>mysql-connector-java</artifactId>
+			<version>${mysql-connector-java.version}</version>
+			<scope>runtime</scope>
+		</dependency>
+		<!--  sqlserver-->
+		<dependency>
+			<groupId>com.microsoft.sqlserver</groupId>
+			<artifactId>sqljdbc4</artifactId>
+			<version>${sqljdbc4.version}</version>
+			<scope>runtime</scope>
+		</dependency>
+		<!-- oracle驱动 -->
+		<dependency>
+			<groupId>com.oracle</groupId>
+			<artifactId>ojdbc6</artifactId>
+			<version>${ojdbc6.version}</version>
+			<scope>runtime</scope>
+		</dependency>
+		<!-- postgresql驱动 -->
+		<dependency>
+			<groupId>org.postgresql</groupId>
+			<artifactId>postgresql</artifactId>
+			<version>${postgresql.version}</version>
+			<scope>runtime</scope>
+		</dependency>
+
+		<!-- Quartz定时任务 -->
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-quartz</artifactId>
+		</dependency>
+
+		<!--JWT-->
+		<dependency>
+			<groupId>com.auth0</groupId>
+			<artifactId>java-jwt</artifactId>
+			<version>${java-jwt.version}</version>
+		</dependency>
+
+		<!--shiro-->
+		<dependency>
+			<groupId>org.apache.shiro</groupId>
+			<artifactId>shiro-spring-boot-starter</artifactId>
+			<version>${shiro.version}</version>
+		</dependency>
+		<!-- shiro-redis -->
+		<dependency>
+			<groupId>org.crazycake</groupId>
+			<artifactId>shiro-redis</artifactId>
+			<version>${shiro-redis.version}</version>
+			<exclusions>
+				<exclusion>
+					<groupId>org.apache.shiro</groupId>
+					<artifactId>shiro-core</artifactId>
+				</exclusion>
+			</exclusions>
+		</dependency>
+
+		<!-- knife4j -->
+		<dependency>
+			<groupId>com.github.xiaoymin</groupId>
+			<artifactId>knife4j-spring-boot-starter</artifactId>
+			<version>${knife4j-spring-boot-starter.version}</version>
+		</dependency>
+
+		<!-- 代码生成器 -->
+		<!-- 如下载失败,请参考此文档  http://doc.jeecg.com/2043876 -->
+		<dependency>
+			<groupId>org.jeecgframework.boot</groupId>
+			<artifactId>codegenerate</artifactId>
+			<version>${codegenerate.version}</version>
+		</dependency>
+
+		<!-- AutoPoi Excel工具类-->
+		<dependency>
+			<groupId>org.jeecgframework</groupId>
+			<artifactId>autopoi-web</artifactId>
+			<version>${autopoi-web.version}</version>
+			<exclusions>
+				<exclusion>
+					<groupId>commons-codec</groupId>
+					<artifactId>commons-codec</artifactId>
+				</exclusion>
+			</exclusions>
+		</dependency>
+
+		<!-- mini文件存储服务 -->
+		<dependency>
+			<groupId>io.minio</groupId>
+			<artifactId>minio</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>com.google.guava</groupId>
+			<artifactId>guava</artifactId>
+			<version>${guava.version}</version>
+		</dependency>
+
+		<!-- 阿里云短信 -->
+		<dependency>
+			<groupId>com.aliyun</groupId>
+			<artifactId>aliyun-java-sdk-dysmsapi</artifactId>
+			<version>${aliyun-java-sdk-dysmsapi.version}</version>
+		</dependency>
+		<!-- aliyun oss -->
+		<dependency>
+			<groupId>com.aliyun.oss</groupId>
+			<artifactId>aliyun-sdk-oss</artifactId>
+			<version>${aliyun.oss.version}</version>
+		</dependency>
+		<!-- 第三方登录  -->
+		<dependency>
+			<groupId>com.xkcoding.justauth</groupId>
+			<artifactId>justauth-spring-boot-starter</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>com.squareup.okhttp3</groupId>
+			<artifactId>okhttp</artifactId>
+		</dependency>
+	</dependencies>
+
+</project>

+ 97 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/api/CommonAPI.java

@@ -0,0 +1,97 @@
+package org.jeecg.common.api;
+
+import org.jeecg.common.system.vo.*;
+
+import java.util.List;
+import java.util.Set;
+
+public interface CommonAPI {
+
+    /**
+     * 1查询用户角色信息
+     * @param username
+     * @return
+     */
+    Set<String> queryUserRoles(String username);
+
+
+    /**
+     * 2查询用户权限信息
+     * @param username
+     * @return
+     */
+    Set<String> queryUserAuths(String username);
+
+    /**
+     * 3根据 id 查询数据库中存储的 DynamicDataSourceModel
+     *
+     * @param dbSourceId
+     * @return
+     */
+    DynamicDataSourceModel getDynamicDbSourceById(String dbSourceId);
+
+    /**
+     * 4根据 code 查询数据库中存储的 DynamicDataSourceModel
+     *
+     * @param dbSourceCode
+     * @return
+     */
+    DynamicDataSourceModel getDynamicDbSourceByCode(String dbSourceCode);
+
+    /**
+     * 5根据用户账号查询用户信息
+     * @param username
+     * @return
+     */
+    public LoginUser getUserByName(String username);
+
+
+    /**
+     * 6字典表的 翻译
+     * @param table
+     * @param text
+     * @param code
+     * @param key
+     * @return
+     */
+    String translateDictFromTable(String table, String text, String code, String key);
+
+    /**
+     * 7普通字典的翻译
+     * @param code
+     * @param key
+     * @return
+     */
+    String translateDict(String code, String key);
+
+    /**
+     * 8查询数据权限
+     * @return
+     */
+    List<SysPermissionDataRuleModel> queryPermissionDataRule(String component, String requestPath, String username);
+
+
+    /**
+     * 9查询用户信息
+     * @param username
+     * @return
+     */
+    SysUserCacheInfo getCacheUser(String username);
+
+    /**
+     * 10获取数据字典
+     * @param code
+     * @return
+     */
+    public List<DictModel> queryDictItemsByCode(String code);
+
+    /**
+     * 13获取表数据字典
+     * @param table
+     * @param text
+     * @param code
+     * @return
+     */
+    List<DictModel> queryTableDictItemsByCode(String table, String text, String code);
+
+}

+ 24 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/api/IWpsBaseAPI.java

@@ -0,0 +1,24 @@
+package org.jeecg.common.api;
+
+import org.jeecg.common.api.vo.OaWpsModel;
+
+/**
+ * @Description: WPS通用接口
+ * @Author: wangshuai
+ * @Date:20200709
+ * @Version:V1.0
+ */
+public interface IWpsBaseAPI {
+
+  /*根据模板id获取模板信息*/
+  OaWpsModel getById(String id);
+
+  /*根据文件路径下载文件*/
+ void downloadOosFiles(String objectName, String basePath,String fileName);
+
+ /*WPS 设置数据存储,用于逻辑判断*/
+ void context(String type,String text);
+
+ /*删除WPS模板相关信息*/
+ void deleteById(String id);
+}

+ 47 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/api/desform/ISysTranslateAPI.java

@@ -0,0 +1,47 @@
+package org.jeecg.common.api.desform;
+
+import org.jeecg.common.system.vo.DictModel;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 表单设计器【System】翻译API接口
+ *
+ * @author sunjianlei
+ */
+public interface ISysTranslateAPI {
+
+    /**
+     * 查询分类字典翻译
+     */
+    List<String> categoryLoadDictItem(String ids);
+
+    /**
+     * 根据字典code加载字典text
+     *
+     * @param dictCode 顺序:tableName,text,code
+     * @param keys     要查询的key
+     * @return
+     */
+    List<String> dictLoadDictItem(String dictCode, String keys);
+
+    /**
+     * 获取字典数据
+     *
+     * @param dictCode 顺序:tableName,text,code
+     * @param dictCode 要查询的key
+     * @return
+     */
+    List<DictModel> dictGetDictItems(String dictCode);
+
+    /**
+     * 【JSearchSelectTag下拉搜索组件专用接口】
+     * 大数据量的字典表 走异步加载  即前端输入内容过滤数据
+     *
+     * @param dictCode 字典code格式:table,text,code
+     * @return
+     */
+    List<DictModel> dictLoadDict(String dictCode, String keyword, Integer pageSize);
+
+}

+ 30 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/api/dto/FileDownDTO.java

@@ -0,0 +1,30 @@
+package org.jeecg.common.api.dto;
+
+import lombok.Data;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.Serializable;
+
+/**
+ * 文件下载
+ * cloud api 用到的接口传输对象
+ */
+@Data
+public class FileDownDTO implements Serializable {
+
+    private static final long serialVersionUID = 6749126258686446019L;
+
+    private String filePath;
+    private String uploadpath;
+    private String uploadType;
+    private HttpServletResponse response;
+
+    public FileDownDTO(){}
+
+    public FileDownDTO(String filePath, String uploadpath, String uploadType,HttpServletResponse response){
+        this.filePath = filePath;
+        this.uploadpath = uploadpath;
+        this.uploadType = uploadType;
+        this.response = response;
+    }
+}

+ 55 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/api/dto/FileUploadDTO.java

@@ -0,0 +1,55 @@
+package org.jeecg.common.api.dto;
+
+import lombok.Data;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.Serializable;
+
+/**
+ * 文件上传
+ * cloud api 用到的接口传输对象
+ */
+@Data
+public class FileUploadDTO implements Serializable {
+
+    private static final long serialVersionUID = -4111953058578954386L;
+
+    private MultipartFile file;
+
+    private String bizPath;
+
+    private String uploadType;
+
+    private String customBucket;
+
+    public FileUploadDTO(){
+
+    }
+
+    /**
+     * 简单上传 构造器1
+     * @param file
+     * @param bizPath
+     * @param uploadType
+     */
+    public FileUploadDTO(MultipartFile file,String bizPath,String uploadType){
+        this.file = file;
+        this.bizPath = bizPath;
+        this.uploadType = uploadType;
+    }
+
+    /**
+     * 申明桶 文件上传 构造器2
+     * @param file
+     * @param bizPath
+     * @param uploadType
+     * @param customBucket
+     */
+    public FileUploadDTO(MultipartFile file,String bizPath,String uploadType,String customBucket){
+        this.file = file;
+        this.bizPath = bizPath;
+        this.uploadType = uploadType;
+        this.customBucket = customBucket;
+    }
+
+}

+ 68 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/api/dto/LogDTO.java

@@ -0,0 +1,68 @@
+package org.jeecg.common.api.dto;
+import lombok.Data;
+import org.jeecg.common.system.vo.LoginUser;
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * 日志对象
+ * cloud api 用到的接口传输对象
+ */
+@Data
+public class LogDTO implements Serializable {
+
+    private static final long serialVersionUID = 8482720462943906924L;
+
+    /**内容*/
+    private String logContent;
+
+    /**日志类型(0:操作日志;1:登录日志;2:定时任务)  */
+    private Integer logType;
+
+    /**操作类型(1:添加;2:修改;3:删除;) */
+    private Integer operateType;
+
+    /**登录用户 */
+    private LoginUser loginUser;
+
+    private String id;
+    private String createBy;
+    private Date createTime;
+    private Long costTime;
+    private String ip;
+
+    /**请求参数 */
+    private String requestParam;
+
+    /**请求类型*/
+    private String requestType;
+
+    /**请求路径*/
+    private String requestUrl;
+
+    /**请求方法 */
+    private String method;
+
+    /**操作人用户名称*/
+    private String username;
+
+    /**操作人用户账户*/
+    private String userid;
+
+    public LogDTO(){
+
+    }
+
+    public LogDTO(String logContent, Integer logType, Integer operatetype){
+        this.logContent = logContent;
+        this.logType = logType;
+        this.operateType = operatetype;
+    }
+
+    public LogDTO(String logContent, Integer logType, Integer operatetype, LoginUser loginUser){
+        this.logContent = logContent;
+        this.logType = logType;
+        this.operateType = operatetype;
+        this.loginUser = loginUser;
+    }
+}

+ 41 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/api/dto/OnlineAuthDTO.java

@@ -0,0 +1,41 @@
+package org.jeecg.common.api.dto;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * online 拦截器权限判断
+ * cloud api 用到的接口传输对象
+ */
+@Data
+public class OnlineAuthDTO implements Serializable {
+    private static final long serialVersionUID = 1771827545416418203L;
+
+
+    /**
+     * 用户名
+     */
+    private String username;
+
+    /**
+     * 可能的请求地址
+     */
+    private List<String> possibleUrl;
+
+    /**
+     * online开发的菜单地址
+     */
+    private String onlineFormUrl;
+
+    public OnlineAuthDTO(){
+
+    }
+
+    public OnlineAuthDTO(String username, List<String> possibleUrl, String onlineFormUrl){
+        this.username = username;
+        this.possibleUrl = possibleUrl;
+        this.onlineFormUrl = onlineFormUrl;
+    }
+}

+ 43 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/api/dto/message/BusMessageDTO.java

@@ -0,0 +1,43 @@
+package org.jeecg.common.api.dto.message;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * 带业务参数的消息
+ */
+@Data
+public class BusMessageDTO extends MessageDTO implements Serializable {
+
+    private static final long serialVersionUID = 9104793287983367669L;
+    /**
+     * 业务类型
+     */
+    private String busType;
+
+    /**
+     * 业务id
+     */
+    private String busId;
+
+    public BusMessageDTO(){
+
+    }
+
+    /**
+     * 构造 带业务参数的消息
+     * @param fromUser
+     * @param toUser
+     * @param title
+     * @param msgContent
+     * @param msgCategory
+     * @param busType
+     * @param busId
+     */
+    public BusMessageDTO(String fromUser, String toUser, String title, String msgContent, String msgCategory, String busType, String busId){
+        super(fromUser, toUser, title, msgContent, msgCategory);
+        this.busId = busId;
+        this.busType = busType;
+    }
+}

+ 45 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/api/dto/message/BusTemplateMessageDTO.java

@@ -0,0 +1,45 @@
+package org.jeecg.common.api.dto.message;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Map;
+
+/**
+ * 带业务参数的模板消息
+ */
+@Data
+public class BusTemplateMessageDTO extends TemplateMessageDTO implements Serializable {
+
+    private static final long serialVersionUID = -4277810906346929459L;
+
+    /**
+     * 业务类型
+     */
+    private String busType;
+
+    /**
+     * 业务id
+     */
+    private String busId;
+
+    public BusTemplateMessageDTO(){
+
+    }
+
+    /**
+     * 构造 带业务参数的模板消息
+     * @param fromUser
+     * @param toUser
+     * @param title
+     * @param templateParam
+     * @param templateCode
+     * @param busType
+     * @param busId
+     */
+    public BusTemplateMessageDTO(String fromUser, String toUser, String title, Map<String, String> templateParam, String templateCode, String busType, String busId){
+        super(fromUser, toUser, title, templateParam, templateCode);
+        this.busId = busId;
+        this.busType = busType;
+    }
+}

+ 74 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/api/dto/message/MessageDTO.java

@@ -0,0 +1,74 @@
+package org.jeecg.common.api.dto.message;
+
+import lombok.Data;
+import org.jeecg.common.constant.CommonConstant;
+
+import java.io.Serializable;
+
+/**
+ * 普通消息
+ */
+@Data
+public class MessageDTO implements Serializable {
+
+    private static final long serialVersionUID = -5690444483968058442L;
+
+    /**
+     * 发送人(用户登录账户)
+     */
+    protected String fromUser;
+
+    /**
+     * 发送给(用户登录账户)
+     */
+    protected String toUser;
+
+    /**
+     * 发送给所有人
+     */
+    protected boolean toAll;
+
+    /**
+     * 消息主题
+     */
+    protected String title;
+
+    /**
+     * 消息内容
+     */
+    protected String content;
+
+    /**
+     * 消息类型 1:消息  2:系统消息
+     */
+    protected String category;
+
+
+    public MessageDTO(){
+
+    }
+
+    /**
+     * 构造器1 系统消息
+     */
+    public MessageDTO(String fromUser,String toUser,String title, String content){
+        this.fromUser = fromUser;
+        this.toUser = toUser;
+        this.title = title;
+        this.content = content;
+        //默认 都是2系统消息
+        this.category = CommonConstant.MSG_CATEGORY_2;
+    }
+
+    /**
+     * 构造器2 支持设置category 1:消息  2:系统消息
+     */
+    public MessageDTO(String fromUser,String toUser,String title, String content, String category){
+        this.fromUser = fromUser;
+        this.toUser = toUser;
+        this.title = title;
+        this.content = content;
+        this.category = category;
+    }
+
+}

+ 37 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/api/dto/message/TemplateDTO.java

@@ -0,0 +1,37 @@
+package org.jeecg.common.api.dto.message;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Map;
+
+/**
+ * 消息模板dto
+ */
+@Data
+public class TemplateDTO implements Serializable {
+
+    private static final long serialVersionUID = 5848247133907528650L;
+
+    /**
+     * 模板编码
+     */
+    protected String templateCode;
+
+    /**
+     * 模板参数
+     */
+    protected Map<String, String> templateParam;
+
+    /**
+     * 构造器 通过设置模板参数和模板编码 作为参数获取消息内容
+     */
+    public TemplateDTO(String templateCode, Map<String, String> templateParam){
+        this.templateCode = templateCode;
+        this.templateParam = templateParam;
+    }
+
+    public TemplateDTO(){
+
+    }
+}

+ 48 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/api/dto/message/TemplateMessageDTO.java

@@ -0,0 +1,48 @@
+package org.jeecg.common.api.dto.message;
+
+import lombok.Data;
+import java.io.Serializable;
+import java.util.Map;
+
+/**
+ * 模板消息
+ */
+@Data
+public class TemplateMessageDTO extends TemplateDTO implements Serializable {
+
+    private static final long serialVersionUID = 411137565170647585L;
+
+
+    /**
+     * 发送人(用户登录账户)
+     */
+    protected String fromUser;
+
+    /**
+     * 发送给(用户登录账户)
+     */
+    protected String toUser;
+
+    /**
+     * 消息主题
+     */
+    protected String title;
+
+
+    public TemplateMessageDTO(){
+
+    }
+
+    /**
+     * 构造器1 发模板消息用
+     */
+    public TemplateMessageDTO(String fromUser, String toUser,String title, Map<String, String> templateParam, String templateCode){
+        super(templateCode, templateParam);
+        this.fromUser = fromUser;
+        this.toUser = toUser;
+        this.title = title;
+    }
+
+
+
+}

+ 107 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/api/vo/OaWpsModel.java

@@ -0,0 +1,107 @@
+package org.jeecg.common.api.vo;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+import org.jeecgframework.poi.excel.annotation.Excel;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * @Description: 文档
+ * @Author: jeecg-boot
+ * @Date: 2020-06-09
+ * @Version: V1.0
+ */
+@Data
+@TableName("oa_wps_file")
+@Accessors(chain = true)
+@EqualsAndHashCode(callSuper = false)
+@ApiModel(value = "oa_wps_file对象", description = "文档")
+public class OaWpsModel implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * id
+     */
+    @TableId(type = IdType.ASSIGN_ID)
+    @ApiModelProperty(value = "id")
+    private String id;
+    /**
+     * name
+     */
+    @Excel(name = "name", width = 15)
+    @ApiModelProperty(value = "name")
+    private String name;
+    /**
+     * version
+     */
+    @Excel(name = "version", width = 15)
+    @ApiModelProperty(value = "version")
+    private Integer version;
+    /**
+     * size
+     */
+    @Excel(name = "size", width = 15)
+    @ApiModelProperty(value = "size")
+    private Integer size;
+    /**
+     * downloadUrl
+     */
+    @Excel(name = "downloadUrl", width = 15)
+    @ApiModelProperty(value = "downloadUrl")
+    private String downloadUrl;
+    /**
+     * deleted
+     */
+    @Excel(name = "deleted", width = 15)
+    @ApiModelProperty(value = "deleted")
+    private String deleted;
+    /**
+     * canDelete
+     */
+    @Excel(name = "canDelete", width = 15)
+    @ApiModelProperty(value = "canDelete")
+    private String canDelete;
+    /**
+     * 创建人
+     */
+    @ApiModelProperty(value = "创建人")
+    private String createBy;
+    /**
+     * 创建时间
+     */
+    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    @ApiModelProperty(value = "创建时间")
+    private Date createTime;
+    /**
+     * 更新人
+     */
+    @ApiModelProperty(value = "更新人")
+    private String updateBy;
+    /**
+     * 更新时间
+     */
+    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    @ApiModelProperty(value = "更新时间")
+    private Date updateTime;
+    /**
+     * 组织机构编码
+     */
+    @ApiModelProperty(value = "组织机构编码")
+    private String sysOrgCode;
+
+    @TableField(exist = false)
+    private String userId;
+}

+ 153 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/api/vo/Result.java

@@ -0,0 +1,153 @@
+package org.jeecg.common.api.vo;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.jeecg.common.constant.CommonConstant;
+
+import java.io.Serializable;
+
+/**
+ *   接口返回数据格式
+ * @author scott
+ * @email jeecgos@163.com
+ * @date  2019年1月19日
+ */
+@Data
+@ApiModel(value="接口返回对象", description="接口返回对象")
+public class Result<T> implements Serializable {
+
+	private static final long serialVersionUID = 1L;
+
+	/**
+	 * 成功标志
+	 */
+	@ApiModelProperty(value = "成功标志")
+	private boolean success = true;
+
+	/**
+	 * 返回处理消息
+	 */
+	@ApiModelProperty(value = "返回处理消息")
+	private String message = "操作成功!";
+
+	/**
+	 * 返回代码
+	 */
+	@ApiModelProperty(value = "返回代码")
+	private Integer code = 0;
+	
+	/**
+	 * 返回数据对象 data
+	 */
+	@ApiModelProperty(value = "返回数据对象")
+	private T result;
+	
+	/**
+	 * 时间戳
+	 */
+	@ApiModelProperty(value = "时间戳")
+	private long timestamp = System.currentTimeMillis();
+
+	public Result() {
+		
+	}
+	
+	public Result<T> success(String message) {
+		this.message = message;
+		this.code = CommonConstant.SC_OK_200;
+		this.success = true;
+		return this;
+	}
+
+	@Deprecated
+	public static Result<Object> ok() {
+		Result<Object> r = new Result<Object>();
+		r.setSuccess(true);
+		r.setCode(CommonConstant.SC_OK_200);
+		r.setMessage("成功");
+		return r;
+	}
+
+	@Deprecated
+	public static Result<Object> ok(String msg) {
+		Result<Object> r = new Result<Object>();
+		r.setSuccess(true);
+		r.setCode(CommonConstant.SC_OK_200);
+		r.setMessage(msg);
+		return r;
+	}
+
+	@Deprecated
+	public static Result<Object> ok(Object data) {
+		Result<Object> r = new Result<Object>();
+		r.setSuccess(true);
+		r.setCode(CommonConstant.SC_OK_200);
+		r.setResult(data);
+		return r;
+	}
+
+	public static<T> Result<T> OK() {
+		Result<T> r = new Result<T>();
+		r.setSuccess(true);
+		r.setCode(CommonConstant.SC_OK_200);
+		r.setMessage("成功");
+		return r;
+	}
+
+	public static<T> Result<T> OK(T data) {
+		Result<T> r = new Result<T>();
+		r.setSuccess(true);
+		r.setCode(CommonConstant.SC_OK_200);
+		r.setResult(data);
+		return r;
+	}
+
+	public static<T> Result<T> OK(String msg, T data) {
+		Result<T> r = new Result<T>();
+		r.setSuccess(true);
+		r.setCode(CommonConstant.SC_OK_200);
+		r.setMessage(msg);
+		r.setResult(data);
+		return r;
+	}
+
+	public static<T> Result<T> error(String msg, T data) {
+		Result<T> r = new Result<T>();
+		r.setSuccess(false);
+		r.setCode(CommonConstant.SC_INTERNAL_SERVER_ERROR_500);
+		r.setMessage(msg);
+		r.setResult(data);
+		return r;
+	}
+
+	public static Result<Object> error(String msg) {
+		return error(CommonConstant.SC_INTERNAL_SERVER_ERROR_500, msg);
+	}
+	
+	public static Result<Object> error(int code, String msg) {
+		Result<Object> r = new Result<Object>();
+		r.setCode(code);
+		r.setMessage(msg);
+		r.setSuccess(false);
+		return r;
+	}
+
+	public Result<T> error500(String message) {
+		this.message = message;
+		this.code = CommonConstant.SC_INTERNAL_SERVER_ERROR_500;
+		this.success = false;
+		return this;
+	}
+	/**
+	 * 无权限访问返回结果
+	 */
+	public static Result<Object> noauth(String msg) {
+		return error(CommonConstant.SC_JEECG_NO_AUTHZ, msg);
+	}
+
+	@JsonIgnore
+	private String onlTable;
+
+}

+ 270 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/aspect/AutoLogAspect.java

@@ -0,0 +1,270 @@
+package org.jeecg.common.aspect;
+
+import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson.serializer.PropertyFilter;
+import org.apache.shiro.SecurityUtils;
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.aspectj.lang.reflect.MethodSignature;
+import org.jeecg.common.api.dto.LogDTO;
+import org.jeecg.common.api.vo.Result;
+import org.jeecg.common.aspect.annotation.AutoLog;
+import org.jeecg.common.constant.CommonConstant;
+import org.jeecg.common.constant.enums.ModuleType;
+import org.jeecg.modules.base.service.BaseCommonService;
+import org.jeecg.common.system.vo.LoginUser;
+import org.jeecg.common.util.IPUtils;
+import org.jeecg.common.util.SpringContextUtils;
+import org.jeecg.common.util.oConvertUtils;
+import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
+import org.springframework.stereotype.Component;
+import org.springframework.validation.BindingResult;
+import org.springframework.web.multipart.MultipartFile;
+import javax.annotation.Resource;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import java.lang.reflect.Method;
+import java.util.Date;
+
+
+/**
+ * 系统日志,切面处理类
+ *
+ * @Author scott
+ * @email jeecgos@163.com
+ * @Date 2018年1月14日
+ */
+@Aspect
+@Component
+public class AutoLogAspect {
+
+    @Resource
+    private BaseCommonService baseCommonService;
+
+    @Pointcut("@annotation(org.jeecg.common.aspect.annotation.AutoLog)")
+    public void logPointCut() {
+
+    }
+
+    @Around("logPointCut()")
+    public Object around(ProceedingJoinPoint point) throws Throwable {
+        long beginTime = System.currentTimeMillis();
+        //执行方法
+        Object result = point.proceed();
+        //执行时长(毫秒)
+        long time = System.currentTimeMillis() - beginTime;
+
+        //保存日志
+        saveSysLog(point, time, result);
+
+        return result;
+    }
+
+    private void saveSysLog(ProceedingJoinPoint joinPoint, long time, Object obj) {
+        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
+        Method method = signature.getMethod();
+
+        LogDTO dto = new LogDTO();
+        AutoLog syslog = method.getAnnotation(AutoLog.class);
+        if(syslog != null){
+            //update-begin-author:taoyan date:
+            String content = syslog.value();
+            if(syslog.module()== ModuleType.ONLINE){
+                content = getOnlineLogContent(obj, content);
+            }
+            //注解上的描述,操作日志内容
+            dto.setLogType(syslog.logType());
+            dto.setLogContent(content);
+        }
+
+        //请求的方法名
+        String className = joinPoint.getTarget().getClass().getName();
+        String methodName = signature.getName();
+        dto.setMethod(className + "." + methodName + "()");
+
+
+        //设置操作类型
+        if (dto.getLogType() == CommonConstant.LOG_TYPE_2) {
+            dto.setOperateType(getOperateType(methodName, syslog.operateType()));
+        }
+
+        //获取request
+        HttpServletRequest request = SpringContextUtils.getHttpServletRequest();
+        //请求的参数
+        dto.setRequestParam(getReqestParams(request,joinPoint));
+        //设置IP地址
+        dto.setIp(IPUtils.getIpAddr(request));
+        //获取登录用户信息
+        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
+        if(sysUser!=null){
+            dto.setUserid(sysUser.getUsername());
+            dto.setUsername(sysUser.getRealname());
+
+        }
+        //耗时
+        dto.setCostTime(time);
+        dto.setCreateTime(new Date());
+        //保存系统日志
+        baseCommonService.addLog(dto);
+    }
+
+
+    /**
+     * 获取操作类型
+     */
+    private int getOperateType(String methodName,int operateType) {
+        if (operateType > 0) {
+            return operateType;
+        }
+        if (methodName.startsWith("list")) {
+            return CommonConstant.OPERATE_TYPE_1;
+        }
+        if (methodName.startsWith("add")) {
+            return CommonConstant.OPERATE_TYPE_2;
+        }
+        if (methodName.startsWith("edit")) {
+            return CommonConstant.OPERATE_TYPE_3;
+        }
+        if (methodName.startsWith("delete")) {
+            return CommonConstant.OPERATE_TYPE_4;
+        }
+        if (methodName.startsWith("import")) {
+            return CommonConstant.OPERATE_TYPE_5;
+        }
+        if (methodName.startsWith("export")) {
+            return CommonConstant.OPERATE_TYPE_6;
+        }
+        return CommonConstant.OPERATE_TYPE_1;
+    }
+
+    /**
+     * @Description: 获取请求参数
+     * @author: scott
+     * @date: 2020/4/16 0:10
+     * @param request:  request
+     * @param joinPoint:  joinPoint
+     * @Return: java.lang.String
+     */
+    private String getReqestParams(HttpServletRequest request, JoinPoint joinPoint) {
+        String httpMethod = request.getMethod();
+        String params = "";
+        if ("POST".equals(httpMethod) || "PUT".equals(httpMethod) || "PATCH".equals(httpMethod)) {
+            Object[] paramsArray = joinPoint.getArgs();
+            // java.lang.IllegalStateException: It is illegal to call this method if the current request is not in asynchronous mode (i.e. isAsyncStarted() returns false)
+            //  https://my.oschina.net/mengzhang6/blog/2395893
+            Object[] arguments  = new Object[paramsArray.length];
+            for (int i = 0; i < paramsArray.length; i++) {
+                if (paramsArray[i] instanceof BindingResult || paramsArray[i] instanceof ServletRequest || paramsArray[i] instanceof ServletResponse || paramsArray[i] instanceof MultipartFile) {
+                    //ServletRequest不能序列化,从入参里排除,否则报异常:java.lang.IllegalStateException: It is illegal to call this method if the current request is not in asynchronous mode (i.e. isAsyncStarted() returns false)
+                    //ServletResponse不能序列化 从入参里排除,否则报异常:java.lang.IllegalStateException: getOutputStream() has already been called for this response
+                    continue;
+                }
+                arguments[i] = paramsArray[i];
+            }
+            //update-begin-author:taoyan date:20200724 for:日志数据太长的直接过滤掉
+            PropertyFilter profilter = new PropertyFilter() {
+                @Override
+                public boolean apply(Object o, String name, Object value) {
+                    if(value!=null && value.toString().length()>500){
+                        return false;
+                    }
+                    return true;
+                }
+            };
+            params = JSONObject.toJSONString(arguments, profilter);
+            //update-end-author:taoyan date:20200724 for:日志数据太长的直接过滤掉
+        } else {
+            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
+            Method method = signature.getMethod();
+            // 请求的方法参数值
+            Object[] args = joinPoint.getArgs();
+            // 请求的方法参数名称
+            LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer();
+            String[] paramNames = u.getParameterNames(method);
+            if (args != null && paramNames != null) {
+                for (int i = 0; i < args.length; i++) {
+                    params += "  " + paramNames[i] + ": " + args[i];
+                }
+            }
+        }
+        return params;
+    }
+
+    /**
+     * online日志内容拼接
+     * @param obj
+     * @param content
+     * @return
+     */
+    private String getOnlineLogContent(Object obj, String content){
+        if (Result.class.isInstance(obj)){
+            Result res = (Result)obj;
+            String msg = res.getMessage();
+            String tableName = res.getOnlTable();
+            if(oConvertUtils.isNotEmpty(tableName)){
+                content+=",表名:"+tableName;
+            }
+            if(res.isSuccess()){
+                content+= ","+(oConvertUtils.isEmpty(msg)?"操作成功":msg);
+            }else{
+                content+= ","+(oConvertUtils.isEmpty(msg)?"操作失败":msg);
+            }
+        }
+        return content;
+    }
+
+
+    /*    private void saveSysLog(ProceedingJoinPoint joinPoint, long time, Object obj) {
+        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
+        Method method = signature.getMethod();
+
+        SysLog sysLog = new SysLog();
+        AutoLog syslog = method.getAnnotation(AutoLog.class);
+        if(syslog != null){
+            //update-begin-author:taoyan date:
+            String content = syslog.value();
+            if(syslog.module()== ModuleType.ONLINE){
+                content = getOnlineLogContent(obj, content);
+            }
+            //注解上的描述,操作日志内容
+            sysLog.setLogContent(content);
+            sysLog.setLogType(syslog.logType());
+        }
+
+        //请求的方法名
+        String className = joinPoint.getTarget().getClass().getName();
+        String methodName = signature.getName();
+        sysLog.setMethod(className + "." + methodName + "()");
+
+
+        //设置操作类型
+        if (sysLog.getLogType() == CommonConstant.LOG_TYPE_2) {
+            sysLog.setOperateType(getOperateType(methodName, syslog.operateType()));
+        }
+
+        //获取request
+        HttpServletRequest request = SpringContextUtils.getHttpServletRequest();
+        //请求的参数
+        sysLog.setRequestParam(getReqestParams(request,joinPoint));
+
+        //设置IP地址
+        sysLog.setIp(IPUtils.getIpAddr(request));
+
+        //获取登录用户信息
+        LoginUser sysUser = (LoginUser)SecurityUtils.getSubject().getPrincipal();
+        if(sysUser!=null){
+            sysLog.setUserid(sysUser.getUsername());
+            sysLog.setUsername(sysUser.getRealname());
+
+        }
+        //耗时
+        sysLog.setCostTime(time);
+        sysLog.setCreateTime(new Date());
+        //保存系统日志
+        sysLogService.save(sysLog);
+    }*/
+}

+ 188 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/aspect/DictAspect.java

@@ -0,0 +1,188 @@
+package org.jeecg.common.aspect;
+
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import lombok.extern.slf4j.Slf4j;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.jeecg.common.api.CommonAPI;
+import org.jeecg.common.api.vo.Result;
+import org.jeecg.common.aspect.annotation.Dict;
+import org.jeecg.common.constant.CommonConstant;
+import org.jeecg.modules.base.service.BaseCommonService;
+import org.jeecg.common.util.oConvertUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
+import java.lang.reflect.Field;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @Description: 字典aop类
+ * @Author: dangzhenghui
+ * @Date: 2019-3-17 21:50
+ * @Version: 1.0
+ */
+@Aspect
+@Component
+@Slf4j
+public class DictAspect {
+
+    @Autowired
+    private CommonAPI commonAPI;
+    @Autowired
+    public RedisTemplate redisTemplate;
+
+    // 定义切点Pointcut
+    @Pointcut("execution(public * org.jeecg.modules..*.*Controller.*(..))")
+    public void excudeService() {
+    }
+
+    @Around("excudeService()")
+    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
+    	long time1=System.currentTimeMillis();	
+        Object result = pjp.proceed();
+        long time2=System.currentTimeMillis();
+        log.debug("获取JSON数据 耗时:"+(time2-time1)+"ms");
+        long start=System.currentTimeMillis();
+        this.parseDictText(result);
+        long end=System.currentTimeMillis();
+        log.debug("解析注入JSON数据  耗时"+(end-start)+"ms");
+        return result;
+    }
+
+    /**
+     * 本方法针对返回对象为Result 的IPage的分页列表数据进行动态字典注入
+     * 字典注入实现 通过对实体类添加注解@dict 来标识需要的字典内容,字典分为单字典code即可 ,table字典 code table text配合使用与原来jeecg的用法相同
+     * 示例为SysUser   字段为sex 添加了注解@Dict(dicCode = "sex") 会在字典服务立马查出来对应的text 然后在请求list的时候将这个字典text,已字段名称加_dictText形式返回到前端
+     * 例输入当前返回值的就会多出一个sex_dictText字段
+     * {
+     *      sex:1,
+     *      sex_dictText:"男"
+     * }
+     * 前端直接取值sext_dictText在table里面无需再进行前端的字典转换了
+     *  customRender:function (text) {
+     *               if(text==1){
+     *                 return "男";
+     *               }else if(text==2){
+     *                 return "女";
+     *               }else{
+     *                 return text;
+     *               }
+     *             }
+     *             目前vue是这么进行字典渲染到table上的多了就很麻烦了 这个直接在服务端渲染完成前端可以直接用
+     * @param result
+     */
+    private void parseDictText(Object result) {
+        if (result instanceof Result) {
+            if (((Result) result).getResult() instanceof IPage) {
+                List<JSONObject> items = new ArrayList<>();
+                for (Object record : ((IPage) ((Result) result).getResult()).getRecords()) {
+                    ObjectMapper mapper = new ObjectMapper();
+                    String json="{}";
+                    try {
+                        //解决@JsonFormat注解解析不了的问题详见SysAnnouncement类的@JsonFormat
+                         json = mapper.writeValueAsString(record);
+                    } catch (JsonProcessingException e) {
+                        log.error("json解析失败"+e.getMessage(),e);
+                    }
+                    JSONObject item = JSONObject.parseObject(json);
+                    //update-begin--Author:scott -- Date:20190603 ----for:解决继承实体字段无法翻译问题------
+                    //for (Field field : record.getClass().getDeclaredFields()) {
+                    for (Field field : oConvertUtils.getAllFields(record)) {
+                    //update-end--Author:scott  -- Date:20190603 ----for:解决继承实体字段无法翻译问题------
+                        if (field.getAnnotation(Dict.class) != null) {
+                            String code = field.getAnnotation(Dict.class).dicCode();
+                            String text = field.getAnnotation(Dict.class).dicText();
+                            String table = field.getAnnotation(Dict.class).dictTable();
+                            String key = String.valueOf(item.get(field.getName()));
+
+                            //翻译字典值对应的txt
+                            String textValue = translateDictValue(code, text, table, key);
+
+                            log.debug(" 字典Val : "+ textValue);
+                            log.debug(" __翻译字典字段__ "+field.getName() + CommonConstant.DICT_TEXT_SUFFIX+": "+ textValue);
+                            item.put(field.getName() + CommonConstant.DICT_TEXT_SUFFIX, textValue);
+                        }
+                        //date类型默认转换string格式化日期
+                        if (field.getType().getName().equals("java.util.Date")&&field.getAnnotation(JsonFormat.class)==null&&item.get(field.getName())!=null){
+                            SimpleDateFormat aDate=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+                            item.put(field.getName(), aDate.format(new Date((Long) item.get(field.getName()))));
+                        }
+                    }
+                    items.add(item);
+                }
+                ((IPage) ((Result) result).getResult()).setRecords(items);
+            }
+
+        }
+    }
+
+    /**
+     *  翻译字典文本
+     * @param code
+     * @param text
+     * @param table
+     * @param key
+     * @return
+     */
+    private String translateDictValue(String code, String text, String table, String key) {
+    	if(oConvertUtils.isEmpty(key)) {
+    		return null;
+    	}
+        StringBuffer textValue=new StringBuffer();
+        String[] keys = key.split(",");
+        for (String k : keys) {
+            String tmpValue = null;
+            log.debug(" 字典 key : "+ k);
+            if (k.trim().length() == 0) {
+                continue; //跳过循环
+            }
+            //update-begin--Author:scott -- Date:20210531 ----for: !56 优化微服务应用下存在表字段需要字典翻译时加载缓慢问题-----
+            if (!StringUtils.isEmpty(table)){
+                log.info("--DictAspect------dicTable="+ table+" ,dicText= "+text+" ,dicCode="+code);
+                String keyString = String.format("sys:cache:dictTable::SimpleKey [%s,%s,%s,%s]",table,text,code,k.trim());
+                if (redisTemplate.hasKey(keyString)){
+                    try {
+                        tmpValue = oConvertUtils.getString(redisTemplate.opsForValue().get(keyString));
+                    } catch (Exception e) {
+                        log.warn(e.getMessage());
+                    }
+                }else {
+                    tmpValue= commonAPI.translateDictFromTable(table,text,code,k.trim());
+                }
+            }else {
+                String keyString = String.format("sys:cache:dict::%s:%s",code,k.trim());
+                if (redisTemplate.hasKey(keyString)){
+                    try {
+                        tmpValue = oConvertUtils.getString(redisTemplate.opsForValue().get(keyString));
+                    } catch (Exception e) {
+                       log.warn(e.getMessage());
+                    }
+                }else {
+                    tmpValue = commonAPI.translateDict(code, k.trim());
+                }
+            }
+            //update-end--Author:scott -- Date:20210531 ----for: !56 优化微服务应用下存在表字段需要字典翻译时加载缓慢问题-----
+
+            if (tmpValue != null) {
+                if (!"".equals(textValue.toString())) {
+                    textValue.append(",");
+                }
+                textValue.append(tmpValue);
+            }
+
+        }
+        return textValue.toString();
+    }
+
+}

+ 119 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/aspect/PermissionDataAspect.java

@@ -0,0 +1,119 @@
+package org.jeecg.common.aspect;
+
+import lombok.extern.slf4j.Slf4j;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.aspectj.lang.reflect.MethodSignature;
+import org.jeecg.common.api.CommonAPI;
+import org.jeecg.common.aspect.annotation.PermissionData;
+import org.jeecg.common.system.util.JeecgDataAutorUtils;
+import org.jeecg.common.system.util.JwtUtil;
+import org.jeecg.common.system.vo.SysPermissionDataRuleModel;
+import org.jeecg.common.system.vo.SysUserCacheInfo;
+import org.jeecg.common.util.SpringContextUtils;
+import org.jeecg.common.util.oConvertUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.http.HttpServletRequest;
+import java.lang.reflect.Method;
+import java.util.List;
+
+/**
+ * 数据权限切面处理类
+ *  当被请求的方法有注解PermissionData时,会在往当前request中写入数据权限信息
+ * @Date 2019年4月10日
+ * @Version: 1.0
+ */
+@Aspect
+@Component
+@Slf4j
+public class PermissionDataAspect {
+
+    @Autowired
+    private CommonAPI commonAPI;
+
+    @Pointcut("@annotation(org.jeecg.common.aspect.annotation.PermissionData)")
+    public void pointCut() {
+
+    }
+
+    @Around("pointCut()")
+    public Object arround(ProceedingJoinPoint point) throws  Throwable{
+        HttpServletRequest request = SpringContextUtils.getHttpServletRequest();
+        MethodSignature signature = (MethodSignature) point.getSignature();
+        Method method = signature.getMethod();
+        PermissionData pd = method.getAnnotation(PermissionData.class);
+        String component = pd.pageComponent();
+
+        String requestMethod = request.getMethod();
+        String requestPath = request.getRequestURI().substring(request.getContextPath().length());
+        requestPath = filterUrl(requestPath);
+        log.debug("拦截请求 >> "+requestPath+";请求类型 >> "+requestMethod);
+        String username = JwtUtil.getUserNameByToken(request);
+        //查询数据权限信息
+        //TODO 微服务情况下也得支持缓存机制
+        List<SysPermissionDataRuleModel> dataRules = commonAPI.queryPermissionDataRule(component, requestPath, username);
+        if(dataRules!=null && dataRules.size()>0) {
+            //临时存储
+            JeecgDataAutorUtils.installDataSearchConditon(request, dataRules);
+            //TODO 微服务情况下也得支持缓存机制
+            SysUserCacheInfo userinfo = commonAPI.getCacheUser(username);
+            JeecgDataAutorUtils.installUserInfo(request, userinfo);
+        }
+        return  point.proceed();
+    }
+
+    private String filterUrl(String requestPath){
+        String url = "";
+        if(oConvertUtils.isNotEmpty(requestPath)){
+            url = requestPath.replace("\\", "/");
+            url = url.replace("//", "/");
+            if(url.indexOf("//")>=0){
+                url = filterUrl(url);
+            }
+			/*if(url.startsWith("/")){
+				url=url.substring(1);
+			}*/
+        }
+        return url;
+    }
+
+    /**
+     * 获取请求地址
+     * @param request
+     * @return
+     */
+    private String getJgAuthRequsetPath(HttpServletRequest request) {
+        String queryString = request.getQueryString();
+        String requestPath = request.getRequestURI();
+        if(oConvertUtils.isNotEmpty(queryString)){
+            requestPath += "?" + queryString;
+        }
+        if (requestPath.indexOf("&") > -1) {// 去掉其他参数(保留一个参数) 例如:loginController.do?login
+            requestPath = requestPath.substring(0, requestPath.indexOf("&"));
+        }
+        if(requestPath.indexOf("=")!=-1){
+            if(requestPath.indexOf(".do")!=-1){
+                requestPath = requestPath.substring(0,requestPath.indexOf(".do")+3);
+            }else{
+                requestPath = requestPath.substring(0,requestPath.indexOf("?"));
+            }
+        }
+        requestPath = requestPath.substring(request.getContextPath().length() + 1);// 去掉项目路径
+        return filterUrl(requestPath);
+    }
+
+    private boolean moHuContain(List<String> list,String key){
+        for(String str : list){
+            if(key.contains(str)){
+                return true;
+            }
+        }
+        return false;
+    }
+
+
+}

+ 58 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/aspect/UrlMatchEnum.java

@@ -0,0 +1,58 @@
+package org.jeecg.common.aspect;
+
+/**
+ * @Author scott
+ * @Date 2020/1/14 13:36
+ * @Description: 请求URL与菜单路由URL转换规则(方便于采用菜单路由URL来配置数据权限规则)
+ */
+public enum UrlMatchEnum {
+    CGFORM_DATA("/online/cgform/api/getData/", "/online/cgformList/"),
+    CGFORM_EXCEL_DATA("/online/cgform/api/exportXls/", "/online/cgformList/"),
+    CGFORM_TREE_DATA("/online/cgform/api/getTreeData/", "/online/cgformList/"),
+    CGREPORT_DATA("/online/cgreport/api/getColumnsAndData/", "/online/cgreport/"),
+    CGREPORT_EXCEL_DATA("/online/cgreport/api/exportXls/", "/online/cgreport/");
+
+
+    UrlMatchEnum(String url, String match_url) {
+        this.url = url;
+        this.match_url = match_url;
+    }
+
+    /**
+     * Request 请求 URL前缀
+     */
+    private String url;
+    /**
+     * 菜单路由 URL前缀 (对应菜单路径)
+     */
+    private String match_url;
+
+    /**
+     * 根据req url 获取到菜单配置路径(前端页面路由URL)
+     *
+     * @param url
+     * @return
+     */
+    public static String getMatchResultByUrl(String url) {
+        //获取到枚举
+        UrlMatchEnum[] values = UrlMatchEnum.values();
+        //加强for循环进行遍历操作
+        for (UrlMatchEnum lr : values) {
+            //如果遍历获取的type和参数type一致
+            if (url.indexOf(lr.url) != -1) {
+                //返回type对象的desc
+                return url.replace(lr.url, lr.match_url);
+            }
+        }
+        return null;
+    }
+
+
+//    public static void main(String[] args) {
+//        /**
+//         * 比如request真实请求URL: /online/cgform/api/getData/81fcf7d8922d45069b0d5ba983612d3a
+//         * 转换匹配路由URL后(对应配置的菜单路径):/online/cgformList/81fcf7d8922d45069b0d5ba983612d3a
+//         */
+//        System.out.println(UrlMatchEnum.getMatchResultByUrl("/online/cgform/api/getData/81fcf7d8922d45069b0d5ba983612d3a"));
+//    }
+}

+ 46 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/aspect/annotation/AutoLog.java

@@ -0,0 +1,46 @@
+package org.jeecg.common.aspect.annotation;
+
+import org.jeecg.common.constant.CommonConstant;
+import org.jeecg.common.constant.enums.ModuleType;
+
+import java.lang.annotation.*;
+
+/**
+ * 系统日志注解
+ * 
+ * @Author scott
+ * @email jeecgos@163.com
+ * @Date 2019年1月14日
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface AutoLog {
+
+	/**
+	 * 日志内容
+	 * 
+	 * @return
+	 */
+	String value() default "";
+
+	/**
+	 * 日志类型
+	 * 
+	 * @return 0:操作日志;1:登录日志;2:定时任务;
+	 */
+	int logType() default CommonConstant.LOG_TYPE_2;
+	
+	/**
+	 * 操作日志类型
+	 * 
+	 * @return (1查询,2添加,3修改,4删除)
+	 */
+	int operateType() default 0;
+
+	/**
+	 * 模块类型 默认为common
+	 * @return
+	 */
+	ModuleType module() default ModuleType.COMMON;
+}

+ 42 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/aspect/annotation/Dict.java

@@ -0,0 +1,42 @@
+package org.jeecg.common.aspect.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ *  类描述:  字典注解
+ * 作    者: dangzhenghui
+ * 日    期: 2019年03月17日-下午9:37:16
+ */
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Dict {
+    /**
+     * 方法描述:  数据code
+     * 作    者: dangzhenghui
+     * 日    期: 2019年03月17日-下午9:37:16
+     *
+     * @return 返回类型: String
+     */
+    String dicCode();
+
+    /**
+     * 方法描述:  数据Text
+     * 作    者: dangzhenghui
+     * 日    期: 2019年03月17日-下午9:37:16
+     *
+     * @return 返回类型: String
+     */
+    String dicText() default "";
+
+    /**
+     * 方法描述: 数据字典表
+     * 作    者: dangzhenghui
+     * 日    期: 2019年03月17日-下午9:37:16
+     *
+     * @return 返回类型: String
+     */
+    String dictTable() default "";
+}

+ 18 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/aspect/annotation/OnlineAuth.java

@@ -0,0 +1,18 @@
+package org.jeecg.common.aspect.annotation;
+
+import java.lang.annotation.*;
+
+/**
+ * online请求拦截专用注解
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE,ElementType.METHOD})
+@Documented
+public @interface OnlineAuth {
+
+    /**
+     * 请求关键字,在xxx/code之前的字符串
+     * @return
+     */
+    String value();
+}

+ 29 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/aspect/annotation/PermissionData.java

@@ -0,0 +1,29 @@
+package org.jeecg.common.aspect.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+  *  数据权限注解
+ * @Author taoyan
+ * @Date 2019年4月11日
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE,ElementType.METHOD})
+@Documented
+public @interface PermissionData {
+	/**
+	 * 暂时没用
+	 * @return
+	 */
+	String value() default "";
+	
+	
+	/**
+	 * 配置菜单的组件路径,用于数据权限
+	 */
+	String pageComponent() default "";
+}

+ 330 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/constant/CommonConstant.java

@@ -0,0 +1,330 @@
+package org.jeecg.common.constant;
+
+public interface CommonConstant {
+
+	/**
+	 * 正常状态
+	 */
+	public static final Integer STATUS_NORMAL = 0;
+
+	/**
+	 * 禁用状态
+	 */
+	public static final Integer STATUS_DISABLE = -1;
+
+	/**
+	 * 删除标志
+	 */
+	public static final Integer DEL_FLAG_1 = 1;
+
+	/**
+	 * 未删除
+	 */
+	public static final Integer DEL_FLAG_0 = 0;
+
+	/**
+	 * 系统日志类型: 登录
+	 */
+	public static final int LOG_TYPE_1 = 1;
+	
+	/**
+	 * 系统日志类型: 操作
+	 */
+	public static final int LOG_TYPE_2 = 2;
+
+	/**
+	 * 操作日志类型: 查询
+	 */
+	public static final int OPERATE_TYPE_1 = 1;
+	
+	/**
+	 * 操作日志类型: 添加
+	 */
+	public static final int OPERATE_TYPE_2 = 2;
+	
+	/**
+	 * 操作日志类型: 更新
+	 */
+	public static final int OPERATE_TYPE_3 = 3;
+	
+	/**
+	 * 操作日志类型: 删除
+	 */
+	public static final int OPERATE_TYPE_4 = 4;
+	
+	/**
+	 * 操作日志类型: 倒入
+	 */
+	public static final int OPERATE_TYPE_5 = 5;
+	
+	/**
+	 * 操作日志类型: 导出
+	 */
+	public static final int OPERATE_TYPE_6 = 6;
+	
+	
+	/** {@code 500 Server Error} (HTTP/1.0 - RFC 1945) */
+    public static final Integer SC_INTERNAL_SERVER_ERROR_500 = 500;
+    /** {@code 200 OK} (HTTP/1.0 - RFC 1945) */
+    public static final Integer SC_OK_200 = 200;
+    
+    /**访问权限认证未通过 510*/
+    public static final Integer SC_JEECG_NO_AUTHZ=510;
+
+    /** 登录用户Shiro权限缓存KEY前缀 */
+    public static String PREFIX_USER_SHIRO_CACHE  = "shiro:cache:org.jeecg.config.shiro.ShiroRealm.authorizationCache:";
+    /** 登录用户Token令牌缓存KEY前缀 */
+    public static final String PREFIX_USER_TOKEN  = "prefix_user_token_";
+    /** Token缓存时间:3600秒即一小时 */
+    public static final int  TOKEN_EXPIRE_TIME  = 3600;
+    
+
+    /**
+     *  0:一级菜单
+     */
+    public static final Integer MENU_TYPE_0  = 0;
+   /**
+    *  1:子菜单 
+    */
+    public static final Integer MENU_TYPE_1  = 1;
+    /**
+     *  2:按钮权限
+     */
+    public static final Integer MENU_TYPE_2  = 2;
+    
+    /**通告对象类型(USER:指定用户,ALL:全体用户)*/
+    public static final String MSG_TYPE_UESR  = "USER";
+    public static final String MSG_TYPE_ALL  = "ALL";
+    
+    /**发布状态(0未发布,1已发布,2已撤销)*/
+    public static final String NO_SEND  = "0";
+    public static final String HAS_SEND  = "1";
+    public static final String HAS_CANCLE  = "2";
+    
+    /**阅读状态(0未读,1已读)*/
+    public static final String HAS_READ_FLAG  = "1";
+    public static final String NO_READ_FLAG  = "0";
+    
+    /**优先级(L低,M中,H高)*/
+    public static final String PRIORITY_L  = "L";
+    public static final String PRIORITY_M  = "M";
+    public static final String PRIORITY_H  = "H";
+    
+    /**
+     * 短信模板方式  0 .登录模板、1.注册模板、2.忘记密码模板
+     */
+    public static final String SMS_TPL_TYPE_0  = "0";
+    public static final String SMS_TPL_TYPE_1  = "1";
+    public static final String SMS_TPL_TYPE_2  = "2";
+    
+    /**
+     * 状态(0无效1有效)
+     */
+    public static final String STATUS_0 = "0";
+    public static final String STATUS_1 = "1";
+    
+    /**
+     * 同步工作流引擎1同步0不同步
+     */
+    public static final Integer ACT_SYNC_1 = 1;
+    public static final Integer ACT_SYNC_0 = 0;
+
+    /**
+     * 消息类型1:通知公告2:系统消息
+     */
+    public static final String MSG_CATEGORY_1 = "1";
+    public static final String MSG_CATEGORY_2 = "2";
+    
+    /**
+     * 是否配置菜单的数据权限 1是0否
+     */
+    public static final Integer RULE_FLAG_0 = 0;
+    public static final Integer RULE_FLAG_1 = 1;
+
+    /**
+     * 是否用户已被冻结 1正常(解冻) 2冻结
+     */
+    public static final Integer USER_UNFREEZE = 1;
+    public static final Integer USER_FREEZE = 2;
+    
+    /**字典翻译文本后缀*/
+    public static final String DICT_TEXT_SUFFIX = "_dictText";
+
+    /**
+     * 表单设计器主表类型
+     */
+    public static final Integer DESIGN_FORM_TYPE_MAIN = 1;
+
+    /**
+     * 表单设计器子表表类型
+     */
+    public static final Integer DESIGN_FORM_TYPE_SUB = 2;
+
+    /**
+     * 表单设计器URL授权通过
+     */
+    public static final Integer DESIGN_FORM_URL_STATUS_PASSED = 1;
+
+    /**
+     * 表单设计器URL授权未通过
+     */
+    public static final Integer DESIGN_FORM_URL_STATUS_NOT_PASSED = 2;
+
+    /**
+     * 表单设计器新增 Flag
+     */
+    public static final String DESIGN_FORM_URL_TYPE_ADD = "add";
+    /**
+     * 表单设计器修改 Flag
+     */
+    public static final String DESIGN_FORM_URL_TYPE_EDIT = "edit";
+    /**
+     * 表单设计器详情 Flag
+     */
+    public static final String DESIGN_FORM_URL_TYPE_DETAIL = "detail";
+    /**
+     * 表单设计器复用数据 Flag
+     */
+    public static final String DESIGN_FORM_URL_TYPE_REUSE = "reuse";
+    /**
+     * 表单设计器编辑 Flag (已弃用)
+     */
+    public static final String DESIGN_FORM_URL_TYPE_VIEW = "view";
+
+    /**
+     * online参数值设置(是:Y, 否:N)
+     */
+    public static final String ONLINE_PARAM_VAL_IS_TURE = "Y";
+    public static final String ONLINE_PARAM_VAL_IS_FALSE = "N";
+
+    /**
+     * 文件上传类型(本地:local,Minio:minio,阿里云:alioss)
+     */
+    public static final String UPLOAD_TYPE_LOCAL = "local";
+    public static final String UPLOAD_TYPE_MINIO = "minio";
+    public static final String UPLOAD_TYPE_OSS = "alioss";
+
+    /**
+     * 文档上传自定义桶名称
+     */
+    public static final String UPLOAD_CUSTOM_BUCKET = "eoafile";
+    /**
+     * 文档上传自定义路径
+     */
+    public static final String UPLOAD_CUSTOM_PATH = "eoafile";
+    /**
+     * 文件外链接有效天数
+     */
+    public static final Integer UPLOAD_EFFECTIVE_DAYS = 1;
+
+    /**
+     * 员工身份 (1:普通员工  2:上级)
+     */
+    public static final Integer USER_IDENTITY_1 = 1;
+    public static final Integer USER_IDENTITY_2 = 2;
+
+    /** sys_user 表 username 唯一键索引 */
+    public static final String SQL_INDEX_UNIQ_SYS_USER_USERNAME = "uniq_sys_user_username";
+    /** sys_user 表 work_no 唯一键索引 */
+    public static final String SQL_INDEX_UNIQ_SYS_USER_WORK_NO = "uniq_sys_user_work_no";
+    /** sys_user 表 phone 唯一键索引 */
+    public static final String SQL_INDEX_UNIQ_SYS_USER_PHONE = "uniq_sys_user_phone";
+    /** sys_user 表 email 唯一键索引 */
+    public static final String SQL_INDEX_UNIQ_SYS_USER_EMAIL = "uniq_sys_user_email";
+    /** sys_quartz_job 表 job_class_name 唯一键索引 */
+    public static final String SQL_INDEX_UNIQ_JOB_CLASS_NAME = "uniq_job_class_name";
+    /** sys_position 表 code 唯一键索引 */
+    public static final String SQL_INDEX_UNIQ_CODE = "uniq_code";
+    /** sys_role 表 code 唯一键索引 */
+    public static final String SQL_INDEX_UNIQ_SYS_ROLE_CODE = "uniq_sys_role_role_code";
+    /** sys_depart 表 code 唯一键索引 */
+    public static final String SQL_INDEX_UNIQ_DEPART_ORG_CODE = "uniq_depart_org_code";
+    /**
+     * 在线聊天 是否为默认分组
+     */
+    public static final String IM_DEFAULT_GROUP = "1";
+    /**
+     * 在线聊天 图片文件保存路径
+     */
+    public static final String IM_UPLOAD_CUSTOM_PATH = "imfile";
+    /**
+     * 在线聊天 用户状态
+     */
+    public static final String IM_STATUS_ONLINE = "online";
+
+    /**
+     * 在线聊天 SOCKET消息类型
+     */
+    public static final String IM_SOCKET_TYPE = "chatMessage";
+
+    /**
+     * 在线聊天 是否开启默认添加好友 1是 0否
+     */
+    public static final String IM_DEFAULT_ADD_FRIEND = "1";
+
+    /**
+     * 在线聊天 用户好友缓存前缀
+     */
+    public static final String IM_PREFIX_USER_FRIEND_CACHE = "sys:cache:im:im_prefix_user_friend_";
+
+    /**
+     * 考勤补卡业务状态 (1:同意  2:不同意)
+     */
+    public static final String SIGN_PATCH_BIZ_STATUS_1 = "1";
+    public static final String SIGN_PATCH_BIZ_STATUS_2 = "2";
+
+    /**
+     * 公文文档上传自定义路径
+     */
+    public static final String UPLOAD_CUSTOM_PATH_OFFICIAL = "officialdoc";
+     /**
+     * 公文文档下载自定义路径
+     */
+    public static final String DOWNLOAD_CUSTOM_PATH_OFFICIAL = "officaldown";
+
+    /**
+     * WPS存储值类别(1 code文号 2 text(WPS模板还是公文发文模板))
+     */
+    public static final String WPS_TYPE_1="1";
+    public static final String WPS_TYPE_2="2";
+
+
+    public final static String X_ACCESS_TOKEN = "X-Access-Token";
+    public final static String X_SIGN = "X-Sign";
+    public final static String X_TIMESTAMP = "X-TIMESTAMP";
+
+    /**
+     * 多租户 请求头
+     */
+    public final static String TENANT_ID = "tenant-id";
+
+    public final static String CAS_USER_SESSION_KEY = "_const_cas_assertion_";
+
+    /**
+     * 微服务读取配置文件属性 服务地址
+     */
+    public final static String CLOUD_SERVER_KEY = "spring.cloud.nacos.discovery.server-addr";
+
+    /**
+     * 第三方登录 验证密码/创建用户 都需要设置一个操作码 防止被恶意调用
+     */
+    public final static String THIRD_LOGIN_CODE = "third_login_code";
+
+
+    /**
+     * 第三方APP同步方向:本地 --> 第三方APP
+     */
+    String THIRD_SYNC_TO_APP = "SYNC_TO_APP";
+    /**
+     * 第三方APP同步方向:第三方APP --> 本地
+     */
+    String THIRD_SYNC_TO_LOCAL = "SYNC_TO_LOCAL";
+
+    /** 系统通告消息状态:0=未发布 */
+    String ANNOUNCEMENT_SEND_STATUS_0 = "0";
+    /** 系统通告消息状态:1=已发布 */
+    String ANNOUNCEMENT_SEND_STATUS_1 = "1";
+    /** 系统通告消息状态:2=已撤销 */
+    String ANNOUNCEMENT_SEND_STATUS_2 = "2";
+
+}

+ 26 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/constant/CommonSendStatus.java

@@ -0,0 +1,26 @@
+package org.jeecg.common.constant;
+
+/**
+ * 	系统通告 - 发布状态
+ * @Author LeeShaoQing
+ *
+ */
+public interface CommonSendStatus {
+	
+	public static final String UNPUBLISHED_STATUS_0 = "0";	//未发布
+	
+	public static final String PUBLISHED_STATUS_1 = "1";		//已发布
+	
+	public static final String REVOKE_STATUS_2 = "2";			//撤销
+	//app端推送会话标识后缀
+	public static final String  APP_SESSION_SUFFIX = "_app";	//app端推送会话标识后缀
+
+
+
+	/**流程催办——系统通知消息模板*/
+	public static final String TZMB_BPM_CUIBAN = "bpm_cuiban";
+	/**标准模板—系统消息通知*/
+	public static final String TZMB_SYS_TS_NOTE = "sys_ts_note";
+	/**流程超时提醒——系统通知消息模板*/
+	public static final String TZMB_BPM_CHAOSHI_TIP = "bpm_chaoshi_tip";
+}

+ 130 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/constant/DataBaseConstant.java

@@ -0,0 +1,130 @@
+package org.jeecg.common.constant;
+/**
+ * 数据库上下文常量
+ */
+public interface DataBaseConstant {
+	//*********数据库类型****************************************
+	public static final String DB_TYPE_MYSQL = "MYSQL";
+	public static final String DB_TYPE_ORACLE = "ORACLE";
+	public static final String DB_TYPE_DM = "DM";//达梦数据库
+	public static final String DB_TYPE_POSTGRESQL = "POSTGRESQL";
+	public static final String DB_TYPE_SQLSERVER = "SQLSERVER";
+	public static final String DB_TYPE_MARIADB = "MARIADB";
+
+	// 数据库类型,对应 database_type 字典
+	public static final String DB_TYPE_MYSQL_NUM = "1";
+	public static final String DB_TYPE_ORACLE_NUM = "2";
+	public static final String DB_TYPE_SQLSERVER_NUM = "3";
+	public static final String DB_TYPE_POSTGRESQL_NUM = "4";
+	public static final String DB_TYPE_MARIADB_NUM = "5";
+	//*********系统上下文变量****************************************
+	/**
+	 * 数据-所属机构编码
+	 */
+	public static final String SYS_ORG_CODE = "sysOrgCode";
+	/**
+	 * 数据-所属机构编码
+	 */
+	public static final String SYS_ORG_CODE_TABLE = "sys_org_code";
+	/**
+	 * 数据-所属机构编码
+	 */
+	public static final String SYS_MULTI_ORG_CODE = "sysMultiOrgCode";
+	/**
+	 * 数据-所属机构编码
+	 */
+	public static final String SYS_MULTI_ORG_CODE_TABLE = "sys_multi_org_code";
+	/**
+	 * 数据-系统用户编码(对应登录用户账号)
+	 */
+	public static final String SYS_USER_CODE = "sysUserCode";
+	/**
+	 * 数据-系统用户编码(对应登录用户账号)
+	 */
+	public static final String SYS_USER_CODE_TABLE = "sys_user_code";
+	
+	/**
+	 * 登录用户真实姓名
+	 */
+	public static final String SYS_USER_NAME = "sysUserName";
+	/**
+	 * 登录用户真实姓名
+	 */
+	public static final String SYS_USER_NAME_TABLE = "sys_user_name";
+	/**
+	 * 系统日期"yyyy-MM-dd"
+	 */
+	public static final String SYS_DATE = "sysDate";
+	/**
+	 * 系统日期"yyyy-MM-dd"
+	 */
+	public static final String SYS_DATE_TABLE = "sys_date";
+	/**
+	 * 系统时间"yyyy-MM-dd HH:mm"
+	 */
+	public static final String SYS_TIME = "sysTime";
+	/**
+	 * 系统时间"yyyy-MM-dd HH:mm"
+	 */
+	public static final String SYS_TIME_TABLE = "sys_time";
+	/**
+	 * 数据-所属机构编码
+	 */
+	public static final String SYS_BASE_PATH = "sys_base_path";
+	//*********系统上下文变量****************************************
+	
+	
+	//*********系统建表标准字段****************************************
+	/**
+	 * 创建者登录名称
+	 */
+	public static final String CREATE_BY_TABLE = "create_by";
+	/**
+	 * 创建者登录名称
+	 */
+	public static final String CREATE_BY = "createBy";
+	/**
+	 * 创建日期时间
+	 */
+	public static final String CREATE_TIME_TABLE = "create_time";
+	/**
+	 * 创建日期时间
+	 */
+	public static final String CREATE_TIME = "createTime";
+	/**
+	 * 更新用户登录名称
+	 */
+	public static final String UPDATE_BY_TABLE = "update_by";
+	/**
+	 * 更新用户登录名称
+	 */
+	public static final String UPDATE_BY = "updateBy";
+	/**
+	 * 更新日期时间
+	 */
+	public static final String UPDATE_TIME = "updateTime";
+	/**
+	 * 更新日期时间
+	 */
+	public static final String UPDATE_TIME_TABLE = "update_time";
+	
+	/**
+	 * 业务流程状态
+	 */
+	public static final String BPM_STATUS = "bpmStatus";
+	/**
+	 * 业务流程状态
+	 */
+	public static final String BPM_STATUS_TABLE = "bpm_status";
+	//*********系统建表标准字段****************************************
+
+
+	/**
+	 * 租户ID 实体字段名
+	 */
+	String TENANT_ID = "tenantId";
+	/**
+	 * 租户ID 数据库字段名
+	 */
+	String TENANT_ID_TABLE = "tenant_id";
+}

+ 25 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/constant/FillRuleConstant.java

@@ -0,0 +1,25 @@
+package org.jeecg.common.constant;
+
+/**
+ * 规则值生成 编码常量类
+ * @author: taoyan
+ * @date: 2020年04月02日
+ */
+public class FillRuleConstant {
+
+    /**
+     * 公文发文编码
+     */
+    public static final String DOC_SEND = "doc_send_code";
+
+    /**
+     * 部门编码
+     */
+    public static final String DEPART = "org_num_role";
+
+    /**
+     * 分类字典编码
+     */
+    public static final String CATEGORY = "category_code_rule";
+
+}

+ 131 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/constant/ProvinceCityArea.java

@@ -0,0 +1,131 @@
+package org.jeecg.common.constant;
+
+import com.alibaba.fastjson.JSONObject;
+import org.jeecg.common.util.oConvertUtils;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.core.io.Resource;
+import org.springframework.stereotype.Component;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Scanner;
+import java.util.Set;
+import java.util.List;
+
+@Component("pca")
+public class ProvinceCityArea {
+    List<Area> areaList;
+
+    public String getText(String code){
+        this.initAreaList();
+        if(this.areaList!=null || this.areaList.size()>0){
+            List<String> ls = new ArrayList<String>();
+            getAreaByCode(code,ls);
+            return String.join("/",ls);
+        }
+        return "";
+    }
+
+    public String getCode(String text){
+        this.initAreaList();
+        if(areaList!=null || areaList.size()>0){
+            for(int i=areaList.size()-1;i>=0;i--){
+                if(text.indexOf(areaList.get(i).getText())>=0){
+                    return areaList.get(i).getId();
+                }
+            }
+        }
+        return null;
+    }
+
+    public void getAreaByCode(String code,List<String> ls){
+        for(Area area: areaList){
+            if(area.getId().equals(code)){
+                String pid = area.getPid();
+                ls.add(0,area.getText());
+                getAreaByCode(pid,ls);
+            }
+        }
+    }
+
+    private void initAreaList(){
+        //System.out.println("=====================");
+        if(this.areaList==null || this.areaList.size()==0){
+            this.areaList = new ArrayList<Area>();
+            try {
+                String jsonData = oConvertUtils.readStatic("classpath:static/pca.json");
+                JSONObject baseJson = JSONObject.parseObject(jsonData);
+                //第一层 省
+                JSONObject provinceJson = baseJson.getJSONObject("86");
+                for(String provinceKey: provinceJson.keySet()){
+                    //System.out.println("===="+provinceKey);
+                    Area province = new Area(provinceKey,provinceJson.getString(provinceKey),"86");
+                    this.areaList.add(province);
+                    //第二层 市
+                    JSONObject cityJson = baseJson.getJSONObject(provinceKey);
+                    for(String cityKey:cityJson.keySet()){
+                        //System.out.println("-----"+cityKey);
+                        Area city = new Area(cityKey,cityJson.getString(cityKey),provinceKey);
+                        this.areaList.add(city);
+                        //第三层 区
+                        JSONObject areaJson =  baseJson.getJSONObject(cityKey);
+                        if(areaJson!=null){
+                            for(String areaKey:areaJson.keySet()){
+                                //System.out.println("········"+areaKey);
+                                Area area = new Area(areaKey,areaJson.getString(areaKey),cityKey);
+                                this.areaList.add(area);
+                            }
+                        }
+                    }
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+
+    }
+
+
+    private String jsonRead(File file){
+        Scanner scanner = null;
+        StringBuilder buffer = new StringBuilder();
+        try {
+            scanner = new Scanner(file, "utf-8");
+            while (scanner.hasNextLine()) {
+                buffer.append(scanner.nextLine());
+            }
+        } catch (Exception e) {
+
+        } finally {
+            if (scanner != null) {
+                scanner.close();
+            }
+        }
+        return buffer.toString();
+    }
+
+    class Area{
+        String id;
+        String text;
+        String pid;
+
+        public Area(String id,String text,String pid){
+            this.id = id;
+            this.text = text;
+            this.pid = pid;
+        }
+
+        public String getId() {
+            return id;
+        }
+
+        public String getText() {
+            return text;
+        }
+
+        public String getPid() {
+            return pid;
+        }
+    }
+}

+ 38 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/constant/ServiceNameConstants.java

@@ -0,0 +1,38 @@
+/*
+ *
+ *  *  Copyright (c) 2019-2020, 冷冷 (wangiegie@gmail.com).
+ *  *  <p>
+ *  *  Licensed under the GNU Lesser General Public License 3.0 (the "License");
+ *  *  you may not use this file except in compliance with the License.
+ *  *  You may obtain a copy of the License at
+ *  *  <p>
+ *  * https://www.gnu.org/licenses/lgpl.html
+ *  *  <p>
+ *  * Unless required by applicable law or agreed to in writing, software
+ *  * distributed under the License is distributed on an "AS IS" BASIS,
+ *  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  * See the License for the specific language governing permissions and
+ *  * limitations under the License.
+ *
+ */
+
+package org.jeecg.common.constant;
+
+/**
+ * @author scott
+ * @date 2019年05月18日
+ * 服务名称
+ */
+public interface ServiceNameConstants {
+
+	/**
+	 * 系统管理 admin
+	 */
+	String SYSTEM_SERVICE = "jeecg-system";
+
+	/**
+	 * gateway通过header传递根路径 basePath
+	 */
+	String X_GATEWAY_BASE_PATH = "X_GATEWAY_BASE_PATH";
+
+}

+ 30 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/constant/VXESocketConst.java

@@ -0,0 +1,30 @@
+package org.jeecg.common.constant;
+
+/**
+ * VXESocket 常量
+ */
+public class VXESocketConst {
+
+    /**
+     * 消息类型
+     */
+    public static final String TYPE = "type";
+    /**
+     * 消息数据
+     */
+    public static final String DATA = "data";
+
+    /**
+     * 消息类型:心跳检测
+     */
+    public static final String TYPE_HB = "heart_beat";
+    /**
+     * 消息类型:通用数据传递
+     */
+    public static final String TYPE_CSD = "common_send_date";
+    /**
+     * 消息类型:更新vxe table数据
+     */
+    public static final String TYPE_UVT = "update_vxe_table";
+
+}

+ 61 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/constant/WebsocketConst.java

@@ -0,0 +1,61 @@
+package org.jeecg.common.constant;
+
+/**
+ * @Description: Websocket常量类
+ * @author: taoyan
+ * @date: 2020年03月23日
+ */
+public class WebsocketConst {
+
+
+    /**
+     * 消息json key:cmd
+     */
+    public static final String MSG_CMD = "cmd";
+
+    /**
+     * 消息json key:msgId
+     */
+    public static final String MSG_ID = "msgId";
+
+    /**
+     * 消息json key:msgTxt
+     */
+    public static final String MSG_TXT = "msgTxt";
+
+    /**
+     * 消息json key:userId
+     */
+    public static final String MSG_USER_ID = "userId";
+
+    /**
+     * 消息类型 heartcheck
+     */
+    public static final String CMD_CHECK = "heartcheck";
+
+    /**
+     * 消息类型 user 用户消息
+     */
+    public static final String CMD_USER = "user";
+
+    /**
+     * 消息类型 topic 系统通知
+     */
+    public static final String CMD_TOPIC = "topic";
+
+    /**
+     * 消息类型 email
+     */
+    public static final String CMD_EMAIL = "email";
+
+    /**
+     * 消息类型 meetingsign 会议签到
+     */
+    public static final String CMD_SIGN = "sign";
+
+    /**
+     * 消息类型 新闻发布/取消
+     */
+    public static final String NEWS_PUBLISH = "publish";
+
+}

+ 150 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/constant/enums/CgformEnum.java

@@ -0,0 +1,150 @@
+package org.jeecg.common.constant.enums;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * online表单枚举 代码生成器用到
+ */
+public enum CgformEnum {
+
+    /**
+     * 单表
+     */
+    ONE(1, "one", "/jeecg/code-template-online", "default.one", "经典风格"),
+    /**
+     * 多表
+     */
+    MANY(2, "many", "/jeecg/code-template-online", "default.onetomany", "经典风格"),
+    /**
+     * 多表
+     */
+    ERP(2, "erp", "/jeecg/code-template-online", "erp.onetomany", "ERP风格"),
+    /**
+     * 多表(jvxe风格)
+     *  */
+    JVXE_TABLE(2, "jvxe", "/jeecg/code-template-online", "jvxe.onetomany", "JVXE风格"),
+    /**
+     * 多表(内嵌子表风格)
+     */
+    INNER_TABLE(2, "innerTable", "/jeecg/code-template-online", "inner-table.onetomany", "内嵌子表风格"),
+    /**
+     * 多表(tab风格)
+     *  */
+    TAB(2, "tab", "/jeecg/code-template-online", "tab.onetomany", "Tab风格"),
+    /**
+     * 树形列表
+     */
+    TREE(3, "tree", "/jeecg/code-template-online", "default.tree", "树形列表");
+
+    /**
+     * 类型 1/单表 2/一对多 3/树
+     */
+    int type;
+    /**
+     * 编码标识
+     */
+    String code;
+    /**
+     * 代码生成器模板路径
+     */
+    String templatePath;
+    /**
+     * 代码生成器模板路径
+     */
+    String stylePath;
+    /**
+     * 模板风格名称
+     */
+    String note;
+
+    /**
+     * 构造器
+     *
+     * @param type 类型 1/单表 2/一对多 3/树
+     * @param code 模板编码
+     * @param templatePath  模板路径
+     * @param stylePath  模板子路径
+     * @param note
+     */
+    CgformEnum(int type, String code, String templatePath, String stylePath, String note) {
+        this.type = type;
+        this.code = code;
+        this.templatePath = templatePath;
+        this.stylePath = stylePath;
+        this.note = note;
+    }
+
+    /**
+     * 根据code获取模板路径
+     *
+     * @param code
+     * @return
+     */
+    public static String getTemplatePathByConfig(String code) {
+        return getCgformEnumByConfig(code).templatePath;
+    }
+
+
+    public int getType() {
+        return type;
+    }
+
+    public void setType(int type) {
+        this.type = type;
+    }
+
+    public String getTemplatePath() {
+        return templatePath;
+    }
+
+    public void setTemplatePath(String templatePath) {
+        this.templatePath = templatePath;
+    }
+
+    public String getStylePath() {
+        return stylePath;
+    }
+
+    public void setStylePath(String stylePath) {
+        this.stylePath = stylePath;
+    }
+
+    /**
+     * 根据code找枚举
+     *
+     * @param code
+     * @return
+     */
+    public static CgformEnum getCgformEnumByConfig(String code) {
+        for (CgformEnum e : CgformEnum.values()) {
+            if (e.code.equals(code)) {
+                return e;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * 根据类型找所有
+     *
+     * @param type
+     * @return
+     */
+    public static List<Map<String, Object>> getJspModelList(int type) {
+        List<Map<String, Object>> ls = new ArrayList<Map<String, Object>>();
+        for (CgformEnum e : CgformEnum.values()) {
+            if (e.type == type) {
+                Map<String, Object> map = new HashMap<String, Object>();
+                map.put("code", e.code);
+                map.put("note", e.note);
+                ls.add(map);
+            }
+        }
+        return ls;
+    }
+
+
+}

+ 17 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/constant/enums/ModuleType.java

@@ -0,0 +1,17 @@
+package org.jeecg.common.constant.enums;
+
+/**
+ * 日志按模块分类
+ */
+public enum ModuleType {
+
+    /**
+     * 普通
+     */
+    COMMON,
+
+    /**
+     * online
+     */
+    ONLINE;
+}

+ 515 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/es/JeecgElasticsearchTemplate.java

@@ -0,0 +1,515 @@
+package org.jeecg.common.es;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.jeecg.common.util.RestUtil;
+import org.jeecg.common.util.oConvertUtils;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Component;
+
+import java.util.*;
+
+/**
+ * 关于 ElasticSearch 的一些方法(创建索引、添加数据、查询等)
+ *
+ * @author sunjianlei
+ */
+@Slf4j
+@Component
+public class JeecgElasticsearchTemplate {
+    /** es服务地址 */
+    private String baseUrl;
+    private final String FORMAT_JSON = "format=json";
+
+    // ElasticSearch 最大可返回条目数
+    public static final int ES_MAX_SIZE = 10000;
+
+    public JeecgElasticsearchTemplate(@Value("${jeecg.elasticsearch.cluster-nodes}") String baseUrl, @Value("${jeecg.elasticsearch.check-enabled}") boolean checkEnabled) {
+        log.debug("JeecgElasticsearchTemplate BaseURL:" + baseUrl);
+        if (StringUtils.isNotEmpty(baseUrl)) {
+            this.baseUrl = baseUrl;
+            // 验证配置的ES地址是否有效
+            if (checkEnabled) {
+                try {
+                    RestUtil.get(this.getBaseUrl().toString());
+                    log.info("ElasticSearch 服务连接成功");
+                } catch (Exception e) {
+                    log.warn("ElasticSearch 服务连接失败,原因:配置未通过。可能是BaseURL未配置或配置有误,也可能是Elasticsearch服务未启动。接下来将会拒绝执行任何方法!");
+                }
+            }
+        }
+    }
+
+    public StringBuilder getBaseUrl(String indexName, String typeName) {
+        typeName = typeName.trim().toLowerCase();
+        return this.getBaseUrl(indexName).append("/").append(typeName);
+    }
+
+    public StringBuilder getBaseUrl(String indexName) {
+        indexName = indexName.trim().toLowerCase();
+        return this.getBaseUrl().append("/").append(indexName);
+    }
+
+    public StringBuilder getBaseUrl() {
+        return new StringBuilder("http://").append(this.baseUrl);
+    }
+
+    /**
+     * cat 查询ElasticSearch系统数据,返回json
+     */
+    public <T> ResponseEntity<T> _cat(String urlAfter, Class<T> responseType) {
+        String url = this.getBaseUrl().append("/_cat").append(urlAfter).append("?").append(FORMAT_JSON).toString();
+        return RestUtil.request(url, HttpMethod.GET, null, null, null, responseType);
+    }
+
+    /**
+     * 查询所有索引
+     * <p>
+     * 查询地址:GET http://{baseUrl}/_cat/indices
+     */
+    public JSONArray getIndices() {
+        return getIndices(null);
+    }
+
+
+    /**
+     * 查询单个索引
+     * <p>
+     * 查询地址:GET http://{baseUrl}/_cat/indices/{indexName}
+     */
+    public JSONArray getIndices(String indexName) {
+        StringBuilder urlAfter = new StringBuilder("/indices");
+        if (!StringUtils.isEmpty(indexName)) {
+            urlAfter.append("/").append(indexName.trim().toLowerCase());
+        }
+        return _cat(urlAfter.toString(), JSONArray.class).getBody();
+    }
+
+    /**
+     * 索引是否存在
+     */
+    public boolean indexExists(String indexName) {
+        try {
+            JSONArray array = getIndices(indexName);
+            return array != null;
+        } catch (org.springframework.web.client.HttpClientErrorException ex) {
+            if (HttpStatus.NOT_FOUND == ex.getStatusCode()) {
+                return false;
+            } else {
+                throw ex;
+            }
+        }
+    }
+
+    /**
+     * 根据ID获取索引数据,未查询到返回null
+     * <p>
+     * 查询地址:GET http://{baseUrl}/{indexName}/{typeName}/{dataId}
+     *
+     * @param indexName 索引名称
+     * @param typeName  type,一个任意字符串,用于分类
+     * @param dataId    数据id
+     * @return
+     */
+    public JSONObject getDataById(String indexName, String typeName, String dataId) {
+        String url = this.getBaseUrl(indexName, typeName).append("/").append(dataId).toString();
+        log.info("url:" + url);
+        JSONObject result = RestUtil.get(url);
+        boolean found = result.getBoolean("found");
+        if (found) {
+            return result.getJSONObject("_source");
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * 创建索引
+     * <p>
+     * 查询地址:PUT http://{baseUrl}/{indexName}
+     */
+    public boolean createIndex(String indexName) {
+        String url = this.getBaseUrl(indexName).toString();
+
+        /* 返回结果 (仅供参考)
+        "createIndex": {
+            "shards_acknowledged": true,
+            "acknowledged": true,
+            "index": "hello_world"
+        }
+        */
+        try {
+            return RestUtil.put(url).getBoolean("acknowledged");
+        } catch (org.springframework.web.client.HttpClientErrorException ex) {
+            if (HttpStatus.BAD_REQUEST == ex.getStatusCode()) {
+                log.warn("索引创建失败:" + indexName + " 已存在,无需再创建");
+            } else {
+                ex.printStackTrace();
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 删除索引
+     * <p>
+     * 查询地址:DELETE http://{baseUrl}/{indexName}
+     */
+    public boolean removeIndex(String indexName) {
+        String url = this.getBaseUrl(indexName).toString();
+        try {
+            return RestUtil.delete(url).getBoolean("acknowledged");
+        } catch (org.springframework.web.client.HttpClientErrorException ex) {
+            if (HttpStatus.NOT_FOUND == ex.getStatusCode()) {
+                log.warn("索引删除失败:" + indexName + " 不存在,无需删除");
+            } else {
+                ex.printStackTrace();
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 获取索引字段映射(可获取字段类型)
+     * <p>
+     *
+     * @param indexName 索引名称
+     * @param typeName  分类名称
+     * @return
+     */
+    public JSONObject getIndexMapping(String indexName, String typeName) {
+        String url = this.getBaseUrl(indexName, typeName).append("/_mapping?").append(FORMAT_JSON).toString();
+        log.info("getIndexMapping-url:" + url);
+        /*
+         * 参考返回JSON结构:
+         *
+         *{
+         *    // 索引名称
+         *    "[indexName]": {
+         *        "mappings": {
+         *            // 分类名称
+         *            "[typeName]": {
+         *                "properties": {
+         *                    // 字段名
+         *                    "input_number": {
+         *                        // 字段类型
+         *                        "type": "long"
+         *                    },
+         *                    "input_string": {
+         *                        "type": "text",
+         *                        "fields": {
+         *                            "keyword": {
+         *                                "type": "keyword",
+         *                                "ignore_above": 256
+         *                            }
+         *                        }
+         *                    }
+         *                 }
+         *            }
+         *        }
+         *    }
+         * }
+         */
+        try {
+            return RestUtil.get(url);
+        } catch (org.springframework.web.client.HttpClientErrorException e) {
+            String message = e.getMessage();
+            if (message != null && message.contains("404 Not Found")) {
+                return null;
+            }
+            throw e;
+        }
+    }
+
+    /**
+     * 获取索引字段映射,返回Java实体类
+     *
+     * @param indexName
+     * @param typeName
+     * @return
+     */
+    public <T> Map<String, T> getIndexMappingFormat(String indexName, String typeName, Class<T> clazz) {
+        JSONObject mapping = this.getIndexMapping(indexName, typeName);
+        Map<String, T> map = new HashMap<>();
+        if (mapping == null) {
+            return map;
+        }
+        // 获取字段属性
+        JSONObject properties = mapping.getJSONObject(indexName)
+                .getJSONObject("mappings")
+                .getJSONObject(typeName)
+                .getJSONObject("properties");
+        // 封装成 java类型
+        for (String key : properties.keySet()) {
+            T entity = properties.getJSONObject(key).toJavaObject(clazz);
+            map.put(key, entity);
+        }
+        return map;
+    }
+
+    /**
+     * 保存数据,详见:saveOrUpdate
+     */
+    public boolean save(String indexName, String typeName, String dataId, JSONObject data) {
+        return this.saveOrUpdate(indexName, typeName, dataId, data);
+    }
+
+    /**
+     * 更新数据,详见:saveOrUpdate
+     */
+    public boolean update(String indexName, String typeName, String dataId, JSONObject data) {
+        return this.saveOrUpdate(indexName, typeName, dataId, data);
+    }
+
+    /**
+     * 保存或修改索引数据
+     * <p>
+     * 查询地址:PUT http://{baseUrl}/{indexName}/{typeName}/{dataId}
+     *
+     * @param indexName 索引名称
+     * @param typeName  type,一个任意字符串,用于分类
+     * @param dataId    数据id
+     * @param data      要存储的数据
+     * @return
+     */
+    public boolean saveOrUpdate(String indexName, String typeName, String dataId, JSONObject data) {
+        String url = this.getBaseUrl(indexName, typeName).append("/").append(dataId).append("?refresh=wait_for").toString();
+        /* 返回结果(仅供参考)
+       "createIndexA2": {
+            "result": "created",
+            "_shards": {
+                "total": 2,
+                "successful": 1,
+                "failed": 0
+            },
+            "_seq_no": 0,
+            "_index": "test_index_1",
+            "_type": "test_type_1",
+            "_id": "a2",
+            "_version": 1,
+            "_primary_term": 1
+        }
+         */
+
+        try {
+            // 去掉 data 中为空的值
+            Set<String> keys = data.keySet();
+            List<String> emptyKeys = new ArrayList<>(keys.size());
+            for (String key : keys) {
+                String value = data.getString(key);
+                //1、剔除空值
+                if (oConvertUtils.isEmpty(value) || "[]".equals(value)) {
+                    emptyKeys.add(key);
+                }
+                //2、剔除上传控件值(会导致ES同步失败,报异常failed to parse field [ge_pic] of type [text] )
+                if (oConvertUtils.isNotEmpty(value) && value.indexOf("[{")!=-1) {
+                    emptyKeys.add(key);
+                    log.info("-------剔除上传控件字段------------key: "+ key);
+                }
+            }
+            for (String key : emptyKeys) {
+                data.remove(key);
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        try {
+            String result = RestUtil.put(url, data).getString("result");
+            return "created".equals(result) || "updated".equals(result);
+        } catch (Exception e) {
+            log.error(e.getMessage() + "\n-- url: " + url + "\n-- data: " + data.toJSONString());
+            //TODO 打印接口返回异常json
+            return false;
+        }
+    }
+
+    /**
+     * 批量保存数据
+     *
+     * @param indexName 索引名称
+     * @param typeName  type,一个任意字符串,用于分类
+     * @param dataList  要存储的数据数组,每行数据必须包含id
+     * @return
+     */
+    public boolean saveBatch(String indexName, String typeName, JSONArray dataList) {
+        String url = this.getBaseUrl().append("/_bulk").append("?refresh=wait_for").toString();
+        StringBuilder bodySB = new StringBuilder();
+        for (int i = 0; i < dataList.size(); i++) {
+            JSONObject data = dataList.getJSONObject(i);
+            String id = data.getString("id");
+            // 该行的操作
+            // {"create": {"_id":"${id}", "_index": "${indexName}", "_type": "${typeName}"}}
+            JSONObject action = new JSONObject();
+            JSONObject actionInfo = new JSONObject();
+            actionInfo.put("_id", id);
+            actionInfo.put("_index", indexName);
+            actionInfo.put("_type", typeName);
+            action.put("create", actionInfo);
+            bodySB.append(action.toJSONString()).append("\n");
+            // 该行的数据
+            data.remove("id");
+            bodySB.append(data.toJSONString()).append("\n");
+        }
+        System.out.println("+-+-+-: bodySB.toString(): " + bodySB.toString());
+        HttpHeaders headers = RestUtil.getHeaderApplicationJson();
+        RestUtil.request(url, HttpMethod.PUT, headers, null, bodySB, JSONObject.class);
+        return true;
+    }
+
+    /**
+     * 删除索引数据
+     * <p>
+     * 请求地址:DELETE http://{baseUrl}/{indexName}/{typeName}/{dataId}
+     */
+    public boolean delete(String indexName, String typeName, String dataId) {
+        String url = this.getBaseUrl(indexName, typeName).append("/").append(dataId).toString();
+        /* 返回结果(仅供参考)
+        {
+            "_index": "es_demo",
+            "_type": "docs",
+            "_id": "001",
+            "_version": 3,
+            "result": "deleted",
+            "_shards": {
+                "total": 1,
+                "successful": 1,
+                "failed": 0
+            },
+            "_seq_no": 28,
+            "_primary_term": 18
+        }
+        */
+        try {
+            return "deleted".equals(RestUtil.delete(url).getString("result"));
+        } catch (org.springframework.web.client.HttpClientErrorException ex) {
+            if (HttpStatus.NOT_FOUND == ex.getStatusCode()) {
+                return false;
+            } else {
+                throw ex;
+            }
+        }
+    }
+
+
+    /* = = = 以下关于查询和查询条件的方法 = = =*/
+
+    /**
+     * 查询数据
+     * <p>
+     * 请求地址:POST http://{baseUrl}/{indexName}/{typeName}/_search
+     */
+    public JSONObject search(String indexName, String typeName, JSONObject queryObject) {
+        String url = this.getBaseUrl(indexName, typeName).append("/_search").toString();
+
+        log.info("url:" + url + " ,search: " + queryObject.toJSONString());
+        JSONObject res = RestUtil.post(url, queryObject);
+        log.info("url:" + url + " ,return res: \n" + res.toJSONString());
+        return res;
+    }
+
+    /**
+     * @param _source (源滤波器)指定返回的字段,传null返回所有字段
+     * @param query
+     * @param from    从第几条数据开始
+     * @param size    返回条目数
+     * @return { "query": query }
+     */
+    public JSONObject buildQuery(List<String> _source, JSONObject query, int from, int size) {
+        JSONObject json = new JSONObject();
+        if (_source != null) {
+            json.put("_source", _source);
+        }
+        json.put("query", query);
+        json.put("from", from);
+        json.put("size", size);
+        return json;
+    }
+
+    /**
+     * @return { "bool" : { "must": must, "must_not": mustNot, "should": should } }
+     */
+    public JSONObject buildBoolQuery(JSONArray must, JSONArray mustNot, JSONArray should) {
+        JSONObject bool = new JSONObject();
+        if (must != null) {
+            bool.put("must", must);
+        }
+        if (mustNot != null) {
+            bool.put("must_not", mustNot);
+        }
+        if (should != null) {
+            bool.put("should", should);
+        }
+        JSONObject json = new JSONObject();
+        json.put("bool", bool);
+        return json;
+    }
+
+    /**
+     * @param field 要查询的字段
+     * @param args  查询参数,参考: *哈哈* OR *哒* NOT *呵* OR *啊*
+     * @return
+     */
+    public JSONObject buildQueryString(String field, String... args) {
+        if (field == null) {
+            return null;
+        }
+        StringBuilder sb = new StringBuilder(field).append(":(");
+        if (args != null) {
+            for (String arg : args) {
+                sb.append(arg).append(" ");
+            }
+        }
+        sb.append(")");
+        return this.buildQueryString(sb.toString());
+    }
+
+    /**
+     * @return { "query_string": { "query": query }  }
+     */
+    public JSONObject buildQueryString(String query) {
+        JSONObject queryString = new JSONObject();
+        queryString.put("query", query);
+        JSONObject json = new JSONObject();
+        json.put("query_string", queryString);
+        return json;
+    }
+
+    /**
+     * @param field      查询字段
+     * @param min        最小值
+     * @param max        最大值
+     * @param containMin 范围内是否包含最小值
+     * @param containMax 范围内是否包含最大值
+     * @return { "range" : { field : { 『 "gt『e』?containMin" : min 』?min!=null , 『 "lt『e』?containMax" : max 』}} }
+     */
+    public JSONObject buildRangeQuery(String field, Object min, Object max, boolean containMin, boolean containMax) {
+        JSONObject inner = new JSONObject();
+        if (min != null) {
+            if (containMin) {
+                inner.put("gte", min);
+            } else {
+                inner.put("gt", min);
+            }
+        }
+        if (max != null) {
+            if (containMax) {
+                inner.put("lte", max);
+            } else {
+                inner.put("lt", max);
+            }
+        }
+        JSONObject range = new JSONObject();
+        range.put(field, inner);
+        JSONObject json = new JSONObject();
+        json.put("range", range);
+        return json;
+    }
+
+}
+

+ 98 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/es/QueryStringBuilder.java

@@ -0,0 +1,98 @@
+package org.jeecg.common.es;
+
+/**
+ * 用于创建 ElasticSearch 的 queryString
+ *
+ * @author sunjianlei
+ */
+public class QueryStringBuilder {
+
+    StringBuilder builder;
+
+    public QueryStringBuilder(String field, String str, boolean not, boolean addQuot) {
+        builder = this.createBuilder(field, str, not, addQuot);
+    }
+
+    public QueryStringBuilder(String field, String str, boolean not) {
+        builder = this.createBuilder(field, str, not, true);
+    }
+
+    /**
+     * 创建 StringBuilder
+     *
+     * @param field
+     * @param str
+     * @param not     是否是不匹配
+     * @param addQuot 是否添加双引号
+     * @return
+     */
+    public StringBuilder createBuilder(String field, String str, boolean not, boolean addQuot) {
+        StringBuilder sb = new StringBuilder(field).append(":(");
+        if (not) {
+            sb.append(" NOT ");
+        }
+        this.addQuotEffect(sb, str, addQuot);
+        return sb;
+    }
+
+    public QueryStringBuilder and(String str) {
+        return this.and(str, true);
+    }
+
+    public QueryStringBuilder and(String str, boolean addQuot) {
+        builder.append(" AND ");
+        this.addQuot(str, addQuot);
+        return this;
+    }
+
+    public QueryStringBuilder or(String str) {
+        return this.or(str, true);
+    }
+
+    public QueryStringBuilder or(String str, boolean addQuot) {
+        builder.append(" OR ");
+        this.addQuot(str, addQuot);
+        return this;
+    }
+
+    public QueryStringBuilder not(String str) {
+        return this.not(str, true);
+    }
+
+    public QueryStringBuilder not(String str, boolean addQuot) {
+        builder.append(" NOT ");
+        this.addQuot(str, addQuot);
+        return this;
+    }
+
+    /**
+    * 添加双引号(模糊查询,不能加双引号)
+    */
+    private QueryStringBuilder addQuot(String str, boolean addQuot) {
+        return this.addQuotEffect(this.builder, str, addQuot);
+    }
+
+    /**
+     * 是否在两边加上双引号
+     * @param builder
+     * @param str
+     * @param addQuot
+     * @return
+     */
+    private QueryStringBuilder addQuotEffect(StringBuilder builder, String str, boolean addQuot) {
+        if (addQuot) {
+            builder.append('"');
+        }
+        builder.append(str);
+        if (addQuot) {
+            builder.append('"');
+        }
+        return this;
+    }
+
+    @Override
+    public String toString() {
+        return builder.append(")").toString();
+    }
+
+}

+ 19 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/exception/JeecgBootException.java

@@ -0,0 +1,19 @@
+package org.jeecg.common.exception;
+
+public class JeecgBootException extends RuntimeException {
+	private static final long serialVersionUID = 1L;
+
+	public JeecgBootException(String message){
+		super(message);
+	}
+	
+	public JeecgBootException(Throwable cause)
+	{
+		super(cause);
+	}
+	
+	public JeecgBootException(String message,Throwable cause)
+	{
+		super(message,cause);
+	}
+}

+ 106 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/exception/JeecgBootExceptionHandler.java

@@ -0,0 +1,106 @@
+package org.jeecg.common.exception;
+
+import io.lettuce.core.RedisConnectionException;
+import org.apache.shiro.authz.AuthorizationException;
+import org.apache.shiro.authz.UnauthorizedException;
+import org.jeecg.common.api.vo.Result;
+import org.springframework.dao.DataIntegrityViolationException;
+import org.springframework.dao.DuplicateKeyException;
+import org.springframework.data.redis.connection.PoolException;
+import org.springframework.web.HttpRequestMethodNotSupportedException;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+import org.springframework.web.multipart.MaxUploadSizeExceededException;
+import org.springframework.web.servlet.NoHandlerFoundException;
+
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * 异常处理器
+ * 
+ * @Author scott
+ * @Date 2019
+ */
+@RestControllerAdvice
+@Slf4j
+public class JeecgBootExceptionHandler {
+
+	/**
+	 * 处理自定义异常
+	 */
+	@ExceptionHandler(JeecgBootException.class)
+	public Result<?> handleRRException(JeecgBootException e){
+		log.error(e.getMessage(), e);
+		return Result.error(e.getMessage());
+	}
+
+	@ExceptionHandler(NoHandlerFoundException.class)
+	public Result<?> handlerNoFoundException(Exception e) {
+		log.error(e.getMessage(), e);
+		return Result.error(404, "路径不存在,请检查路径是否正确");
+	}
+
+	@ExceptionHandler(DuplicateKeyException.class)
+	public Result<?> handleDuplicateKeyException(DuplicateKeyException e){
+		log.error(e.getMessage(), e);
+		return Result.error("数据库中已存在该记录");
+	}
+
+	@ExceptionHandler({UnauthorizedException.class, AuthorizationException.class})
+	public Result<?> handleAuthorizationException(AuthorizationException e){
+		log.error(e.getMessage(), e);
+		return Result.noauth("没有权限,请联系管理员授权");
+	}
+
+	@ExceptionHandler(Exception.class)
+	public Result<?> handleException(Exception e){
+		log.error(e.getMessage(), e);
+		return Result.error("操作失败,"+e.getMessage());
+	}
+	
+	/**
+	 * @Author 政辉
+	 * @param e
+	 * @return
+	 */
+	@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
+	public Result<?> HttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e){
+		StringBuffer sb = new StringBuffer();
+		sb.append("不支持");
+		sb.append(e.getMethod());
+		sb.append("请求方法,");
+		sb.append("支持以下");
+		String [] methods = e.getSupportedMethods();
+		if(methods!=null){
+			for(String str:methods){
+				sb.append(str);
+				sb.append("、");
+			}
+		}
+		log.error(sb.toString(), e);
+		//return Result.error("没有权限,请联系管理员授权");
+		return Result.error(405,sb.toString());
+	}
+	
+	 /** 
+	  * spring默认上传大小100MB 超出大小捕获异常MaxUploadSizeExceededException 
+	  */
+    @ExceptionHandler(MaxUploadSizeExceededException.class)
+    public Result<?> handleMaxUploadSizeExceededException(MaxUploadSizeExceededException e) {
+    	log.error(e.getMessage(), e);
+        return Result.error("文件大小超出10MB限制, 请压缩或降低文件质量! ");
+    }
+
+    @ExceptionHandler(DataIntegrityViolationException.class)
+    public Result<?> handleDataIntegrityViolationException(DataIntegrityViolationException e) {
+    	log.error(e.getMessage(), e);
+        return Result.error("字段太长,超出数据库字段的长度");
+    }
+
+    @ExceptionHandler(PoolException.class)
+    public Result<?> handlePoolException(PoolException e) {
+    	log.error(e.getMessage(), e);
+        return Result.error("Redis 连接异常!");
+    }
+
+}

+ 21 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/handler/IFillRuleHandler.java

@@ -0,0 +1,21 @@
+package org.jeecg.common.handler;
+
+import com.alibaba.fastjson.JSONObject;
+
+/**
+ * 填值规则接口
+ *
+ * @author Yan_东
+ * 如需使用填值规则功能,规则实现类必须实现此接口
+ */
+public interface IFillRuleHandler {
+
+    /**
+     * @param params 页面配置固定参数
+     * @param formData  动态表单参数
+     * @return
+     */
+    public Object execute(JSONObject params, JSONObject formData);
+
+}
+

+ 194 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/system/base/controller/JeecgController.java

@@ -0,0 +1,194 @@
+package org.jeecg.common.system.base.controller;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.beanutils.PropertyUtils;
+import org.apache.shiro.SecurityUtils;
+import org.jeecg.common.api.vo.Result;
+import org.jeecg.common.system.query.QueryGenerator;
+import org.jeecg.common.system.vo.LoginUser;
+import org.jeecg.common.util.oConvertUtils;
+import org.jeecgframework.poi.excel.ExcelImportUtil;
+import org.jeecgframework.poi.excel.def.NormalExcelConstants;
+import org.jeecgframework.poi.excel.entity.ExportParams;
+import org.jeecgframework.poi.excel.entity.ImportParams;
+import org.jeecgframework.poi.excel.entity.enmus.ExcelType;
+import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.web.multipart.MultipartFile;
+import org.springframework.web.multipart.MultipartHttpServletRequest;
+import org.springframework.web.servlet.ModelAndView;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * @Description: Controller基类
+ * @Author: dangzhenghui@163.com
+ * @Date: 2019-4-21 8:13
+ * @Version: 1.0
+ */
+@Slf4j
+public class JeecgController<T, S extends IService<T>> {
+    @Autowired
+    S service;
+
+    @Value("${jeecg.path.upload}")
+    private String upLoadPath;
+    /**
+     * 导出excel
+     *
+     * @param request
+     */
+    protected ModelAndView exportXls(HttpServletRequest request, T object, Class<T> clazz, String title) {
+        // Step.1 组装查询条件
+        QueryWrapper<T> queryWrapper = QueryGenerator.initQueryWrapper(object, request.getParameterMap());
+        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
+
+        // Step.2 获取导出数据
+        List<T> pageList = service.list(queryWrapper);
+        List<T> exportList = null;
+
+        // 过滤选中数据
+        String selections = request.getParameter("selections");
+        if (oConvertUtils.isNotEmpty(selections)) {
+            List<String> selectionList = Arrays.asList(selections.split(","));
+            exportList = pageList.stream().filter(item -> selectionList.contains(getId(item))).collect(Collectors.toList());
+        } else {
+            exportList = pageList;
+        }
+
+        // Step.3 AutoPoi 导出Excel
+        ModelAndView mv = new ModelAndView(new JeecgEntityExcelView());
+        mv.addObject(NormalExcelConstants.FILE_NAME, title); //此处设置的filename无效 ,前端会重更新设置一下
+        mv.addObject(NormalExcelConstants.CLASS, clazz);
+        //update-begin--Author:liusq  Date:20210126 for:图片导出报错,ImageBasePath未设置--------------------
+        ExportParams  exportParams=new ExportParams(title + "报表", "导出人:" + sysUser.getRealname(), title);
+        exportParams.setImageBasePath(upLoadPath);
+        //update-end--Author:liusq  Date:20210126 for:图片导出报错,ImageBasePath未设置----------------------
+        mv.addObject(NormalExcelConstants.PARAMS,exportParams);
+        mv.addObject(NormalExcelConstants.DATA_LIST, exportList);
+        return mv;
+    }
+    /**
+     * 根据每页sheet数量导出多sheet
+     *
+     * @param request
+     * @param object 实体类
+     * @param clazz 实体类class
+     * @param title 标题
+     * @param exportFields 导出字段自定义
+     * @param pageNum 每个sheet的数据条数
+     * @param request
+     */
+    protected ModelAndView exportXlsSheet(HttpServletRequest request, T object, Class<T> clazz, String title,String exportFields,Integer pageNum) {
+        // Step.1 组装查询条件
+        QueryWrapper<T> queryWrapper = QueryGenerator.initQueryWrapper(object, request.getParameterMap());
+        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
+        // Step.2 计算分页sheet数据
+        double total = service.count();
+        int count = (int)Math.ceil(total/pageNum);
+        // Step.3 多sheet处理
+        List<Map<String, Object>> listMap = new ArrayList<Map<String, Object>>();
+        for (int i = 1; i <=count ; i++) {
+            Page<T> page = new Page<T>(i, pageNum);
+            IPage<T> pageList = service.page(page, queryWrapper);
+            List<T> records = pageList.getRecords();
+            List<T> exportList = null;
+            // 过滤选中数据
+            String selections = request.getParameter("selections");
+            if (oConvertUtils.isNotEmpty(selections)) {
+                List<String> selectionList = Arrays.asList(selections.split(","));
+                exportList = records.stream().filter(item -> selectionList.contains(getId(item))).collect(Collectors.toList());
+            } else {
+                exportList = records;
+            }
+            Map<String, Object> map = new HashMap<String, Object>();
+            ExportParams  exportParams=new ExportParams(title + "报表", "导出人:" + sysUser.getRealname(), title+i,upLoadPath);
+            exportParams.setType(ExcelType.XSSF);
+            //map.put("title",exportParams);//表格Title
+            map.put(NormalExcelConstants.PARAMS,exportParams);//表格Title
+            map.put(NormalExcelConstants.CLASS,clazz);//表格对应实体
+            map.put(NormalExcelConstants.DATA_LIST, exportList);//数据集合
+            listMap.add(map);
+        }
+        // Step.4 AutoPoi 导出Excel
+        ModelAndView mv = new ModelAndView(new JeecgEntityExcelView());
+        mv.addObject(NormalExcelConstants.FILE_NAME, title); //此处设置的filename无效 ,前端会重更新设置一下
+        mv.addObject(NormalExcelConstants.MAP_LIST, listMap);
+        return mv;
+    }
+
+
+    /**
+     * 根据权限导出excel,传入导出字段参数
+     *
+     * @param request
+     */
+    protected ModelAndView exportXls(HttpServletRequest request, T object, Class<T> clazz, String title,String exportFields) {
+        ModelAndView mv = this.exportXls(request,object,clazz,title);
+        mv.addObject(NormalExcelConstants.EXPORT_FIELDS,exportFields);
+        return mv;
+    }
+
+    /**
+     * 获取对象ID
+     *
+     * @return
+     */
+    private String getId(T item) {
+        try {
+            return PropertyUtils.getProperty(item, "id").toString();
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    /**
+     * 通过excel导入数据
+     *
+     * @param request
+     * @param response
+     * @return
+     */
+    protected Result<?> importExcel(HttpServletRequest request, HttpServletResponse response, Class<T> clazz) {
+        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
+        Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
+        for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
+            MultipartFile file = entity.getValue();// 获取上传文件对象
+            ImportParams params = new ImportParams();
+            params.setTitleRows(2);
+            params.setHeadRows(1);
+            params.setNeedSave(true);
+            try {
+                List<T> list = ExcelImportUtil.importExcel(file.getInputStream(), clazz, params);
+                //update-begin-author:taoyan date:20190528 for:批量插入数据
+                long start = System.currentTimeMillis();
+                service.saveBatch(list);
+                //400条 saveBatch消耗时间1592毫秒  循环插入消耗时间1947毫秒
+                //1200条  saveBatch消耗时间3687毫秒 循环插入消耗时间5212毫秒
+                log.info("消耗时间" + (System.currentTimeMillis() - start) + "毫秒");
+                //update-end-author:taoyan date:20190528 for:批量插入数据
+                return Result.ok("文件导入成功!数据行数:" + list.size());
+            } catch (Exception e) {
+                log.error(e.getMessage(), e);
+                return Result.error("文件导入失败:" + e.getMessage());
+            } finally {
+                try {
+                    file.getInputStream().close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+        return Result.error("文件导入失败!");
+    }
+}

+ 52 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/system/base/entity/JeecgEntity.java

@@ -0,0 +1,52 @@
+package org.jeecg.common.system.base.entity;
+
+import java.io.Serializable;
+import org.jeecgframework.poi.excel.annotation.Excel;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+/**
+ * @Description: Entity基类
+ * @Author: dangzhenghui@163.com
+ * @Date: 2019-4-28
+ * @Version: 1.1
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+public class JeecgEntity implements Serializable {
+	private static final long serialVersionUID = 1L;
+
+	/** ID */
+	@TableId(type = IdType.ASSIGN_ID)
+	@ApiModelProperty(value = "ID")
+	private java.lang.String id;
+	/** 创建人 */
+	@ApiModelProperty(value = "创建人")
+	@Excel(name = "创建人", width = 15)
+	private java.lang.String createBy;
+	/** 创建时间 */
+	@ApiModelProperty(value = "创建时间")
+	@Excel(name = "创建时间", width = 20, format = "yyyy-MM-dd HH:mm:ss")
+	@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
+	@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+	private java.util.Date createTime;
+	/** 更新人 */
+	@ApiModelProperty(value = "更新人")
+	@Excel(name = "更新人", width = 15)
+	private java.lang.String updateBy;
+	/** 更新时间 */
+	@ApiModelProperty(value = "更新时间")
+	@Excel(name = "更新时间", width = 20, format = "yyyy-MM-dd HH:mm:ss")
+	@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
+	@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+	private java.util.Date updateTime;
+}

+ 12 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/system/base/service/JeecgService.java

@@ -0,0 +1,12 @@
+package org.jeecg.common.system.base.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * @Description: Service基类
+ * @Author: dangzhenghui@163.com
+ * @Date: 2019-4-21 8:13
+ * @Version: 1.0
+ */
+public interface JeecgService<T> extends IService<T> {
+}

+ 19 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/system/base/service/impl/JeecgServiceImpl.java

@@ -0,0 +1,19 @@
+package org.jeecg.common.system.base.service.impl;
+
+import org.jeecg.common.system.base.entity.JeecgEntity;
+import org.jeecg.common.system.base.service.JeecgService;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * @Description: ServiceImpl基类
+ * @Author: dangzhenghui@163.com
+ * @Date: 2019-4-21 8:13
+ * @Version: 1.0
+ */
+@Slf4j
+public class JeecgServiceImpl<M extends BaseMapper<T>, T extends JeecgEntity> extends ServiceImpl<M, T> implements JeecgService<T> {
+
+}

+ 43 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/system/query/MatchTypeEnum.java

@@ -0,0 +1,43 @@
+package org.jeecg.common.system.query;
+
+import org.jeecg.common.util.oConvertUtils;
+
+/**
+ * 查询链接规则
+ *
+ * @Author Sunjianlei
+ */
+public enum MatchTypeEnum {
+
+    AND("AND"),
+    OR("OR");
+
+    private String value;
+
+    MatchTypeEnum(String value) {
+        this.value = value;
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+    public static MatchTypeEnum getByValue(Object value) {
+        if (oConvertUtils.isEmpty(value)) {
+            return null;
+        }
+        return getByValue(value.toString());
+    }
+
+    public static MatchTypeEnum getByValue(String value) {
+        if (oConvertUtils.isEmpty(value)) {
+            return null;
+        }
+        for (MatchTypeEnum val : values()) {
+            if (val.getValue().toLowerCase().equals(value.toLowerCase())) {
+                return val;
+            }
+        }
+        return null;
+    }
+}

+ 55 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/system/query/QueryCondition.java

@@ -0,0 +1,55 @@
+package org.jeecg.common.system.query;
+
+import java.io.Serializable;
+
+public class QueryCondition implements Serializable {
+
+	private static final long serialVersionUID = 4740166316629191651L;
+	
+	private String field;
+	private String type;
+	private String rule;
+	private String val;
+	
+	public String getField() {
+		return field;
+	}
+
+	public void setField(String field) {
+		this.field = field;
+	}
+
+	public String getType() {
+		return type;
+	}
+
+	public void setType(String type) {
+		this.type = type;
+	}
+
+	public String getRule() {
+		return rule;
+	}
+
+	public void setRule(String rule) {
+		this.rule = rule;
+	}
+
+	public String getVal() {
+		return val;
+	}
+
+	public void setVal(String val) {
+		this.val = val;
+	}
+
+	@Override
+	public String toString(){
+		StringBuffer sb =new StringBuffer();
+		if(field == null || "".equals(field)){
+			return "";
+		}
+		sb.append(this.field).append(" ").append(this.rule).append(" ").append(this.type).append(" ").append(this.val);
+		return sb.toString();
+	}
+}

+ 1097 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/system/query/QueryGenerator.java

@@ -0,0 +1,1097 @@
+package org.jeecg.common.system.query;
+
+import com.alibaba.fastjson.JSON;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.beanutils.PropertyUtils;
+import org.jeecg.common.constant.CommonConstant;
+import org.jeecg.common.constant.DataBaseConstant;
+import org.jeecg.common.system.util.JeecgDataAutorUtils;
+import org.jeecg.common.system.util.JwtUtil;
+import org.jeecg.common.system.vo.SysPermissionDataRuleModel;
+import org.jeecg.common.util.CommonUtils;
+import org.jeecg.common.util.DateUtils;
+import org.jeecg.common.util.SqlInjectionUtil;
+import org.jeecg.common.util.oConvertUtils;
+import org.springframework.util.NumberUtils;
+
+import java.beans.PropertyDescriptor;
+import java.io.UnsupportedEncodingException;
+import java.lang.reflect.Field;
+import java.math.BigDecimal;
+import java.net.URLDecoder;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+@Slf4j
+public class QueryGenerator {
+	public static final String SQL_RULES_COLUMN = "SQL_RULES_COLUMN";
+
+	private static final String BEGIN = "_begin";
+	private static final String END = "_end";
+	/**
+	 * 数字类型字段,拼接此后缀 接受多值参数
+	 */
+	private static final String MULTI = "_MultiString";
+	private static final String STAR = "*";
+	private static final String COMMA = ",";
+	/**
+	 * 查询 逗号转义符 相当于一个逗号【作废】
+	 */
+	public static final String QUERY_COMMA_ESCAPE = "++";
+	private static final String NOT_EQUAL = "!";
+	/**页面带有规则值查询,空格作为分隔符*/
+	private static final String QUERY_SEPARATE_KEYWORD = " ";
+	/**高级查询前端传来的参数名*/
+	private static final String SUPER_QUERY_PARAMS = "superQueryParams";
+	/** 高级查询前端传来的拼接方式参数名 */
+	private static final String SUPER_QUERY_MATCH_TYPE = "superQueryMatchType";
+	/** 单引号 */
+	public static final String SQL_SQ = "'";
+	/**排序列*/
+	private static final String ORDER_COLUMN = "column";
+	/**排序方式*/
+	private static final String ORDER_TYPE = "order";
+	private static final String ORDER_TYPE_ASC = "ASC";
+
+	/**mysql 模糊查询之特殊字符下划线 (_、\)*/
+	public static final String LIKE_MYSQL_SPECIAL_STRS = "_,%";
+	
+	/**时间格式化 */
+	private static final ThreadLocal<SimpleDateFormat> local = new ThreadLocal<SimpleDateFormat>();
+	private static SimpleDateFormat getTime(){
+		SimpleDateFormat time = local.get();
+		if(time == null){
+			time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+			local.set(time);
+		}
+		return time;
+	}
+	
+	/**
+	 * 获取查询条件构造器QueryWrapper实例 通用查询条件已被封装完成
+	 * @param searchObj 查询实体
+	 * @param parameterMap request.getParameterMap()
+	 * @return QueryWrapper实例
+	 */
+	public static <T> QueryWrapper<T> initQueryWrapper(T searchObj,Map<String, String[]> parameterMap){
+		long start = System.currentTimeMillis();
+		QueryWrapper<T> queryWrapper = new QueryWrapper<T>();
+		installMplus(queryWrapper, searchObj, parameterMap);
+		log.debug("---查询条件构造器初始化完成,耗时:"+(System.currentTimeMillis()-start)+"毫秒----");
+		return queryWrapper;
+	}
+
+	/**
+	 * 组装Mybatis Plus 查询条件
+	 * <p>使用此方法 需要有如下几点注意:   
+	 * <br>1.使用QueryWrapper 而非LambdaQueryWrapper;
+	 * <br>2.实例化QueryWrapper时不可将实体传入参数   
+	 * <br>错误示例:如QueryWrapper<JeecgDemo> queryWrapper = new QueryWrapper<JeecgDemo>(jeecgDemo);
+	 * <br>正确示例:QueryWrapper<JeecgDemo> queryWrapper = new QueryWrapper<JeecgDemo>();
+	 * <br>3.也可以不使用这个方法直接调用 {@link #initQueryWrapper}直接获取实例
+	 */
+	public static void installMplus(QueryWrapper<?> queryWrapper,Object searchObj,Map<String, String[]> parameterMap) {
+		
+		/*
+		 * 注意:权限查询由前端配置数据规则 当一个人有多个所属部门时候 可以在规则配置包含条件 orgCode 包含 #{sys_org_code}
+		但是不支持在自定义SQL中写orgCode in #{sys_org_code} 
+		当一个人只有一个部门 就直接配置等于条件: orgCode 等于 #{sys_org_code} 或者配置自定义SQL: orgCode = '#{sys_org_code}'
+		*/
+		
+		//区间条件组装 模糊查询 高级查询组装 简单排序 权限查询
+		PropertyDescriptor origDescriptors[] = PropertyUtils.getPropertyDescriptors(searchObj);
+		Map<String,SysPermissionDataRuleModel> ruleMap = getRuleMap();
+		
+		//权限规则自定义SQL表达式
+		for (String c : ruleMap.keySet()) {
+			if(oConvertUtils.isNotEmpty(c) && c.startsWith(SQL_RULES_COLUMN)){
+				queryWrapper.and(i ->i.apply(getSqlRuleValue(ruleMap.get(c).getRuleValue())));
+			}
+		}
+		
+		String name, type, column;
+		// update-begin--Author:taoyan  Date:20200923 for:issues/1671 如果字段加注解了@TableField(exist = false),不走DB查询-------
+		//定义实体字段和数据库字段名称的映射 高级查询中 只能获取实体字段 如果设置TableField注解 那么查询条件会出问题
+		Map<String,String> fieldColumnMap = new HashMap<String,String>();
+		for (int i = 0; i < origDescriptors.length; i++) {
+			//aliasName = origDescriptors[i].getName();  mybatis  不存在实体属性 不用处理别名的情况
+			name = origDescriptors[i].getName();
+			type = origDescriptors[i].getPropertyType().toString();
+			try {
+				if (judgedIsUselessField(name)|| !PropertyUtils.isReadable(searchObj, name)) {
+					continue;
+				}
+
+				Object value = PropertyUtils.getSimpleProperty(searchObj, name);
+				column = getTableFieldName(searchObj.getClass(), name);
+				if(column==null){
+					//column为null只有一种情况 那就是 添加了注解@TableField(exist = false) 后续都不用处理了
+					continue;
+				}
+				fieldColumnMap.put(name,column);
+				//数据权限查询
+				if(ruleMap.containsKey(name)) {
+					addRuleToQueryWrapper(ruleMap.get(name), column, origDescriptors[i].getPropertyType(), queryWrapper);
+				}
+				//区间查询
+				doIntervalQuery(queryWrapper, parameterMap, type, name, column);
+				//判断单值  参数带不同标识字符串 走不同的查询
+				//TODO 这种前后带逗号的支持分割后模糊查询需要否 使多选字段的查询生效
+				if (null != value && value.toString().startsWith(COMMA) && value.toString().endsWith(COMMA)) {
+					String multiLikeval = value.toString().replace(",,", COMMA);
+					String[] vals = multiLikeval.substring(1, multiLikeval.length()).split(COMMA);
+					final String field = oConvertUtils.camelToUnderline(column);
+					if(vals.length>1) {
+						queryWrapper.and(j -> {
+							j = j.like(field,vals[0]);
+							for (int k=1;k<vals.length;k++) {
+								j = j.or().like(field,vals[k]);
+							}
+							//return j;
+						});
+					}else {
+						queryWrapper.and(j -> j.like(field,vals[0]));
+					}
+				}else {
+					//根据参数值带什么关键字符串判断走什么类型的查询
+					QueryRuleEnum rule = convert2Rule(value);
+					value = replaceValue(rule,value);
+					// add -begin 添加判断为字符串时设为全模糊查询
+					//if( (rule==null || QueryRuleEnum.EQ.equals(rule)) && "class java.lang.String".equals(type)) {
+						// 可以设置左右模糊或全模糊,因人而异
+						//rule = QueryRuleEnum.LIKE;
+					//}
+					// add -end 添加判断为字符串时设为全模糊查询
+					addEasyQuery(queryWrapper, column, rule, value);
+				}
+				
+			} catch (Exception e) {
+				log.error(e.getMessage(), e);
+			}
+		}
+		// 排序逻辑 处理 
+		doMultiFieldsOrder(queryWrapper, parameterMap);
+				
+		//高级查询
+		doSuperQuery(queryWrapper, parameterMap, fieldColumnMap);
+		// update-end--Author:taoyan  Date:20200923 for:issues/1671 如果字段加注解了@TableField(exist = false),不走DB查询-------
+		
+	}
+
+
+	/**
+	 * 区间查询
+	 * @param queryWrapper query对象
+	 * @param parameterMap 参数map
+	 * @param type         字段类型
+	 * @param filedName    字段名称
+	 * @param columnName   列名称
+	 */
+	private static void doIntervalQuery(QueryWrapper<?> queryWrapper, Map<String, String[]> parameterMap, String type, String filedName, String columnName) throws ParseException {
+		// 添加 判断是否有区间值
+		String endValue = null,beginValue = null;
+		if (parameterMap != null && parameterMap.containsKey(filedName + BEGIN)) {
+			beginValue = parameterMap.get(filedName + BEGIN)[0].trim();
+			addQueryByRule(queryWrapper, columnName, type, beginValue, QueryRuleEnum.GE);
+
+		}
+		if (parameterMap != null && parameterMap.containsKey(filedName + END)) {
+			endValue = parameterMap.get(filedName + END)[0].trim();
+			addQueryByRule(queryWrapper, columnName, type, endValue, QueryRuleEnum.LE);
+		}
+		//多值查询
+		if (parameterMap != null && parameterMap.containsKey(filedName + MULTI)) {
+			endValue = parameterMap.get(filedName + MULTI)[0].trim();
+			addQueryByRule(queryWrapper, columnName.replace(MULTI,""), type, endValue, QueryRuleEnum.IN);
+		}
+	}
+	
+	//多字段排序 TODO 需要修改前端
+	public static void doMultiFieldsOrder(QueryWrapper<?> queryWrapper,Map<String, String[]> parameterMap) {
+		String column=null,order=null;
+		if(parameterMap!=null&& parameterMap.containsKey(ORDER_COLUMN)) {
+			column = parameterMap.get(ORDER_COLUMN)[0];
+		}
+		if(parameterMap!=null&& parameterMap.containsKey(ORDER_TYPE)) {
+			order = parameterMap.get(ORDER_TYPE)[0];
+		}
+        log.info("排序规则>>列:" + column + ",排序方式:" + order);
+		if (oConvertUtils.isNotEmpty(column) && oConvertUtils.isNotEmpty(order)) {
+			//字典字段,去掉字典翻译文本后缀
+			if(column.endsWith(CommonConstant.DICT_TEXT_SUFFIX)) {
+				column = column.substring(0, column.lastIndexOf(CommonConstant.DICT_TEXT_SUFFIX));
+			}
+			//SQL注入check
+			SqlInjectionUtil.filterContent(column);
+
+			//update-begin--Author:scott  Date:20210531 for:36 多条件排序无效问题修正-------
+			// 排序规则修改
+			// 将现有排序 _ 前端传递排序条件{....,column: 'column1,column2',order: 'desc'} 翻译成sql "column1,column2 desc"
+			// 修改为 _ 前端传递排序条件{....,column: 'column1,column2',order: 'desc'} 翻译成sql "column1 desc,column2 desc"
+			if (order.toUpperCase().indexOf(ORDER_TYPE_ASC)>=0) {
+				//queryWrapper.orderByAsc(oConvertUtils.camelToUnderline(column));
+				String columnStr = oConvertUtils.camelToUnderline(column);
+				String[] columnArray = columnStr.split(",");
+				queryWrapper.orderByAsc(columnArray);
+			} else {
+				//queryWrapper.orderByDesc(oConvertUtils.camelToUnderline(column));
+				String columnStr = oConvertUtils.camelToUnderline(column);
+				String[] columnArray = columnStr.split(",");
+				queryWrapper.orderByDesc(columnArray);
+			}
+			//update-end--Author:scott  Date:20210531 for:36 多条件排序无效问题修正-------
+		}
+	}
+	
+	/**
+	 * 高级查询
+	 * @param queryWrapper 查询对象
+	 * @param parameterMap 参数对象
+	 * @param fieldColumnMap 实体字段和数据库列对应的map
+	 */
+	public static void doSuperQuery(QueryWrapper<?> queryWrapper,Map<String, String[]> parameterMap, Map<String,String> fieldColumnMap) {
+		if(parameterMap!=null&& parameterMap.containsKey(SUPER_QUERY_PARAMS)){
+			String superQueryParams = parameterMap.get(SUPER_QUERY_PARAMS)[0];
+			String superQueryMatchType = parameterMap.get(SUPER_QUERY_MATCH_TYPE) != null ? parameterMap.get(SUPER_QUERY_MATCH_TYPE)[0] : MatchTypeEnum.AND.getValue();
+            MatchTypeEnum matchType = MatchTypeEnum.getByValue(superQueryMatchType);
+            // update-begin--Author:sunjianlei  Date:20200325 for:高级查询的条件要用括号括起来,防止和用户的其他条件冲突 -------
+            try {
+                superQueryParams = URLDecoder.decode(superQueryParams, "UTF-8");
+                List<QueryCondition> conditions = JSON.parseArray(superQueryParams, QueryCondition.class);
+                if (conditions == null || conditions.size() == 0) {
+                    return;
+                }
+                log.info("---高级查询参数-->" + conditions.toString());
+                queryWrapper.and(andWrapper -> {
+                    for (int i = 0; i < conditions.size(); i++) {
+                        QueryCondition rule = conditions.get(i);
+                        if (oConvertUtils.isNotEmpty(rule.getField())
+                                && oConvertUtils.isNotEmpty(rule.getRule())
+                                && oConvertUtils.isNotEmpty(rule.getVal())) {
+
+                            log.debug("SuperQuery ==> " + rule.toString());
+
+                            //update-begin-author:taoyan date:20201228 for: 【高级查询】 oracle 日期等于查询报错
+							Object queryValue = rule.getVal();
+                            if("date".equals(rule.getType())){
+								queryValue = DateUtils.str2Date(rule.getVal(),DateUtils.date_sdf.get());
+							}else if("datetime".equals(rule.getType())){
+								queryValue = DateUtils.str2Date(rule.getVal(), DateUtils.datetimeFormat.get());
+							}
+                            addEasyQuery(andWrapper, fieldColumnMap.get(rule.getField()), QueryRuleEnum.getByValue(rule.getRule()), queryValue);
+							//update-end-author:taoyan date:20201228 for: 【高级查询】 oracle 日期等于查询报错
+
+                            // 如果拼接方式是OR,就拼接OR
+                            if (MatchTypeEnum.OR == matchType && i < (conditions.size() - 1)) {
+                                andWrapper.or();
+                            }
+                        }
+                    }
+                    //return andWrapper;
+                });
+            } catch (UnsupportedEncodingException e) {
+                log.error("--高级查询参数转码失败:" + superQueryParams, e);
+            } catch (Exception e) {
+                log.error("--高级查询拼接失败:" + e.getMessage());
+                e.printStackTrace();
+            }
+            // update-end--Author:sunjianlei  Date:20200325 for:高级查询的条件要用括号括起来,防止和用户的其他条件冲突 -------
+		}
+		//log.info(" superQuery getCustomSqlSegment: "+ queryWrapper.getCustomSqlSegment());
+	}
+	/**
+	 * 根据所传的值 转化成对应的比较方式
+	 * 支持><= like in !
+	 * @param value
+	 * @return
+	 */
+	private static QueryRuleEnum convert2Rule(Object value) {
+		// 避免空数据
+		if (value == null) {
+			return null;
+		}
+		String val = (value + "").toString().trim();
+		if (val.length() == 0) {
+			return null;
+		}
+		QueryRuleEnum rule =null;
+
+		//update-begin--Author:scott  Date:20190724 for:initQueryWrapper组装sql查询条件错误 #284-------------------
+		//TODO 此处规则,只适用于 le lt ge gt
+		// step 2 .>= =<
+		if (rule == null && val.length() >= 3) {
+			if(QUERY_SEPARATE_KEYWORD.equals(val.substring(2, 3))){
+				rule = QueryRuleEnum.getByValue(val.substring(0, 2));
+			}
+		}
+		// step 1 .> <
+		if (rule == null && val.length() >= 2) {
+			if(QUERY_SEPARATE_KEYWORD.equals(val.substring(1, 2))){
+				rule = QueryRuleEnum.getByValue(val.substring(0, 1));
+			}
+		}
+		//update-end--Author:scott  Date:20190724 for:initQueryWrapper组装sql查询条件错误 #284---------------------
+
+		// step 3 like
+		if (rule == null && val.contains(STAR)) {
+			if (val.startsWith(STAR) && val.endsWith(STAR)) {
+				rule = QueryRuleEnum.LIKE;
+			} else if (val.startsWith(STAR)) {
+				rule = QueryRuleEnum.LEFT_LIKE;
+			} else if(val.endsWith(STAR)){
+				rule = QueryRuleEnum.RIGHT_LIKE;
+			}
+		}
+
+		// step 4 in
+		if (rule == null && val.contains(COMMA)) {
+			//TODO in 查询这里应该有个bug  如果一字段本身就是多选 此时用in查询 未必能查询出来
+			rule = QueryRuleEnum.IN;
+		}
+		// step 5 != 
+		if(rule == null && val.startsWith(NOT_EQUAL)){
+			rule = QueryRuleEnum.NE;
+		}
+		// step 6 xx+xx+xx 这种情况适用于如果想要用逗号作精确查询 但是系统默认逗号走in 所以可以用++替换【此逻辑作废】
+		if(rule == null && val.indexOf(QUERY_COMMA_ESCAPE)>0){
+			rule = QueryRuleEnum.EQ_WITH_ADD;
+		}
+
+		//update-begin--Author:taoyan  Date:20201229 for:initQueryWrapper组装sql查询条件错误 #284---------------------
+		//特殊处理:Oracle的表达式to_date('xxx','yyyy-MM-dd')含有逗号,会被识别为in查询,转为等于查询
+		if(rule == QueryRuleEnum.IN && val.indexOf("yyyy-MM-dd")>=0 && val.indexOf("to_date")>=0){
+			rule = QueryRuleEnum.EQ;
+		}
+		//update-end--Author:taoyan  Date:20201229 for:initQueryWrapper组装sql查询条件错误 #284---------------------
+
+		return rule != null ? rule : QueryRuleEnum.EQ;
+	}
+	
+	/**
+	 * 替换掉关键字字符
+	 * 
+	 * @param rule
+	 * @param value
+	 * @return
+	 */
+	private static Object replaceValue(QueryRuleEnum rule, Object value) {
+		if (rule == null) {
+			return null;
+		}
+		if (! (value instanceof String)){
+			return value;
+		}
+		String val = (value + "").toString().trim();
+		if (rule == QueryRuleEnum.LIKE) {
+			value = val.substring(1, val.length() - 1);
+			//mysql 模糊查询之特殊字符下划线 (_、\)
+			value = specialStrConvert(value.toString());
+		} else if (rule == QueryRuleEnum.LEFT_LIKE || rule == QueryRuleEnum.NE) {
+			value = val.substring(1);
+			//mysql 模糊查询之特殊字符下划线 (_、\)
+			value = specialStrConvert(value.toString());
+		} else if (rule == QueryRuleEnum.RIGHT_LIKE) {
+			value = val.substring(0, val.length() - 1);
+			//mysql 模糊查询之特殊字符下划线 (_、\)
+			value = specialStrConvert(value.toString());
+		} else if (rule == QueryRuleEnum.IN) {
+			value = val.split(",");
+		} else if (rule == QueryRuleEnum.EQ_WITH_ADD) {
+			value = val.replaceAll("\\+\\+", COMMA);
+		}else {
+			//update-begin--Author:scott  Date:20190724 for:initQueryWrapper组装sql查询条件错误 #284-------------------
+			if(val.startsWith(rule.getValue())){
+				//TODO 此处逻辑应该注释掉-> 如果查询内容中带有查询匹配规则符号,就会被截取的(比如:>=您好)
+				value = val.replaceFirst(rule.getValue(),"");
+			}else if(val.startsWith(rule.getCondition()+QUERY_SEPARATE_KEYWORD)){
+				value = val.replaceFirst(rule.getCondition()+QUERY_SEPARATE_KEYWORD,"").trim();
+			}
+			//update-end--Author:scott  Date:20190724 for:initQueryWrapper组装sql查询条件错误 #284-------------------
+		}
+		return value;
+	}
+	
+	private static void addQueryByRule(QueryWrapper<?> queryWrapper,String name,String type,String value,QueryRuleEnum rule) throws ParseException {
+		if(oConvertUtils.isNotEmpty(value)) {
+			Object temp;
+			// 针对数字类型字段,多值查询
+			if(value.indexOf(COMMA)!=-1){
+				temp = value;
+				addEasyQuery(queryWrapper, name, rule, temp);
+				return;
+			}
+
+			switch (type) {
+			case "class java.lang.Integer":
+				temp =  Integer.parseInt(value);
+				break;
+			case "class java.math.BigDecimal":
+				temp =  new BigDecimal(value);
+				break;
+			case "class java.lang.Short":
+				temp =  Short.parseShort(value);
+				break;
+			case "class java.lang.Long":
+				temp =  Long.parseLong(value);
+				break;
+			case "class java.lang.Float":
+				temp =   Float.parseFloat(value);
+				break;
+			case "class java.lang.Double":
+				temp =  Double.parseDouble(value);
+				break;
+			case "class java.util.Date":
+				temp = getDateQueryByRule(value, rule);
+				break;
+			default:
+				temp = value;
+				break;
+			}
+			addEasyQuery(queryWrapper, name, rule, temp);
+		}
+	}
+	
+	/**
+	 * 获取日期类型的值
+	 * @param value
+	 * @param rule
+	 * @return
+	 * @throws ParseException
+	 */
+	private static Date getDateQueryByRule(String value,QueryRuleEnum rule) throws ParseException {
+		Date date = null;
+		if(value.length()==10) {
+			if(rule==QueryRuleEnum.GE) {
+				//比较大于
+				date = getTime().parse(value + " 00:00:00");
+			}else if(rule==QueryRuleEnum.LE) {
+				//比较小于
+				date = getTime().parse(value + " 23:59:59");
+			}
+			//TODO 日期类型比较特殊 可能oracle下不一定好使
+		}
+		if(date==null) {
+			date = getTime().parse(value);
+		}
+		return date;
+	}
+	
+	/**
+	  * 根据规则走不同的查询
+	 * @param queryWrapper QueryWrapper
+	 * @param name         字段名字
+	 * @param rule         查询规则
+	 * @param value        查询条件值
+	 */
+	private static void addEasyQuery(QueryWrapper<?> queryWrapper, String name, QueryRuleEnum rule, Object value) {
+		if (value == null || rule == null || oConvertUtils.isEmpty(value)) {
+			return;
+		}
+		name = oConvertUtils.camelToUnderline(name);
+		log.info("--查询规则-->"+name+" "+rule.getValue()+" "+value);
+		switch (rule) {
+		case GT:
+			queryWrapper.gt(name, value);
+			break;
+		case GE:
+			queryWrapper.ge(name, value);
+			break;
+		case LT:
+			queryWrapper.lt(name, value);
+			break;
+		case LE:
+			queryWrapper.le(name, value);
+			break;
+		case EQ:
+		case EQ_WITH_ADD:
+			queryWrapper.eq(name, value);
+			break;
+		case NE:
+			queryWrapper.ne(name, value);
+			break;
+		case IN:
+			if(value instanceof String) {
+				queryWrapper.in(name, (Object[])value.toString().split(","));
+			}else if(value instanceof String[]) {
+				queryWrapper.in(name, (Object[]) value);
+			}
+			//update-begin-author:taoyan date:20200909 for:【bug】in 类型多值查询 不适配postgresql #1671
+			else if(value.getClass().isArray()) {
+				queryWrapper.in(name, (Object[])value);
+			}else {
+				queryWrapper.in(name, value);
+			}
+			//update-end-author:taoyan date:20200909 for:【bug】in 类型多值查询 不适配postgresql #1671
+			break;
+		case LIKE:
+			queryWrapper.like(name, value);
+			break;
+		case LEFT_LIKE:
+			queryWrapper.likeLeft(name, value);
+			break;
+		case RIGHT_LIKE:
+			queryWrapper.likeRight(name, value);
+			break;
+		default:
+			log.info("--查询规则未匹配到---");
+			break;
+		}
+	}
+	/**
+	 * 
+	 * @param name
+	 * @return
+	 */
+	private static boolean judgedIsUselessField(String name) {
+		return "class".equals(name) || "ids".equals(name)
+				|| "page".equals(name) || "rows".equals(name)
+				|| "sort".equals(name) || "order".equals(name);
+	}
+
+	
+
+	/**
+	 * 获取请求对应的数据权限规则
+	 * @return
+	 */
+	public static Map<String, SysPermissionDataRuleModel> getRuleMap() {
+		Map<String, SysPermissionDataRuleModel> ruleMap = new HashMap<String, SysPermissionDataRuleModel>();
+		List<SysPermissionDataRuleModel> list =JeecgDataAutorUtils.loadDataSearchConditon();
+		if(list != null&&list.size()>0){
+			if(list.get(0)==null){
+				return ruleMap;
+			}
+			for (SysPermissionDataRuleModel rule : list) {
+				String column = rule.getRuleColumn();
+				if(QueryRuleEnum.SQL_RULES.getValue().equals(rule.getRuleConditions())) {
+					column = SQL_RULES_COLUMN+rule.getId();
+				}
+				ruleMap.put(column, rule);
+			}
+		}
+		return ruleMap;
+	}
+
+	/**
+	 * 获取请求对应的数据权限规则
+	 * @return
+	 */
+	public static Map<String, SysPermissionDataRuleModel> getRuleMap(List<SysPermissionDataRuleModel> list) {
+		Map<String, SysPermissionDataRuleModel> ruleMap = new HashMap<String, SysPermissionDataRuleModel>();
+		if(list==null){
+			list =JeecgDataAutorUtils.loadDataSearchConditon();
+		}
+		if(list != null&&list.size()>0){
+			if(list.get(0)==null){
+				return ruleMap;
+			}
+			for (SysPermissionDataRuleModel rule : list) {
+				String column = rule.getRuleColumn();
+				if(QueryRuleEnum.SQL_RULES.getValue().equals(rule.getRuleConditions())) {
+					column = SQL_RULES_COLUMN+rule.getId();
+				}
+				ruleMap.put(column, rule);
+			}
+		}
+		return ruleMap;
+	}
+	
+	private static void addRuleToQueryWrapper(SysPermissionDataRuleModel dataRule, String name, Class propertyType, QueryWrapper<?> queryWrapper) {
+		QueryRuleEnum rule = QueryRuleEnum.getByValue(dataRule.getRuleConditions());
+		if(rule.equals(QueryRuleEnum.IN) && ! propertyType.equals(String.class)) {
+			String[] values = dataRule.getRuleValue().split(",");
+			Object[] objs = new Object[values.length];
+			for (int i = 0; i < values.length; i++) {
+				objs[i] = NumberUtils.parseNumber(values[i], propertyType);
+			}
+			addEasyQuery(queryWrapper, name, rule, objs);
+		}else {
+			if (propertyType.equals(String.class)) {
+				addEasyQuery(queryWrapper, name, rule, converRuleValue(dataRule.getRuleValue()));
+			}else if (propertyType.equals(Date.class)) {
+				String dateStr =converRuleValue(dataRule.getRuleValue());
+				if(dateStr.length()==10){
+					addEasyQuery(queryWrapper, name, rule, DateUtils.str2Date(dateStr,DateUtils.date_sdf.get()));
+				}else{
+					addEasyQuery(queryWrapper, name, rule, DateUtils.str2Date(dateStr,DateUtils.datetimeFormat.get()));
+				}
+			}else {
+				addEasyQuery(queryWrapper, name, rule, NumberUtils.parseNumber(dataRule.getRuleValue(), propertyType));
+			}
+		}
+	}
+	
+	public static String converRuleValue(String ruleValue) {
+		String value = JwtUtil.getUserSystemData(ruleValue,null);
+		return value!= null ? value : ruleValue;
+	}
+
+	/**
+	* @author: scott
+	* @Description: 去掉值前后单引号
+	* @date: 2020/3/19 21:26
+	* @param ruleValue: 
+	* @Return: java.lang.String
+	*/
+	public static String trimSingleQuote(String ruleValue) {
+		if (oConvertUtils.isEmpty(ruleValue)) {
+			return "";
+		}
+		if (ruleValue.startsWith(QueryGenerator.SQL_SQ)) {
+			ruleValue = ruleValue.substring(1);
+		}
+		if (ruleValue.endsWith(QueryGenerator.SQL_SQ)) {
+			ruleValue = ruleValue.substring(0, ruleValue.length() - 1);
+		}
+		return ruleValue;
+	}
+	
+	public static String getSqlRuleValue(String sqlRule){
+		try {
+			Set<String> varParams = getSqlRuleParams(sqlRule);
+			for(String var:varParams){
+				String tempValue = converRuleValue(var);
+				sqlRule = sqlRule.replace("#{"+var+"}",tempValue);
+			}
+		} catch (Exception e) {
+			log.error(e.getMessage(), e);
+		}
+		return sqlRule;
+	}
+	
+	/**
+	 * 获取sql中的#{key} 这个key组成的set
+	 */
+	public static Set<String> getSqlRuleParams(String sql) {
+		if(oConvertUtils.isEmpty(sql)){
+			return null;
+		}
+		Set<String> varParams = new HashSet<String>();
+		String regex = "\\#\\{\\w+\\}";
+		
+		Pattern p = Pattern.compile(regex);
+		Matcher m = p.matcher(sql);
+		while(m.find()){
+			String var = m.group();
+			varParams.add(var.substring(var.indexOf("{")+1,var.indexOf("}")));
+		}
+		return varParams;
+	}
+	
+	/**
+	 * 获取查询条件 
+	 * @param field
+	 * @param alias
+	 * @param value
+	 * @param isString
+	 * @return
+	 */
+	public static String getSingleQueryConditionSql(String field,String alias,Object value,boolean isString) {
+		return getSingleQueryConditionSql(field, alias, value, isString,null);
+	}
+
+	/**
+	 * 报表获取查询条件 支持多数据源
+	 * @param field
+	 * @param alias
+	 * @param value
+	 * @param isString
+	 * @param dataBaseType
+	 * @return
+	 */
+	public static String getSingleQueryConditionSql(String field,String alias,Object value,boolean isString, String dataBaseType) {
+		if (value == null) {
+			return "";
+		}
+		field =  alias+oConvertUtils.camelToUnderline(field);
+		QueryRuleEnum rule = QueryGenerator.convert2Rule(value);
+		return getSingleSqlByRule(rule, field, value, isString, dataBaseType);
+	}
+
+	/**
+	 * 获取单个查询条件的值
+	 * @param rule
+	 * @param field
+	 * @param value
+	 * @param isString
+	 * @param dataBaseType
+	 * @return
+	 */
+	public static String getSingleSqlByRule(QueryRuleEnum rule,String field,Object value,boolean isString, String dataBaseType) {
+		String res = "";
+		switch (rule) {
+		case GT:
+			res =field+rule.getValue()+getFieldConditionValue(value, isString, dataBaseType);
+			break;
+		case GE:
+			res = field+rule.getValue()+getFieldConditionValue(value, isString, dataBaseType);
+			break;
+		case LT:
+			res = field+rule.getValue()+getFieldConditionValue(value, isString, dataBaseType);
+			break;
+		case LE:
+			res = field+rule.getValue()+getFieldConditionValue(value, isString, dataBaseType);
+			break;
+		case EQ:
+			res = field+rule.getValue()+getFieldConditionValue(value, isString, dataBaseType);
+			break;
+		case EQ_WITH_ADD:
+			res = field+" = "+getFieldConditionValue(value, isString, dataBaseType);
+			break;
+		case NE:
+			res = field+" <> "+getFieldConditionValue(value, isString, dataBaseType);
+			break;
+		case IN:
+			res = field + " in "+getInConditionValue(value, isString);
+			break;
+		case LIKE:
+			res = field + " like "+getLikeConditionValue(value);
+			break;
+		case LEFT_LIKE:
+			res = field + " like "+getLikeConditionValue(value);
+			break;
+		case RIGHT_LIKE:
+			res = field + " like "+getLikeConditionValue(value);
+			break;
+		default:
+			res = field+" = "+getFieldConditionValue(value, isString, dataBaseType);
+			break;
+		}
+		return res;
+	}
+
+
+	/**
+	 * 获取单个查询条件的值
+	 * @param rule
+	 * @param field
+	 * @param value
+	 * @param isString
+	 * @return
+	 */
+	public static String getSingleSqlByRule(QueryRuleEnum rule,String field,Object value,boolean isString) {
+		return getSingleSqlByRule(rule, field, value, isString, null);
+	}
+
+	/**
+	 * 获取查询条件的值
+	 * @param value
+	 * @param isString
+	 * @param dataBaseType
+	 * @return
+	 */
+	private static String getFieldConditionValue(Object value,boolean isString, String dataBaseType) {
+		String str = value.toString().trim();
+		if(str.startsWith("!")) {
+			str = str.substring(1);
+		}else if(str.startsWith(">=")) {
+			str = str.substring(2);
+		}else if(str.startsWith("<=")) {
+			str = str.substring(2);
+		}else if(str.startsWith(">")) {
+			str = str.substring(1);
+		}else if(str.startsWith("<")) {
+			str = str.substring(1);
+		}else if(str.indexOf(QUERY_COMMA_ESCAPE)>0) {
+			str = str.replaceAll("\\+\\+", COMMA);
+		}
+		if(dataBaseType==null){
+			dataBaseType = getDbType();
+		}
+		if(isString) {
+			if(DataBaseConstant.DB_TYPE_SQLSERVER.equals(dataBaseType)){
+				return " N'"+str+"' ";
+			}else{
+				return " '"+str+"' ";
+			}
+		}else {
+			// 如果不是字符串 有一种特殊情况 popup调用都走这个逻辑 参数传递的可能是“‘admin’”这种格式的
+			if(DataBaseConstant.DB_TYPE_SQLSERVER.equals(dataBaseType) && str.endsWith("'") && str.startsWith("'")){
+				return " N"+str;
+			}
+			return value.toString();
+		}
+	}
+
+	private static String getInConditionValue(Object value,boolean isString) {
+		if(isString) {
+			String temp[] = value.toString().split(",");
+			String res="";
+			for (String string : temp) {
+				if(DataBaseConstant.DB_TYPE_SQLSERVER.equals(getDbType())){
+					res+=",N'"+string+"'";
+				}else{
+					res+=",'"+string+"'";
+				}
+			}
+			return "("+res.substring(1)+")";
+		}else {
+			return "("+value.toString()+")";
+		}
+	}
+	
+	private static String getLikeConditionValue(Object value) {
+		String str = value.toString().trim();
+		if(str.startsWith("*") && str.endsWith("*")) {
+			if(DataBaseConstant.DB_TYPE_SQLSERVER.equals(getDbType())){
+				return "N'%"+str.substring(1,str.length()-1)+"%'";
+			}else{
+				return "'%"+str.substring(1,str.length()-1)+"%'";
+			}
+		}else if(str.startsWith("*")) {
+			if(DataBaseConstant.DB_TYPE_SQLSERVER.equals(getDbType())){
+				return "N'%"+str.substring(1)+"'";
+			}else{
+				return "'%"+str.substring(1)+"'";
+			}
+		}else if(str.endsWith("*")) {
+			if(DataBaseConstant.DB_TYPE_SQLSERVER.equals(getDbType())){
+				return "N'"+str.substring(0,str.length()-1)+"%'";
+			}else{
+				return "'"+str.substring(0,str.length()-1)+"%'";
+			}
+		}else {
+			if(str.indexOf("%")>=0) {
+				if(DataBaseConstant.DB_TYPE_SQLSERVER.equals(getDbType())){
+					if(str.startsWith("'") && str.endsWith("'")){
+						return "N"+str;
+					}else{
+						return "N"+"'"+str+"'";
+					}
+				}else{
+					if(str.startsWith("'") && str.endsWith("'")){
+						return str;
+					}else{
+						return "'"+str+"'";
+					}
+				}
+			}else {
+				if(DataBaseConstant.DB_TYPE_SQLSERVER.equals(getDbType())){
+					return "N'%"+str+"%'";
+				}else{
+					return "'%"+str+"%'";
+				}
+			}
+		}
+	}
+	
+	/**
+	 *   根据权限相关配置生成相关的SQL 语句
+	 * @param clazz
+	 * @return
+	 */
+	@SuppressWarnings({ "unchecked", "rawtypes" })
+	public static String installAuthJdbc(Class<?> clazz) {
+		StringBuffer sb = new StringBuffer();
+		//权限查询
+		Map<String,SysPermissionDataRuleModel> ruleMap = getRuleMap();
+		PropertyDescriptor origDescriptors[] = PropertyUtils.getPropertyDescriptors(clazz);
+		String sql_and = " and ";
+		for (String c : ruleMap.keySet()) {
+			if(oConvertUtils.isNotEmpty(c) && c.startsWith(SQL_RULES_COLUMN)){
+				sb.append(sql_and+getSqlRuleValue(ruleMap.get(c).getRuleValue()));
+			}
+		}
+		String name, column;
+		for (int i = 0; i < origDescriptors.length; i++) {
+			name = origDescriptors[i].getName();
+			if (judgedIsUselessField(name)) {
+				continue;
+			}
+			if(ruleMap.containsKey(name)) {
+				column = getTableFieldName(clazz, name);
+				if(column==null){
+					continue;
+				}
+				SysPermissionDataRuleModel dataRule = ruleMap.get(name);
+				QueryRuleEnum rule = QueryRuleEnum.getByValue(dataRule.getRuleConditions());
+				Class propType = origDescriptors[i].getPropertyType();
+				boolean isString = propType.equals(String.class);
+				Object value;
+				if(isString) {
+					value = converRuleValue(dataRule.getRuleValue());
+				}else {
+					value = NumberUtils.parseNumber(dataRule.getRuleValue(),propType);
+				}
+				String filedSql = getSingleSqlByRule(rule, oConvertUtils.camelToUnderline(column), value,isString);
+				sb.append(sql_and+filedSql);
+			}
+		}
+		log.info("query auth sql is:"+sb.toString());
+		return sb.toString();
+	}
+	
+	/**
+	  * 根据权限相关配置 组装mp需要的权限
+	 * @param queryWrapper
+	 * @param clazz
+	 * @return
+	 */
+	public static void installAuthMplus(QueryWrapper<?> queryWrapper,Class<?> clazz) {
+		//权限查询
+		Map<String,SysPermissionDataRuleModel> ruleMap = getRuleMap();
+		PropertyDescriptor origDescriptors[] = PropertyUtils.getPropertyDescriptors(clazz);
+		for (String c : ruleMap.keySet()) {
+			if(oConvertUtils.isNotEmpty(c) && c.startsWith(SQL_RULES_COLUMN)){
+				queryWrapper.and(i ->i.apply(getSqlRuleValue(ruleMap.get(c).getRuleValue())));
+			}
+		}
+		String name, column;
+		for (int i = 0; i < origDescriptors.length; i++) {
+			name = origDescriptors[i].getName();
+			if (judgedIsUselessField(name)) {
+				continue;
+			}
+			column = getTableFieldName(clazz, name);
+			if(column==null){
+				continue;
+			}
+			if(ruleMap.containsKey(name)) {
+				addRuleToQueryWrapper(ruleMap.get(name), column, origDescriptors[i].getPropertyType(), queryWrapper);
+			}
+		}
+	}
+
+	/**
+	 * 转换sql中的系统变量
+	 * @param sql
+	 * @return
+	 */
+	public static String convertSystemVariables(String sql){
+		return getSqlRuleValue(sql);
+	}
+
+	/**
+	 * 获取所有配置的权限 返回sql字符串 不受字段限制 配置什么就拿到什么
+	 * @return
+	 */
+	public static String getAllConfigAuth() {
+		StringBuffer sb = new StringBuffer();
+		//权限查询
+		Map<String,SysPermissionDataRuleModel> ruleMap = getRuleMap();
+		String sql_and = " and ";
+		for (String c : ruleMap.keySet()) {
+			SysPermissionDataRuleModel dataRule = ruleMap.get(c);
+			String ruleValue = dataRule.getRuleValue();
+			if(oConvertUtils.isEmpty(ruleValue)){
+				continue;
+			}
+			if(oConvertUtils.isNotEmpty(c) && c.startsWith(SQL_RULES_COLUMN)){
+				sb.append(sql_and+getSqlRuleValue(ruleValue));
+			}else{
+				boolean isString  = false;
+				ruleValue = ruleValue.trim();
+				if(ruleValue.startsWith("'") && ruleValue.endsWith("'")){
+					isString = true;
+					ruleValue = ruleValue.substring(1,ruleValue.length()-1);
+				}
+				QueryRuleEnum rule = QueryRuleEnum.getByValue(dataRule.getRuleConditions());
+				String value = converRuleValue(ruleValue);
+				String filedSql = getSingleSqlByRule(rule, c, value,isString);
+				sb.append(sql_and+filedSql);
+			}
+		}
+		log.info("query auth sql is = "+sb.toString());
+		return sb.toString();
+	}
+
+
+
+	/** 当前系统数据库类型 */
+	private static String DB_TYPE;
+	/**
+	 * 获取系统数据库类型
+	 */
+	private static String getDbType(){
+		return CommonUtils.getDatabaseType();
+	}
+
+
+	/**
+	 * 获取class的 包括父类的
+	 * @param clazz
+	 * @return
+	 */
+	private static List<Field> getClassFields(Class<?> clazz) {
+		List<Field> list = new ArrayList<Field>();
+		Field[] fields;
+		do{
+			fields = clazz.getDeclaredFields();
+			for(int i = 0;i<fields.length;i++){
+				list.add(fields[i]);
+			}
+			clazz = clazz.getSuperclass();
+		}while(clazz!= Object.class&&clazz!=null);
+		return list;
+	}
+
+	/**
+	 * 获取表字段名
+	 * @param clazz
+	 * @param name
+	 * @return
+	 */
+	private static String getTableFieldName(Class<?> clazz, String name) {
+		try {
+			//如果字段加注解了@TableField(exist = false),不走DB查询
+			Field field = null;
+			try {
+				field = clazz.getDeclaredField(name);
+			} catch (NoSuchFieldException e) {
+				//e.printStackTrace();
+			}
+
+			//如果为空,则去父类查找字段
+			if (field == null) {
+				List<Field> allFields = getClassFields(clazz);
+				List<Field> searchFields = allFields.stream().filter(a -> a.getName().equals(name)).collect(Collectors.toList());
+				if(searchFields!=null && searchFields.size()>0){
+					field = searchFields.get(0);
+				}
+			}
+
+			if (field != null) {
+				TableField tableField = field.getAnnotation(TableField.class);
+				if (tableField != null){
+					if(tableField.exist() == false){
+						//如果设置了TableField false 这个字段不需要处理
+						return null;
+					}else{
+						String column = tableField.value();
+						//如果设置了TableField value 这个字段是实体字段
+						if(!"".equals(column)){
+							return column;
+						}
+					}
+				}
+			}
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+		return name;
+	}
+
+	/**
+	 * mysql 模糊查询之特殊字符下划线 (_、\)
+	 *
+	 * @param value:
+	 * @Return: java.lang.String
+	 */
+	private static String specialStrConvert(String value) {
+		if (DataBaseConstant.DB_TYPE_MYSQL.equals(getDbType()) || DataBaseConstant.DB_TYPE_MARIADB.equals(getDbType())) {
+			String[] special_str = QueryGenerator.LIKE_MYSQL_SPECIAL_STRS.split(",");
+			for (String str : special_str) {
+				if (value.indexOf(str) !=-1) {
+					value = value.replace(str, "\\" + str);
+				}
+			}
+		}
+		return value;
+	}
+}

+ 73 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/system/query/QueryRuleEnum.java

@@ -0,0 +1,73 @@
+package org.jeecg.common.system.query;
+
+import org.jeecg.common.util.oConvertUtils;
+
+/**
+ * Query 规则 常量
+ * @Author Scott
+ * @Date 2019年02月14日
+ */
+public enum QueryRuleEnum {
+
+    GT(">","gt","大于"),
+    GE(">=","ge","大于等于"),
+    LT("<","lt","小于"),
+    LE("<=","le","小于等于"),
+    EQ("=","eq","等于"),
+    NE("!=","ne","不等于"),
+    IN("IN","in","包含"),
+    LIKE("LIKE","like","全模糊"),
+    LEFT_LIKE("LEFT_LIKE","left_like","左模糊"),
+    RIGHT_LIKE("RIGHT_LIKE","right_like","右模糊"),
+    EQ_WITH_ADD("EQWITHADD","eq_with_add","带加号等于"),
+    LIKE_WITH_AND("LIKEWITHAND","like_with_and","多词模糊匹配————暂时未用上"),
+    SQL_RULES("USE_SQL_RULES","ext","自定义SQL片段");
+
+    private String value;
+    
+    private String condition; 
+
+    private String msg;
+
+    QueryRuleEnum(String value, String condition, String msg){
+        this.value = value;
+        this.condition = condition;
+        this.msg = msg;
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+    public void setValue(String value) {
+        this.value = value;
+    }
+
+    public String getMsg() {
+        return msg;
+    }
+
+    public void setMsg(String msg) {
+        this.msg = msg;
+    }
+
+    public String getCondition() {
+		return condition;
+	}
+
+	public void setCondition(String condition) {
+		this.condition = condition;
+	}
+
+	public static QueryRuleEnum getByValue(String value){
+    	if(oConvertUtils.isEmpty(value)) {
+    		return null;
+    	}
+        for(QueryRuleEnum val :values()){
+            if (val.getValue().equals(value) || val.getCondition().equals(value)){
+                return val;
+            }
+        }
+        return  null;
+    }
+}

+ 104 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/system/util/JeecgDataAutorUtils.java

@@ -0,0 +1,104 @@
+package org.jeecg.common.system.util;
+
+import org.jeecg.common.system.vo.SysPermissionDataRuleModel;
+import org.jeecg.common.system.vo.SysUserCacheInfo;
+import org.jeecg.common.util.SpringContextUtils;
+import org.springframework.util.StringUtils;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @ClassName: JeecgDataAutorUtils
+ * @Description: 数据权限查询规则容器工具类
+ * @Author: 张代浩
+ * @Date: 2012-12-15 下午11:27:39
+ * 
+ */
+public class JeecgDataAutorUtils {
+	
+	public static final String MENU_DATA_AUTHOR_RULES = "MENU_DATA_AUTHOR_RULES";
+	
+	public static final String MENU_DATA_AUTHOR_RULE_SQL = "MENU_DATA_AUTHOR_RULE_SQL";
+	
+	public static final String SYS_USER_INFO = "SYS_USER_INFO";
+
+	/**
+	 * 往链接请求里面,传入数据查询条件
+	 * 
+	 * @param request
+	 * @param dataRules
+	 */
+	public static synchronized void installDataSearchConditon(HttpServletRequest request, List<SysPermissionDataRuleModel> dataRules) {
+		@SuppressWarnings("unchecked")
+		List<SysPermissionDataRuleModel> list = (List<SysPermissionDataRuleModel>)loadDataSearchConditon();// 1.先从request获取MENU_DATA_AUTHOR_RULES,如果存则获取到LIST
+		if (list==null) {
+			// 2.如果不存在,则new一个list
+			list = new ArrayList<SysPermissionDataRuleModel>();
+		}
+		for (SysPermissionDataRuleModel tsDataRule : dataRules) {
+			list.add(tsDataRule);
+		}
+		request.setAttribute(MENU_DATA_AUTHOR_RULES, list); // 3.往list里面增量存指
+	}
+
+	/**
+	 * 获取请求对应的数据权限规则
+	 * 
+	 * @return
+	 */
+	@SuppressWarnings("unchecked")
+	public static synchronized List<SysPermissionDataRuleModel> loadDataSearchConditon() {
+		return (List<SysPermissionDataRuleModel>) SpringContextUtils.getHttpServletRequest().getAttribute(MENU_DATA_AUTHOR_RULES);
+				
+	}
+
+	/**
+	 * 获取请求对应的数据权限SQL
+	 * 
+	 * @return
+	 */
+	public static synchronized String loadDataSearchConditonSQLString() {
+		return (String) SpringContextUtils.getHttpServletRequest().getAttribute(MENU_DATA_AUTHOR_RULE_SQL);
+	}
+
+	/**
+	 * 往链接请求里面,传入数据查询条件
+	 * 
+	 * @param request
+	 * @param sql
+	 */
+	public static synchronized void installDataSearchConditon(HttpServletRequest request, String sql) {
+		String ruleSql = (String)loadDataSearchConditonSQLString();
+		if (!StringUtils.hasText(ruleSql)) {
+			request.setAttribute(MENU_DATA_AUTHOR_RULE_SQL,sql);
+		}
+	}
+
+	/**
+	 * 将用户信息存到request
+	 * @param request
+	 * @param userinfo
+	 */
+	public static synchronized void installUserInfo(HttpServletRequest request, SysUserCacheInfo userinfo) {
+		request.setAttribute(SYS_USER_INFO, userinfo);
+	}
+
+	/**
+	 * 将用户信息存到request
+	 * @param userinfo
+	 */
+	public static synchronized void installUserInfo(SysUserCacheInfo userinfo) {
+		SpringContextUtils.getHttpServletRequest().setAttribute(SYS_USER_INFO, userinfo);
+	}
+
+	/**
+	 * 从request获取用户信息
+	 * @return
+	 */
+	public static synchronized SysUserCacheInfo loadUserInfo() {
+		return (SysUserCacheInfo) SpringContextUtils.getHttpServletRequest().getAttribute(SYS_USER_INFO);
+				
+	}
+}

+ 233 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/system/util/JwtUtil.java

@@ -0,0 +1,233 @@
+package org.jeecg.common.system.util;
+
+import com.auth0.jwt.JWT;
+import com.auth0.jwt.JWTVerifier;
+import com.auth0.jwt.algorithms.Algorithm;
+import com.auth0.jwt.exceptions.JWTDecodeException;
+import com.auth0.jwt.interfaces.DecodedJWT;
+import com.google.common.base.Joiner;
+
+import java.util.Date;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
+import org.apache.shiro.SecurityUtils;
+import org.jeecg.common.constant.CommonConstant;
+import org.jeecg.common.constant.DataBaseConstant;
+import org.jeecg.common.exception.JeecgBootException;
+import org.jeecg.common.system.vo.LoginUser;
+import org.jeecg.common.system.vo.SysUserCacheInfo;
+import org.jeecg.common.util.DateUtils;
+import org.jeecg.common.util.SpringContextUtils;
+import org.jeecg.common.util.oConvertUtils;
+
+/**
+ * @Author Scott
+ * @Date 2018-07-12 14:23
+ * @Desc JWT工具类
+ **/
+public class JwtUtil {
+
+	// Token过期时间30分钟(用户登录过期时间是此时间的两倍,以token在reids缓存时间为准)
+	public static final long EXPIRE_TIME = 30 * 60 * 1000;
+	// cas版本过期时间
+
+	public static final long CAS_EXPIRE_TIME = 30 * 60 * 1000 * 2 * 24 * 365;
+
+	/**
+	 * 校验token是否正确
+	 *
+	 * @param token  密钥
+	 * @param secret 用户的密码
+	 * @return 是否正确
+	 */
+	public static boolean verify(String token, String username, String secret) {
+		try {
+			// 根据密码生成JWT效验器
+			Algorithm algorithm = Algorithm.HMAC256(secret);
+			JWTVerifier verifier = JWT.require(algorithm).withClaim("username", username).build();
+			// 效验TOKEN
+			DecodedJWT jwt = verifier.verify(token);
+			return true;
+		} catch (Exception exception) {
+			return false;
+		}
+	}
+
+	/**
+	 * 获得token中的信息无需secret解密也能获得
+	 *
+	 * @return token中包含的用户名
+	 */
+	public static String getUsername(String token) {
+		try {
+			DecodedJWT jwt = JWT.decode(token);
+			return jwt.getClaim("username").asString();
+		} catch (JWTDecodeException e) {
+			return null;
+		}
+	}
+
+	/**
+	 * 生成签名,5min后过期
+	 *
+	 * @param username 用户名
+	 * @param secret   用户的密码
+	 * @return 加密的token
+	 */
+	public static String sign(String username, String secret) {
+		Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
+		Algorithm algorithm = Algorithm.HMAC256(secret);
+		// 附带username信息
+		return JWT.create().withClaim("username", username).withExpiresAt(date).sign(algorithm);
+	}
+
+	/**
+	 * 生成签名,5min后过期
+	 *
+	 * @param username 用户名
+	 * @param secret   用户的密码
+	 * @return 加密的token
+	 */
+	public static String signByCas(String username, String secret) {
+		Date date = new Date(System.currentTimeMillis() + CAS_EXPIRE_TIME);
+		Algorithm algorithm = Algorithm.HMAC256(secret);
+		// 附带username信息
+		return JWT.create().withClaim("username", username).withExpiresAt(date).sign(algorithm);
+	}
+
+	/**
+	 * 根据request中的token获取用户账号
+	 * 
+	 * @param request
+	 * @return
+	 * @throws JeecgBootException
+	 */
+	public static String getUserNameByToken(HttpServletRequest request) throws JeecgBootException {
+		String accessToken = request.getHeader("X-Access-Token");
+		String username = getUsername(accessToken);
+		if (oConvertUtils.isEmpty(username)) {
+			throw new JeecgBootException("未获取到用户");
+		}
+		return username;
+	}
+	
+	/**
+	  *  从session中获取变量
+	 * @param key
+	 * @return
+	 */
+	public static String getSessionData(String key) {
+		//${myVar}%
+		//得到${} 后面的值
+		String moshi = "";
+		if(key.indexOf("}")!=-1){
+			 moshi = key.substring(key.indexOf("}")+1);
+		}
+		String returnValue = null;
+		if (key.contains("#{")) {
+			key = key.substring(2,key.indexOf("}"));
+		}
+		if (oConvertUtils.isNotEmpty(key)) {
+			HttpSession session = SpringContextUtils.getHttpServletRequest().getSession();
+			returnValue = (String) session.getAttribute(key);
+		}
+		//结果加上${} 后面的值
+		if(returnValue!=null){returnValue = returnValue + moshi;}
+		return returnValue;
+	}
+	
+	/**
+	  * 从当前用户中获取变量
+	 * @param key
+	 * @param user
+	 * @return
+	 */
+	//TODO 急待改造 sckjkdsjsfjdk
+	public static String getUserSystemData(String key,SysUserCacheInfo user) {
+		if(user==null) {
+			user = JeecgDataAutorUtils.loadUserInfo();
+		}
+		//#{sys_user_code}%
+		
+		// 获取登录用户信息
+		LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
+		
+		String moshi = "";
+		if(key.indexOf("}")!=-1){
+			 moshi = key.substring(key.indexOf("}")+1);
+		}
+		String returnValue = null;
+		//针对特殊标示处理#{sysOrgCode},判断替换
+		if (key.contains("#{")) {
+			key = key.substring(2,key.indexOf("}"));
+		} else {
+			key = key;
+		}
+		//替换为系统登录用户帐号
+		if (key.equals(DataBaseConstant.SYS_USER_CODE)|| key.toLowerCase().equals(DataBaseConstant.SYS_USER_CODE_TABLE)) {
+			if(user==null) {
+				returnValue = sysUser.getUsername();
+			}else {
+				returnValue = user.getSysUserCode();
+			}
+		}
+		//替换为系统登录用户真实名字
+		else if (key.equals(DataBaseConstant.SYS_USER_NAME)|| key.toLowerCase().equals(DataBaseConstant.SYS_USER_NAME_TABLE)) {
+			if(user==null) {
+				returnValue = sysUser.getRealname();
+			}else {
+				returnValue = user.getSysUserName();
+			}
+		}
+		
+		//替换为系统用户登录所使用的机构编码
+		else if (key.equals(DataBaseConstant.SYS_ORG_CODE)|| key.toLowerCase().equals(DataBaseConstant.SYS_ORG_CODE_TABLE)) {
+			if(user==null) {
+				returnValue = sysUser.getOrgCode();
+			}else {
+				returnValue = user.getSysOrgCode();
+			}
+		}
+		//替换为系统用户所拥有的所有机构编码
+		else if (key.equals(DataBaseConstant.SYS_MULTI_ORG_CODE)|| key.toLowerCase().equals(DataBaseConstant.SYS_MULTI_ORG_CODE_TABLE)) {
+			if(user==null){
+				//TODO 暂时使用用户登录部门,存在逻辑缺陷,不是用户所拥有的部门
+				returnValue = sysUser.getOrgCode();
+			}else{
+				if(user.isOneDepart()) {
+					returnValue = user.getSysMultiOrgCode().get(0);
+				}else {
+					returnValue = Joiner.on(",").join(user.getSysMultiOrgCode());
+				}
+			}
+		}
+		//替换为当前系统时间(年月日)
+		else if (key.equals(DataBaseConstant.SYS_DATE)|| key.toLowerCase().equals(DataBaseConstant.SYS_DATE_TABLE)) {
+			returnValue = DateUtils.formatDate();
+		}
+		//替换为当前系统时间(年月日时分秒)
+		else if (key.equals(DataBaseConstant.SYS_TIME)|| key.toLowerCase().equals(DataBaseConstant.SYS_TIME_TABLE)) {
+			returnValue = DateUtils.now();
+		}
+		//流程状态默认值(默认未发起)
+		else if (key.equals(DataBaseConstant.BPM_STATUS)|| key.toLowerCase().equals(DataBaseConstant.BPM_STATUS_TABLE)) {
+			returnValue = "1";
+		}
+		//update-begin-author:taoyan date:20210330 for:多租户ID作为系统变量
+		else if (key.equals(DataBaseConstant.TENANT_ID) || key.toLowerCase().equals(DataBaseConstant.TENANT_ID_TABLE)){
+			returnValue = sysUser.getRelTenantIds();
+			if(oConvertUtils.isEmpty(returnValue) || (returnValue!=null && returnValue.indexOf(",")>0)){
+				returnValue = SpringContextUtils.getHttpServletRequest().getHeader(CommonConstant.TENANT_ID);
+			}
+		}
+		//update-end-author:taoyan date:20210330 for:多租户ID作为系统变量
+		if(returnValue!=null){returnValue = returnValue + moshi;}
+		return returnValue;
+	}
+	
+//	public static void main(String[] args) {
+//		 String token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1NjUzMzY1MTMsInVzZXJuYW1lIjoiYWRtaW4ifQ.xjhud_tWCNYBOg_aRlMgOdlZoWFFKB_givNElHNw3X0";
+//		 System.out.println(JwtUtil.getUsername(token));
+//	}
+}

+ 36 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/system/vo/ComboModel.java

@@ -0,0 +1,36 @@
+package org.jeecg.common.system.vo;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class ComboModel implements Serializable {
+    private String id;
+    private String title;
+    /**文档管理 表单table默认选中*/
+    private boolean checked;
+    /**文档管理 表单table 用户账号*/
+    private String username;
+    /**文档管理 表单table 用户邮箱*/
+    private String email;
+    /**文档管理 表单table 角色编码*/
+    private String roleCode;
+
+    public ComboModel(){
+
+    };
+
+    public ComboModel(String id,String title,boolean checked,String username){
+        this.id = id;
+        this.title = title;
+        this.checked = false;
+        this.username = username;
+    };
+}

+ 43 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/system/vo/DictModel.java

@@ -0,0 +1,43 @@
+package org.jeecg.common.system.vo;
+
+import java.io.Serializable;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class DictModel implements Serializable{
+	private static final long serialVersionUID = 1L;
+
+	public DictModel() {
+	}
+	
+	public DictModel(String value, String text) {
+		this.value = value;
+		this.text = text;
+	}
+	
+	/**
+	 * 字典value
+	 */
+	private String value;
+	/**
+	 * 字典文本
+	 */
+	private String text;
+
+	/**
+	 * 特殊用途: JgEditableTable
+	 * @return
+	 */
+	public String getTitle() {
+		return this.text;
+	}
+
+}

+ 34 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/system/vo/DictQuery.java

@@ -0,0 +1,34 @@
+package org.jeecg.common.system.vo;
+
+import lombok.Data;
+
+/**
+ * 字典查询参数实体
+ */
+@Data
+public class DictQuery {
+    /**
+     * 表名
+     */
+    private String table;
+    /**
+     * 存储列
+     */
+    private String code;
+
+    /**
+     * 显示列
+     */
+    private String text;
+
+    /**
+     * 关键字查询
+     */
+    private String keyword;
+
+    /**
+     * 存储列的值 用于回显查询
+     */
+    private String codeValue;
+
+}

+ 52 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/system/vo/DynamicDataSourceModel.java

@@ -0,0 +1,52 @@
+package org.jeecg.common.system.vo;
+
+import lombok.Data;
+import org.springframework.beans.BeanUtils;
+
+@Data
+public class DynamicDataSourceModel {
+
+    public DynamicDataSourceModel() {
+
+    }
+
+    public DynamicDataSourceModel(Object dbSource) {
+        if (dbSource != null) {
+            BeanUtils.copyProperties(dbSource, this);
+        }
+    }
+
+    /**
+     * id
+     */
+    private java.lang.String id;
+    /**
+     * 数据源编码
+     */
+    private java.lang.String code;
+    /**
+     * 数据库类型
+     */
+    private java.lang.String dbType;
+    /**
+     * 驱动类
+     */
+    private java.lang.String dbDriver;
+    /**
+     * 数据源地址
+     */
+    private java.lang.String dbUrl;
+    /**
+     * 数据库名称
+     */
+    private java.lang.String dbName;
+    /**
+     * 用户名
+     */
+    private java.lang.String dbUsername;
+    /**
+     * 密码
+     */
+    private java.lang.String dbPassword;
+
+}

+ 127 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/system/vo/LoginUser.java

@@ -0,0 +1,127 @@
+package org.jeecg.common.system.vo;
+
+import java.util.Date;
+
+import org.springframework.format.annotation.DateTimeFormat;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+/**
+ * <p>
+ * 在线用户信息
+ * </p>
+ *
+ * @Author scott
+ * @since 2018-12-20
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+public class LoginUser {
+
+	public String getId() {
+		return "e9ca23d68d884d4ebb19d07889727dae";
+	}
+
+	public void setId(String id) {
+		this.id = id;
+	}
+
+	/**
+	 * 登录人id
+	 */
+	private String id;
+
+	/**
+	 * 登录人账号
+	 */
+	private String username;
+
+	/**
+	 * 登录人名字
+	 */
+	private String realname;
+
+	/**
+	 * 登录人密码
+	 */
+	private String password;
+
+     /**
+      * 当前登录部门code
+      */
+    private String orgCode;
+	/**
+	 * 头像
+	 */
+	private String avatar;
+
+	/**
+	 * 生日
+	 */
+	@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd")
+	@DateTimeFormat(pattern = "yyyy-MM-dd")
+	private Date birthday;
+
+	/**
+	 * 性别(1:男 2:女)
+	 */
+	private Integer sex;
+
+	/**
+	 * 电子邮件
+	 */
+	private String email;
+
+	/**
+	 * 电话
+	 */
+	private String phone;
+
+	/**
+	 * 状态(1:正常 2:冻结 )
+	 */
+	private Integer status;
+	
+	private Integer delFlag;
+	/**
+     * 同步工作流引擎1同步0不同步
+     */
+    private Integer activitiSync;
+
+	/**
+	 * 创建时间
+	 */
+	private Date createTime;
+
+	/**
+	 *  身份(1 普通员工 2 上级)
+	 */
+	private Integer userIdentity;
+
+	/**
+	 * 管理部门ids
+	 */
+	private String departIds;
+
+	/**
+	 * 职务,关联职务表
+	 */
+	private String post;
+
+	/**
+	 * 座机号
+	 */
+	private String telephone;
+
+	/**多租户id配置,编辑用户的时候设置*/
+	private String relTenantIds;
+
+	/**设备id uniapp推送用*/
+	private String clientId;
+
+}

+ 52 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/system/vo/SysCategoryModel.java

@@ -0,0 +1,52 @@
+package org.jeecg.common.system.vo;
+
+import org.jeecgframework.poi.excel.annotation.Excel;
+
+/**
+ * @Author qinfeng
+ * @Date 2020/2/19 12:01
+ * @Description:
+ * @Version 1.0
+ */
+public class SysCategoryModel {
+    /**主键*/
+    private java.lang.String id;
+    /**父级节点*/
+    private java.lang.String pid;
+    /**类型名称*/
+    private java.lang.String name;
+    /**类型编码*/
+    private java.lang.String code;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getPid() {
+        return pid;
+    }
+
+    public void setPid(String pid) {
+        this.pid = pid;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public void setCode(String code) {
+        this.code = code;
+    }
+}

+ 147 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/system/vo/SysDepartModel.java

@@ -0,0 +1,147 @@
+package org.jeecg.common.system.vo;
+
+/**
+ * lvdandan 部门机构model
+ */
+public class SysDepartModel {
+    /**ID*/
+    private String id;
+    /**父机构ID*/
+    private String parentId;
+    /**机构/部门名称*/
+    private String departName;
+    /**英文名*/
+    private String departNameEn;
+    /**缩写*/
+    private String departNameAbbr;
+    /**排序*/
+    private Integer departOrder;
+    /**描述*/
+    private String description;
+    /**机构类别 1组织机构,2岗位*/
+    private String orgCategory;
+    /**机构类型*/
+    private String orgType;
+    /**机构编码*/
+    private String orgCode;
+    /**手机号*/
+    private String mobile;
+    /**传真*/
+    private String fax;
+    /**地址*/
+    private String address;
+    /**备注*/
+    private String memo;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getParentId() {
+        return parentId;
+    }
+
+    public void setParentId(String parentId) {
+        this.parentId = parentId;
+    }
+
+    public String getDepartName() {
+        return departName;
+    }
+
+    public void setDepartName(String departName) {
+        this.departName = departName;
+    }
+
+    public String getDepartNameEn() {
+        return departNameEn;
+    }
+
+    public void setDepartNameEn(String departNameEn) {
+        this.departNameEn = departNameEn;
+    }
+
+    public String getDepartNameAbbr() {
+        return departNameAbbr;
+    }
+
+    public void setDepartNameAbbr(String departNameAbbr) {
+        this.departNameAbbr = departNameAbbr;
+    }
+
+    public Integer getDepartOrder() {
+        return departOrder;
+    }
+
+    public void setDepartOrder(Integer departOrder) {
+        this.departOrder = departOrder;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public String getOrgCategory() {
+        return orgCategory;
+    }
+
+    public void setOrgCategory(String orgCategory) {
+        this.orgCategory = orgCategory;
+    }
+
+    public String getOrgType() {
+        return orgType;
+    }
+
+    public void setOrgType(String orgType) {
+        this.orgType = orgType;
+    }
+
+    public String getOrgCode() {
+        return orgCode;
+    }
+
+    public void setOrgCode(String orgCode) {
+        this.orgCode = orgCode;
+    }
+
+    public String getMobile() {
+        return mobile;
+    }
+
+    public void setMobile(String mobile) {
+        this.mobile = mobile;
+    }
+
+    public String getFax() {
+        return fax;
+    }
+
+    public void setFax(String fax) {
+        this.fax = fax;
+    }
+
+    public String getAddress() {
+        return address;
+    }
+
+    public void setAddress(String address) {
+        this.address = address;
+    }
+
+    public String getMemo() {
+        return memo;
+    }
+
+    public void setMemo(String memo) {
+        this.memo = memo;
+    }
+}

+ 151 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/system/vo/SysPermissionDataRuleModel.java

@@ -0,0 +1,151 @@
+package org.jeecg.common.system.vo;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * <p>
+ * 菜单权限规则表
+ * </p>
+ *
+ * @Author huangzhilin
+ * @since 2019-03-29
+ */
+public class SysPermissionDataRuleModel {
+
+    /**
+     * id
+     */
+    private String id;
+
+    /**
+     * 对应的菜单id
+     */
+    private String permissionId;
+
+    /**
+     * 规则名称
+     */
+    private String ruleName;
+
+    /**
+     * 字段
+     */
+    private String ruleColumn;
+
+    /**
+     * 条件
+     */
+    private String ruleConditions;
+
+    /**
+     * 规则值
+     */
+    private String ruleValue;
+
+    /**
+     * 创建时间
+     */
+    private Date createTime;
+
+    /**
+     * 创建人
+     */
+    private String createBy;
+
+    /**
+     * 修改时间
+     */
+    private Date updateTime;
+
+    /**
+     * 修改人
+     */
+    private String updateBy;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getPermissionId() {
+        return permissionId;
+    }
+
+    public void setPermissionId(String permissionId) {
+        this.permissionId = permissionId;
+    }
+
+    public String getRuleName() {
+        return ruleName;
+    }
+
+    public void setRuleName(String ruleName) {
+        this.ruleName = ruleName;
+    }
+
+    public String getRuleColumn() {
+        return ruleColumn;
+    }
+
+    public void setRuleColumn(String ruleColumn) {
+        this.ruleColumn = ruleColumn;
+    }
+
+    public String getRuleConditions() {
+        return ruleConditions;
+    }
+
+    public void setRuleConditions(String ruleConditions) {
+        this.ruleConditions = ruleConditions;
+    }
+
+    public String getRuleValue() {
+        return ruleValue;
+    }
+
+    public void setRuleValue(String ruleValue) {
+        this.ruleValue = ruleValue;
+    }
+
+    public Date getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(Date createTime) {
+        this.createTime = createTime;
+    }
+
+    public String getCreateBy() {
+        return createBy;
+    }
+
+    public void setCreateBy(String createBy) {
+        this.createBy = createBy;
+    }
+
+    public Date getUpdateTime() {
+        return updateTime;
+    }
+
+    public void setUpdateTime(Date updateTime) {
+        this.updateTime = updateTime;
+    }
+
+    public String getUpdateBy() {
+        return updateBy;
+    }
+
+    public void setUpdateBy(String updateBy) {
+        this.updateBy = updateBy;
+    }
+}

+ 67 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/system/vo/SysUserCacheInfo.java

@@ -0,0 +1,67 @@
+package org.jeecg.common.system.vo;
+
+import java.util.List;
+
+import org.jeecg.common.util.DateUtils;
+
+public class SysUserCacheInfo {
+	
+	private String sysUserCode;
+	
+	private String sysUserName;
+	
+	private String sysOrgCode;
+	
+	private List<String> sysMultiOrgCode;
+	
+	private boolean oneDepart;
+	
+	public boolean isOneDepart() {
+		return oneDepart;
+	}
+
+	public void setOneDepart(boolean oneDepart) {
+		this.oneDepart = oneDepart;
+	}
+
+	public String getSysDate() {
+		return DateUtils.formatDate();
+	}
+
+	public String getSysTime() {
+		return DateUtils.now();
+	}
+
+	public String getSysUserCode() {
+		return sysUserCode;
+	}
+
+	public void setSysUserCode(String sysUserCode) {
+		this.sysUserCode = sysUserCode;
+	}
+
+	public String getSysUserName() {
+		return sysUserName;
+	}
+
+	public void setSysUserName(String sysUserName) {
+		this.sysUserName = sysUserName;
+	}
+
+	public String getSysOrgCode() {
+		return sysOrgCode;
+	}
+
+	public void setSysOrgCode(String sysOrgCode) {
+		this.sysOrgCode = sysOrgCode;
+	}
+
+	public List<String> getSysMultiOrgCode() {
+		return sysMultiOrgCode;
+	}
+
+	public void setSysMultiOrgCode(List<String> sysMultiOrgCode) {
+		this.sysMultiOrgCode = sysMultiOrgCode;
+	}
+
+}

+ 10 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/BrowserType.java

@@ -0,0 +1,10 @@
+package org.jeecg.common.util;
+
+/**
+ * 
+ * @Author  张代浩
+ *
+ */
+public enum BrowserType {
+	IE11,IE10,IE9,IE8,IE7,IE6,Firefox,Safari,Chrome,Opera,Camino,Gecko
+}

+ 206 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/BrowserUtils.java

@@ -0,0 +1,206 @@
+package org.jeecg.common.util;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * 
+ * @Author 张代浩
+ * 
+ */
+public class BrowserUtils {
+	
+	// 判断是否是IE
+	public static boolean isIE(HttpServletRequest request) {
+		return (request.getHeader("USER-AGENT").toLowerCase().indexOf("msie") > 0 || request
+				.getHeader("USER-AGENT").toLowerCase().indexOf("rv:11.0") > 0) ? true
+				: false;
+	}
+
+	/**
+	 * 获取IE版本
+	 * 
+	 * @param request
+	 * @return
+	 */
+	public static Double getIEversion(HttpServletRequest request) {
+		Double version = 0.0;
+		if (getBrowserType(request, IE11)) {
+			version = 11.0;
+		} else if (getBrowserType(request, IE10)) {
+			version = 10.0;
+		} else if (getBrowserType(request, IE9)) {
+			version = 9.0;
+		} else if (getBrowserType(request, IE8)) {
+			version = 8.0;
+		} else if (getBrowserType(request, IE7)) {
+			version = 7.0;
+		} else if (getBrowserType(request, IE6)) {
+			version = 6.0;
+		}
+		return version;
+	}
+
+	/**
+	 * 获取浏览器类型
+	 * 
+	 * @param request
+	 * @return
+	 */
+	public static BrowserType getBrowserType(HttpServletRequest request) {
+		BrowserType browserType = null;
+		if (getBrowserType(request, IE11)) {
+			browserType = BrowserType.IE11;
+		}
+		if (getBrowserType(request, IE10)) {
+			browserType = BrowserType.IE10;
+		}
+		if (getBrowserType(request, IE9)) {
+			browserType = BrowserType.IE9;
+		}
+		if (getBrowserType(request, IE8)) {
+			browserType = BrowserType.IE8;
+		}
+		if (getBrowserType(request, IE7)) {
+			browserType = BrowserType.IE7;
+		}
+		if (getBrowserType(request, IE6)) {
+			browserType = BrowserType.IE6;
+		}
+		if (getBrowserType(request, FIREFOX)) {
+			browserType = BrowserType.Firefox;
+		}
+		if (getBrowserType(request, SAFARI)) {
+			browserType = BrowserType.Safari;
+		}
+		if (getBrowserType(request, CHROME)) {
+			browserType = BrowserType.Chrome;
+		}
+		if (getBrowserType(request, OPERA)) {
+			browserType = BrowserType.Opera;
+		}
+		if (getBrowserType(request, "Camino")) {
+			browserType = BrowserType.Camino;
+		}
+		return browserType;
+	}
+
+	private static boolean getBrowserType(HttpServletRequest request,
+			String brosertype) {
+		return request.getHeader("USER-AGENT").toLowerCase()
+				.indexOf(brosertype) > 0 ? true : false;
+	}
+
+	private final static String IE11 = "rv:11.0";
+	private final static String IE10 = "MSIE 10.0";
+	private final static String IE9 = "MSIE 9.0";
+	private final static String IE8 = "MSIE 8.0";
+	private final static String IE7 = "MSIE 7.0";
+	private final static String IE6 = "MSIE 6.0";
+	private final static String MAXTHON = "Maxthon";
+	private final static String QQ = "QQBrowser";
+	private final static String GREEN = "GreenBrowser";
+	private final static String SE360 = "360SE";
+	private final static String FIREFOX = "Firefox";
+	private final static String OPERA = "Opera";
+	private final static String CHROME = "Chrome";
+	private final static String SAFARI = "Safari";
+	private final static String OTHER = "其它";
+
+	public static String checkBrowse(HttpServletRequest request) {
+		String userAgent = request.getHeader("USER-AGENT");
+		if (regex(OPERA, userAgent)) {
+			return OPERA;
+		}
+		if (regex(CHROME, userAgent)) {
+			return CHROME;
+		}
+		if (regex(FIREFOX, userAgent)) {
+			return FIREFOX;
+		}
+		if (regex(SAFARI, userAgent)) {
+			return SAFARI;
+		}
+		if (regex(SE360, userAgent)) {
+			return SE360;
+		}
+		if (regex(GREEN, userAgent)) {
+			return GREEN;
+		}
+		if (regex(QQ, userAgent)) {
+			return QQ;
+		}
+		if (regex(MAXTHON, userAgent)) {
+			return MAXTHON;
+		}
+		if (regex(IE11, userAgent)) {
+			return IE11;
+		}
+		if (regex(IE10, userAgent)) {
+			return IE10;
+		}
+		if (regex(IE9, userAgent)) {
+			return IE9;
+		}
+		if (regex(IE8, userAgent)) {
+			return IE8;
+		}
+		if (regex(IE7, userAgent)) {
+			return IE7;
+		}
+		if (regex(IE6, userAgent)) {
+			return IE6;
+		}
+		return OTHER;
+	}
+
+	public static boolean regex(String regex, String str) {
+		Pattern p = Pattern.compile(regex, Pattern.MULTILINE);
+		Matcher m = p.matcher(str);
+		return m.find();
+	}
+
+	
+	private static Map<String, String> langMap = new HashMap<String, String>();
+	private final static String ZH = "zh";
+	private final static String ZH_CN = "zh-cn";
+	
+	private final static String EN = "en";
+	private final static String EN_US = "en";
+	
+	
+	static 
+	{
+		langMap.put(ZH, ZH_CN);
+		langMap.put(EN, EN_US);
+	}
+	
+	public static String getBrowserLanguage(HttpServletRequest request) {
+		
+		String browserLang = request.getLocale().getLanguage();
+		String browserLangCode = (String)langMap.get(browserLang);
+		
+		if(browserLangCode == null)
+		{
+			browserLangCode = EN_US;
+		}
+		return browserLangCode;
+	}
+
+    /** 判断请求是否来自电脑端 */
+    public static boolean isDesktop(HttpServletRequest request) {
+        return !isMobile(request);
+    }
+
+    /** 判断请求是否来自移动端 */
+    public static boolean isMobile(HttpServletRequest request) {
+        String ua = request.getHeader("User-Agent").toLowerCase();
+        Pattern pattern = Pattern.compile("(phone|pad|pod|iphone|ipod|ios|ipad|android|mobile|blackberry|iemobile|mqqbrowser|juc|fennec|wosbrowser|browserng|webos|symbian|windows phone)");
+        return pattern.matcher(ua).find();
+    }
+
+}

+ 215 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/CommonUtils.java

@@ -0,0 +1,215 @@
+package org.jeecg.common.util;
+
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.extra.pinyin.PinyinUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.jeecg.common.constant.CommonConstant;
+import org.jeecg.common.constant.DataBaseConstant;
+import org.jeecg.common.exception.JeecgBootException;
+import org.jeecg.common.util.oss.OssBootUtil;
+import org.jeecgframework.poi.util.PoiPublicUtil;
+import org.springframework.util.FileCopyUtils;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.sql.DataSource;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.SQLException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+@Slf4j
+public class CommonUtils {
+
+   //中文正则
+    private static Pattern ZHONGWEN_PATTERN = Pattern.compile("[\u4e00-\u9fa5]");
+
+    public static String uploadOnlineImage(byte[] data,String basePath,String bizPath,String uploadType){
+        String dbPath = null;
+        String fileName = "image" + Math.round(Math.random() * 100000000000L);
+        fileName += "." + PoiPublicUtil.getFileExtendName(data);
+        try {
+            if(CommonConstant.UPLOAD_TYPE_LOCAL.equals(uploadType)){
+                File file = new File(basePath + File.separator + bizPath + File.separator );
+                if (!file.exists()) {
+                    file.mkdirs();// 创建文件根目录
+                }
+                String savePath = file.getPath() + File.separator + fileName;
+                File savefile = new File(savePath);
+                FileCopyUtils.copy(data, savefile);
+                dbPath = bizPath + File.separator + fileName;
+            }else {
+                InputStream in = new ByteArrayInputStream(data);
+                String relativePath = bizPath+"/"+fileName;
+                if(CommonConstant.UPLOAD_TYPE_MINIO.equals(uploadType)){
+                    dbPath = MinioUtil.upload(in,relativePath);
+                }else if(CommonConstant.UPLOAD_TYPE_OSS.equals(uploadType)){
+                    dbPath = OssBootUtil.upload(in,relativePath);
+                }
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return dbPath;
+    }
+
+    /**
+     * 判断文件名是否带盘符,重新处理
+     * @param fileName
+     * @return
+     */
+    public static String getFileName(String fileName){
+        //判断是否带有盘符信息
+        // Check for Unix-style path
+        int unixSep = fileName.lastIndexOf('/');
+        // Check for Windows-style path
+        int winSep = fileName.lastIndexOf('\\');
+        // Cut off at latest possible point
+        int pos = (winSep > unixSep ? winSep : unixSep);
+        if (pos != -1)  {
+            // Any sort of path separator found...
+            fileName = fileName.substring(pos + 1);
+        }
+        //替换上传文件名字的特殊字符
+        fileName = fileName.replace("=","").replace(",","").replace("&","")
+                .replace("#", "").replace("“", "").replace("”", "");
+        //替换上传文件名字中的空格
+        fileName=fileName.replaceAll("\\s","");
+        return fileName;
+    }
+
+    // java 判断字符串里是否包含中文字符
+    public static boolean ifContainChinese(String str) {
+        if(str.getBytes().length == str.length()){
+            return false;
+        }else{
+            Matcher m = ZHONGWEN_PATTERN.matcher(str);
+            if (m.find()) {
+                return true;
+            }
+            return false;
+        }
+    }
+
+    /**
+     * 统一全局上传
+     * @Return: java.lang.String
+     */
+    public static String upload(MultipartFile file, String bizPath, String uploadType) {
+        String url = "";
+        if(CommonConstant.UPLOAD_TYPE_MINIO.equals(uploadType)){
+            url = MinioUtil.upload(file,bizPath);
+        }else{
+            url = OssBootUtil.upload(file,bizPath);
+        }
+        return url;
+    }
+    /**
+     * 本地文件上传
+     * @param mf 文件
+     * @param bizPath  自定义路径
+     * @return
+     */
+    public static String uploadLocal(MultipartFile mf,String bizPath,String uploadpath){
+        try {
+            String fileName = null;
+            File file = new File(uploadpath + File.separator + bizPath + File.separator );
+            if (!file.exists()) {
+                file.mkdirs();// 创建文件根目录
+            }
+            String orgName = mf.getOriginalFilename();// 获取文件名
+            orgName = CommonUtils.getFileName(orgName);
+            if(orgName.indexOf(".")!=-1){
+                fileName = orgName.substring(0, orgName.lastIndexOf(".")) + "_" + System.currentTimeMillis() + orgName.substring(orgName.lastIndexOf("."));
+            }else{
+                fileName = orgName+ "_" + System.currentTimeMillis();
+            }
+            String savePath = file.getPath() + File.separator + fileName;
+            File savefile = new File(savePath);
+            FileCopyUtils.copy(mf.getBytes(), savefile);
+            String dbpath = null;
+            if(oConvertUtils.isNotEmpty(bizPath)){
+                dbpath = bizPath + File.separator + fileName;
+            }else{
+                dbpath = fileName;
+            }
+            if (dbpath.contains("\\")) {
+                dbpath = dbpath.replace("\\", "/");
+            }
+            return dbpath;
+        } catch (IOException e) {
+            log.error(e.getMessage(), e);
+        }
+        return "";
+    }
+
+    /**
+     * 统一全局上传 带桶
+     * @Return: java.lang.String
+     */
+    public static String upload(MultipartFile file, String bizPath, String uploadType, String customBucket) {
+        String url = "";
+        if(CommonConstant.UPLOAD_TYPE_MINIO.equals(uploadType)){
+            url = MinioUtil.upload(file,bizPath,customBucket);
+        }else{
+            url = OssBootUtil.upload(file,bizPath,customBucket);
+        }
+        return url;
+    }
+
+    /** 当前系统数据库类型 */
+    private static String DB_TYPE = "";
+    public static String getDatabaseType() {
+        if(oConvertUtils.isNotEmpty(DB_TYPE)){
+            return DB_TYPE;
+        }
+        DataSource dataSource = SpringContextUtils.getApplicationContext().getBean(DataSource.class);
+        try {
+            return getDatabaseTypeByDataSource(dataSource);
+        } catch (SQLException e) {
+            //e.printStackTrace();
+            log.warn(e.getMessage(),e);
+            return "";
+        }
+    }
+
+    /**
+     * 获取数据库类型
+     * @param dataSource
+     * @return
+     * @throws SQLException
+     */
+    private static String getDatabaseTypeByDataSource(DataSource dataSource) throws SQLException{
+        if("".equals(DB_TYPE)) {
+            Connection connection = dataSource.getConnection();
+            try {
+                DatabaseMetaData md = connection.getMetaData();
+                String dbType = md.getDatabaseProductName().toLowerCase();
+                if(dbType.indexOf("mysql")>=0) {
+                    DB_TYPE = DataBaseConstant.DB_TYPE_MYSQL;
+                }else if(dbType.indexOf("oracle")>=0 ||dbType.indexOf("dm")>=0) {
+                    DB_TYPE = DataBaseConstant.DB_TYPE_ORACLE;
+                }else if(dbType.indexOf("sqlserver")>=0||dbType.indexOf("sql server")>=0) {
+                    DB_TYPE = DataBaseConstant.DB_TYPE_SQLSERVER;
+                }else if(dbType.indexOf("postgresql")>=0) {
+                    DB_TYPE = DataBaseConstant.DB_TYPE_POSTGRESQL;
+                }else if(dbType.indexOf("mariadb")>=0) {
+                    DB_TYPE = DataBaseConstant.DB_TYPE_MARIADB;
+                }else {
+                    log.error("数据库类型:[" + dbType + "]不识别!");
+                    //throw new JeecgBootException("数据库类型:["+dbType+"]不识别!");
+                }
+            } catch (Exception e) {
+                log.error(e.getMessage(), e);
+            }finally {
+                connection.close();
+            }
+        }
+        return DB_TYPE;
+
+    }
+}

+ 654 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/DateUtils.java

@@ -0,0 +1,654 @@
+package org.jeecg.common.util;
+
+import java.beans.PropertyEditorSupport;
+import java.sql.Timestamp;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+
+import org.springframework.util.StringUtils;
+
+/**
+ * 类描述:时间操作定义类
+ *
+ * @Author: 张代浩
+ * @Date:2012-12-8 12:15:03
+ * @Version 1.0
+ */
+public class DateUtils extends PropertyEditorSupport {
+
+    public static ThreadLocal<SimpleDateFormat> date_sdf = new ThreadLocal<SimpleDateFormat>() {
+        @Override
+        protected SimpleDateFormat initialValue() {
+            return new SimpleDateFormat("yyyy-MM-dd");
+        }
+    };
+    public static ThreadLocal<SimpleDateFormat> yyyyMMdd = new ThreadLocal<SimpleDateFormat>() {
+        @Override
+        protected SimpleDateFormat initialValue() {
+            return new SimpleDateFormat("yyyyMMdd");
+        }
+    };
+    public static ThreadLocal<SimpleDateFormat> date_sdf_wz = new ThreadLocal<SimpleDateFormat>() {
+        @Override
+        protected SimpleDateFormat initialValue() {
+            return new SimpleDateFormat("yyyy年MM月dd日");
+        }
+    };
+    public static ThreadLocal<SimpleDateFormat> time_sdf = new ThreadLocal<SimpleDateFormat>() {
+        @Override
+        protected SimpleDateFormat initialValue() {
+            return new SimpleDateFormat("yyyy-MM-dd HH:mm");
+        }
+    };
+    public static ThreadLocal<SimpleDateFormat> yyyymmddhhmmss = new ThreadLocal<SimpleDateFormat>() {
+        @Override
+        protected SimpleDateFormat initialValue() {
+            return new SimpleDateFormat("yyyyMMddHHmmss");
+        }
+    };
+    public static ThreadLocal<SimpleDateFormat> short_time_sdf = new ThreadLocal<SimpleDateFormat>() {
+        @Override
+        protected SimpleDateFormat initialValue() {
+            return new SimpleDateFormat("HH:mm");
+        }
+    };
+    public static ThreadLocal<SimpleDateFormat> datetimeFormat = new ThreadLocal<SimpleDateFormat>() {
+        @Override
+        protected SimpleDateFormat initialValue() {
+            return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        }
+    };
+
+    // 以毫秒表示的时间
+    private static final long DAY_IN_MILLIS = 24 * 3600 * 1000;
+    private static final long HOUR_IN_MILLIS = 3600 * 1000;
+    private static final long MINUTE_IN_MILLIS = 60 * 1000;
+    private static final long SECOND_IN_MILLIS = 1000;
+
+    // 指定模式的时间格式
+    private static SimpleDateFormat getSDFormat(String pattern) {
+        return new SimpleDateFormat(pattern);
+    }
+
+    /**
+     * 当前日历,这里用中国时间表示
+     *
+     * @return 以当地时区表示的系统当前日历
+     */
+    public static Calendar getCalendar() {
+        return Calendar.getInstance();
+    }
+
+    /**
+     * 指定毫秒数表示的日历
+     *
+     * @param millis 毫秒数
+     * @return 指定毫秒数表示的日历
+     */
+    public static Calendar getCalendar(long millis) {
+        Calendar cal = Calendar.getInstance();
+        // --------------------cal.setTimeInMillis(millis);
+        cal.setTime(new Date(millis));
+        return cal;
+    }
+
+    // ////////////////////////////////////////////////////////////////////////////
+    // getDate
+    // 各种方式获取的Date
+    // ////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * 当前日期
+     *
+     * @return 系统当前时间
+     */
+    public static Date getDate() {
+        return new Date();
+    }
+
+    /**
+     * 指定毫秒数表示的日期
+     *
+     * @param millis 毫秒数
+     * @return 指定毫秒数表示的日期
+     */
+    public static Date getDate(long millis) {
+        return new Date(millis);
+    }
+
+    /**
+     * 时间戳转换为字符串
+     *
+     * @param time
+     * @return
+     */
+    public static String timestamptoStr(Timestamp time) {
+        Date date = null;
+        if (null != time) {
+            date = new Date(time.getTime());
+        }
+        return date2Str(date_sdf.get());
+    }
+
+    /**
+     * 字符串转换时间戳
+     *
+     * @param str
+     * @return
+     */
+    public static Timestamp str2Timestamp(String str) {
+        Date date = str2Date(str, date_sdf.get());
+        return new Timestamp(date.getTime());
+    }
+
+    /**
+     * 字符串转换成日期
+     *
+     * @param str
+     * @param sdf
+     * @return
+     */
+    public static Date str2Date(String str, SimpleDateFormat sdf) {
+        if (null == str || "".equals(str)) {
+            return null;
+        }
+        Date date = null;
+        try {
+            date = sdf.parse(str);
+            return date;
+        } catch (ParseException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    /**
+     * 日期转换为字符串
+     *
+     * @param date_sdf 日期格式
+     * @return 字符串
+     */
+    public static String date2Str(SimpleDateFormat date_sdf) {
+        Date date = getDate();
+        if (null == date) {
+            return null;
+        }
+        return date_sdf.format(date);
+    }
+
+    /**
+     * 格式化时间
+     *
+     * @param date
+     * @param format
+     * @return
+     */
+    public static String dateformat(String date, String format) {
+        SimpleDateFormat sformat = new SimpleDateFormat(format);
+        Date _date = null;
+        try {
+            _date = sformat.parse(date);
+        } catch (ParseException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+        return sformat.format(_date);
+    }
+
+    /**
+     * 日期转换为字符串
+     *
+     * @param date     日期
+     * @param date_sdf 日期格式
+     * @return 字符串
+     */
+    public static String date2Str(Date date, SimpleDateFormat date_sdf) {
+        if (null == date) {
+            return null;
+        }
+        return date_sdf.format(date);
+    }
+
+    /**
+     * 日期转换为字符串
+     *
+     * @param format 日期格式
+     * @return 字符串
+     */
+    public static String getDate(String format) {
+        Date date = new Date();
+        if (null == date) {
+            return null;
+        }
+        SimpleDateFormat sdf = new SimpleDateFormat(format);
+        return sdf.format(date);
+    }
+
+    /**
+     * 指定毫秒数的时间戳
+     *
+     * @param millis 毫秒数
+     * @return 指定毫秒数的时间戳
+     */
+    public static Timestamp getTimestamp(long millis) {
+        return new Timestamp(millis);
+    }
+
+    /**
+     * 以字符形式表示的时间戳
+     *
+     * @param time 毫秒数
+     * @return 以字符形式表示的时间戳
+     */
+    public static Timestamp getTimestamp(String time) {
+        return new Timestamp(Long.parseLong(time));
+    }
+
+    /**
+     * 系统当前的时间戳
+     *
+     * @return 系统当前的时间戳
+     */
+    public static Timestamp getTimestamp() {
+        return new Timestamp(System.currentTimeMillis());
+    }
+
+    /**
+     * 当前时间,格式 yyyy-MM-dd HH:mm:ss
+     *
+     * @return 当前时间的标准形式字符串
+     */
+    public static String now() {
+        return datetimeFormat.get().format(getCalendar().getTime());
+    }
+
+    /**
+     * 指定日期的时间戳
+     *
+     * @param date 指定日期
+     * @return 指定日期的时间戳
+     */
+    public static Timestamp getTimestamp(Date date) {
+        return new Timestamp(date.getTime());
+    }
+
+    /**
+     * 指定日历的时间戳
+     *
+     * @param cal 指定日历
+     * @return 指定日历的时间戳
+     */
+    public static Timestamp getCalendarTimestamp(Calendar cal) {
+        // ---------------------return new Timestamp(cal.getTimeInMillis());
+        return new Timestamp(cal.getTime().getTime());
+    }
+
+    public static Timestamp gettimestamp() {
+        Date dt = new Date();
+        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        String nowTime = df.format(dt);
+        Timestamp buydate = Timestamp.valueOf(nowTime);
+        return buydate;
+    }
+
+    // ////////////////////////////////////////////////////////////////////////////
+    // getMillis
+    // 各种方式获取的Millis
+    // ////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * 系统时间的毫秒数
+     *
+     * @return 系统时间的毫秒数
+     */
+    public static long getMillis() {
+        return System.currentTimeMillis();
+    }
+
+    /**
+     * 指定日历的毫秒数
+     *
+     * @param cal 指定日历
+     * @return 指定日历的毫秒数
+     */
+    public static long getMillis(Calendar cal) {
+        // --------------------return cal.getTimeInMillis();
+        return cal.getTime().getTime();
+    }
+
+    /**
+     * 指定日期的毫秒数
+     *
+     * @param date 指定日期
+     * @return 指定日期的毫秒数
+     */
+    public static long getMillis(Date date) {
+        return date.getTime();
+    }
+
+    /**
+     * 指定时间戳的毫秒数
+     *
+     * @param ts 指定时间戳
+     * @return 指定时间戳的毫秒数
+     */
+    public static long getMillis(Timestamp ts) {
+        return ts.getTime();
+    }
+
+    // ////////////////////////////////////////////////////////////////////////////
+    // formatDate
+    // 将日期按照一定的格式转化为字符串
+    // ////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * 默认方式表示的系统当前日期,具体格式:年-月-日
+     *
+     * @return 默认日期按“年-月-日“格式显示
+     */
+    public static String formatDate() {
+        return date_sdf.get().format(getCalendar().getTime());
+    }
+
+    /**
+     * 默认方式表示的系统当前日期,具体格式:yyyy-MM-dd HH:mm:ss
+     *
+     * @return 默认日期按“yyyy-MM-dd HH:mm:ss“格式显示
+     */
+    public static String formatDateTime() {
+        return datetimeFormat.get().format(getCalendar().getTime());
+    }
+
+    /**
+     * 获取时间字符串
+     */
+    public static String getDataString(SimpleDateFormat formatstr) {
+        return formatstr.format(getCalendar().getTime());
+    }
+
+    /**
+     * 指定日期的默认显示,具体格式:年-月-日
+     *
+     * @param cal 指定的日期
+     * @return 指定日期按“年-月-日“格式显示
+     */
+    public static String formatDate(Calendar cal) {
+        return date_sdf.get().format(cal.getTime());
+    }
+
+    /**
+     * 指定日期的默认显示,具体格式:年-月-日
+     *
+     * @param date 指定的日期
+     * @return 指定日期按“年-月-日“格式显示
+     */
+    public static String formatDate(Date date) {
+        return date_sdf.get().format(date);
+    }
+
+    /**
+     * 指定毫秒数表示日期的默认显示,具体格式:年-月-日
+     *
+     * @param millis 指定的毫秒数
+     * @return 指定毫秒数表示日期按“年-月-日“格式显示
+     */
+    public static String formatDate(long millis) {
+        return date_sdf.get().format(new Date(millis));
+    }
+
+    /**
+     * 默认日期按指定格式显示
+     *
+     * @param pattern 指定的格式
+     * @return 默认日期按指定格式显示
+     */
+    public static String formatDate(String pattern) {
+        return getSDFormat(pattern).format(getCalendar().getTime());
+    }
+
+    /**
+     * 指定日期按指定格式显示
+     *
+     * @param cal     指定的日期
+     * @param pattern 指定的格式
+     * @return 指定日期按指定格式显示
+     */
+    public static String formatDate(Calendar cal, String pattern) {
+        return getSDFormat(pattern).format(cal.getTime());
+    }
+
+    /**
+     * 指定日期按指定格式显示
+     *
+     * @param date    指定的日期
+     * @param pattern 指定的格式
+     * @return 指定日期按指定格式显示
+     */
+    public static String formatDate(Date date, String pattern) {
+        return getSDFormat(pattern).format(date);
+    }
+
+    // ////////////////////////////////////////////////////////////////////////////
+    // formatTime
+    // 将日期按照一定的格式转化为字符串
+    // ////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * 默认方式表示的系统当前日期,具体格式:年-月-日 时:分
+     *
+     * @return 默认日期按“年-月-日 时:分“格式显示
+     */
+    public static String formatTime() {
+        return time_sdf.get().format(getCalendar().getTime());
+    }
+
+    /**
+     * 指定毫秒数表示日期的默认显示,具体格式:年-月-日 时:分
+     *
+     * @param millis 指定的毫秒数
+     * @return 指定毫秒数表示日期按“年-月-日 时:分“格式显示
+     */
+    public static String formatTime(long millis) {
+        return time_sdf.get().format(new Date(millis));
+    }
+
+    /**
+     * 指定日期的默认显示,具体格式:年-月-日 时:分
+     *
+     * @param cal 指定的日期
+     * @return 指定日期按“年-月-日 时:分“格式显示
+     */
+    public static String formatTime(Calendar cal) {
+        return time_sdf.get().format(cal.getTime());
+    }
+
+    /**
+     * 指定日期的默认显示,具体格式:年-月-日 时:分
+     *
+     * @param date 指定的日期
+     * @return 指定日期按“年-月-日 时:分“格式显示
+     */
+    public static String formatTime(Date date) {
+        return time_sdf.get().format(date);
+    }
+
+    // ////////////////////////////////////////////////////////////////////////////
+    // formatShortTime
+    // 将日期按照一定的格式转化为字符串
+    // ////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * 默认方式表示的系统当前日期,具体格式:时:分
+     *
+     * @return 默认日期按“时:分“格式显示
+     */
+    public static String formatShortTime() {
+        return short_time_sdf.get().format(getCalendar().getTime());
+    }
+
+    /**
+     * 指定毫秒数表示日期的默认显示,具体格式:时:分
+     *
+     * @param millis 指定的毫秒数
+     * @return 指定毫秒数表示日期按“时:分“格式显示
+     */
+    public static String formatShortTime(long millis) {
+        return short_time_sdf.get().format(new Date(millis));
+    }
+
+    /**
+     * 指定日期的默认显示,具体格式:时:分
+     *
+     * @param cal 指定的日期
+     * @return 指定日期按“时:分“格式显示
+     */
+    public static String formatShortTime(Calendar cal) {
+        return short_time_sdf.get().format(cal.getTime());
+    }
+
+    /**
+     * 指定日期的默认显示,具体格式:时:分
+     *
+     * @param date 指定的日期
+     * @return 指定日期按“时:分“格式显示
+     */
+    public static String formatShortTime(Date date) {
+        return short_time_sdf.get().format(date);
+    }
+
+    // ////////////////////////////////////////////////////////////////////////////
+    // parseDate
+    // parseCalendar
+    // parseTimestamp
+    // 将字符串按照一定的格式转化为日期或时间
+    // ////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * 根据指定的格式将字符串转换成Date 如输入:2003-11-19 11:20:20将按照这个转成时间
+     *
+     * @param src     将要转换的原始字符窜
+     * @param pattern 转换的匹配格式
+     * @return 如果转换成功则返回转换后的日期
+     * @throws ParseException
+     */
+    public static Date parseDate(String src, String pattern) throws ParseException {
+        return getSDFormat(pattern).parse(src);
+
+    }
+
+    /**
+     * 根据指定的格式将字符串转换成Date 如输入:2003-11-19 11:20:20将按照这个转成时间
+     *
+     * @param src     将要转换的原始字符窜
+     * @param pattern 转换的匹配格式
+     * @return 如果转换成功则返回转换后的日期
+     * @throws ParseException
+     */
+    public static Calendar parseCalendar(String src, String pattern) throws ParseException {
+
+        Date date = parseDate(src, pattern);
+        Calendar cal = Calendar.getInstance();
+        cal.setTime(date);
+        return cal;
+    }
+
+    public static String formatAddDate(String src, String pattern, int amount) throws ParseException {
+        Calendar cal;
+        cal = parseCalendar(src, pattern);
+        cal.add(Calendar.DATE, amount);
+        return formatDate(cal);
+    }
+
+    /**
+     * 根据指定的格式将字符串转换成Date 如输入:2003-11-19 11:20:20将按照这个转成时间
+     *
+     * @param src     将要转换的原始字符窜
+     * @param pattern 转换的匹配格式
+     * @return 如果转换成功则返回转换后的时间戳
+     * @throws ParseException
+     */
+    public static Timestamp parseTimestamp(String src, String pattern) throws ParseException {
+        Date date = parseDate(src, pattern);
+        return new Timestamp(date.getTime());
+    }
+
+    // ////////////////////////////////////////////////////////////////////////////
+    // dateDiff
+    // 计算两个日期之间的差值
+    // ////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * 计算两个时间之间的差值,根据标志的不同而不同
+     *
+     * @param flag   计算标志,表示按照年/月/日/时/分/秒等计算
+     * @param calSrc 减数
+     * @param calDes 被减数
+     * @return 两个日期之间的差值
+     */
+    public static int dateDiff(char flag, Calendar calSrc, Calendar calDes) {
+
+        long millisDiff = getMillis(calSrc) - getMillis(calDes);
+
+        if (flag == 'y') {
+            return (calSrc.get(Calendar.YEAR) - calDes.get(Calendar.YEAR));
+        }
+
+        if (flag == 'd') {
+            return (int) (millisDiff / DAY_IN_MILLIS);
+        }
+
+        if (flag == 'h') {
+            return (int) (millisDiff / HOUR_IN_MILLIS);
+        }
+
+        if (flag == 'm') {
+            return (int) (millisDiff / MINUTE_IN_MILLIS);
+        }
+
+        if (flag == 's') {
+            return (int) (millisDiff / SECOND_IN_MILLIS);
+        }
+
+        return 0;
+    }
+
+    public static Long getCurrentTimestamp() {
+        return Long.valueOf(DateUtils.yyyymmddhhmmss.get().format(new Date()));
+    }
+
+    /**
+     * String类型 转换为Date, 如果参数长度为10 转换格式”yyyy-MM-dd“ 如果参数长度为19 转换格式”yyyy-MM-dd
+     * HH:mm:ss“ * @param text String类型的时间值
+     */
+    @Override
+    public void setAsText(String text) throws IllegalArgumentException {
+        if (StringUtils.hasText(text)) {
+            try {
+                if (text.indexOf(":") == -1 && text.length() == 10) {
+                    setValue(DateUtils.date_sdf.get().parse(text));
+                } else if (text.indexOf(":") > 0 && text.length() == 19) {
+                    setValue(DateUtils.datetimeFormat.get().parse(text));
+                } else {
+                    throw new IllegalArgumentException("Could not parse date, date format is error ");
+                }
+            } catch (ParseException ex) {
+                IllegalArgumentException iae = new IllegalArgumentException("Could not parse date: " + ex.getMessage());
+                iae.initCause(ex);
+                throw iae;
+            }
+        } else {
+            setValue(null);
+        }
+    }
+
+    public static int getYear() {
+        GregorianCalendar calendar = new GregorianCalendar();
+        calendar.setTime(getDate());
+        return calendar.get(Calendar.YEAR);
+    }
+
+}

+ 70 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/DySmsEnum.java

@@ -0,0 +1,70 @@
+package org.jeecg.common.util;
+
+import org.apache.commons.lang3.StringUtils;
+
+public enum DySmsEnum {
+	
+	LOGIN_TEMPLATE_CODE("SMS_175435174","JEECG","code"),
+	FORGET_PASSWORD_TEMPLATE_CODE("SMS_175435174","JEECG","code"),
+	REGISTER_TEMPLATE_CODE("SMS_175430166","JEECG","code"),
+	/**会议通知*/
+	MEET_NOTICE_TEMPLATE_CODE("SMS_201480469","H5活动之家","username,title,minute,time"),
+	/**我的计划通知*/
+	PLAN_NOTICE_TEMPLATE_CODE("SMS_201470515","H5活动之家","username,title,time");
+
+	/**
+	 * 短信模板编码
+	 */
+	private String templateCode;
+	/**
+	 * 签名
+	 */
+	private String signName;
+	/**
+	 * 短信模板必需的数据名称,多个key以逗号分隔,此处配置作为校验
+	 */
+	private String keys;
+	
+	private DySmsEnum(String templateCode,String signName,String keys) {
+		this.templateCode = templateCode;
+		this.signName = signName;
+		this.keys = keys;
+	}
+	
+	public String getTemplateCode() {
+		return templateCode;
+	}
+	
+	public void setTemplateCode(String templateCode) {
+		this.templateCode = templateCode;
+	}
+	
+	public String getSignName() {
+		return signName;
+	}
+	
+	public void setSignName(String signName) {
+		this.signName = signName;
+	}
+	
+	public String getKeys() {
+		return keys;
+	}
+
+	public void setKeys(String keys) {
+		this.keys = keys;
+	}
+
+	public static DySmsEnum toEnum(String templateCode) {
+		if(StringUtils.isEmpty(templateCode)){
+			return null;
+		}
+		for(DySmsEnum item : DySmsEnum.values()) {
+			if(item.getTemplateCode().equals(templateCode)) {
+				return item;
+			}
+		}
+		return null;
+	}
+}
+

+ 122 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/DySmsHelper.java

@@ -0,0 +1,122 @@
+package org.jeecg.common.util;
+
+import org.jeecg.config.StaticConfig;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.alibaba.fastjson.JSONObject;
+import com.aliyuncs.DefaultAcsClient;
+import com.aliyuncs.IAcsClient;
+import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
+import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
+import com.aliyuncs.exceptions.ClientException;
+import com.aliyuncs.profile.DefaultProfile;
+import com.aliyuncs.profile.IClientProfile;
+
+/**
+ * Created on 17/6/7.
+ * 短信API产品的DEMO程序,工程中包含了一个SmsDemo类,直接通过
+ * 执行main函数即可体验短信产品API功能(只需要将AK替换成开通了云通信-短信产品功能的AK即可)
+ * 工程依赖了2个jar包(存放在工程的libs目录下)
+ * 1:aliyun-java-sdk-core.jar
+ * 2:aliyun-java-sdk-dysmsapi.jar
+ *
+ * 备注:Demo工程编码采用UTF-8
+ * 国际短信发送请勿参照此DEMO
+ */
+public class DySmsHelper {
+	
+	private final static Logger logger=LoggerFactory.getLogger(DySmsHelper.class);
+
+    //产品名称:云通信短信API产品,开发者无需替换
+    static final String product = "Dysmsapi";
+    //产品域名,开发者无需替换
+    static final String domain = "dysmsapi.aliyuncs.com";
+
+    // TODO 此处需要替换成开发者自己的AK(在阿里云访问控制台寻找)
+    static  String accessKeyId;
+    static  String accessKeySecret;
+
+    public static void setAccessKeyId(String accessKeyId) {
+        DySmsHelper.accessKeyId = accessKeyId;
+    }
+
+    public static void setAccessKeySecret(String accessKeySecret) {
+        DySmsHelper.accessKeySecret = accessKeySecret;
+    }
+
+    public static String getAccessKeyId() {
+        return accessKeyId;
+    }
+
+    public static String getAccessKeySecret() {
+        return accessKeySecret;
+    }
+    
+    
+    public static boolean sendSms(String phone,JSONObject templateParamJson,DySmsEnum dySmsEnum) throws ClientException {
+    	//可自助调整超时时间
+        System.setProperty("sun.net.client.defaultConnectTimeout", "10000");
+        System.setProperty("sun.net.client.defaultReadTimeout", "10000");
+
+        //update-begin-author:taoyan date:20200811 for:配置类数据获取
+        StaticConfig staticConfig = SpringContextUtils.getBean(StaticConfig.class);
+        setAccessKeyId(staticConfig.getAccessKeyId());
+        setAccessKeySecret(staticConfig.getAccessKeySecret());
+        //update-end-author:taoyan date:20200811 for:配置类数据获取
+        
+        //初始化acsClient,暂不支持region化
+        IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessKeySecret);
+        DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", product, domain);
+        IAcsClient acsClient = new DefaultAcsClient(profile);
+        
+        //验证json参数
+        validateParam(templateParamJson,dySmsEnum);
+        
+        //组装请求对象-具体描述见控制台-文档部分内容
+        SendSmsRequest request = new SendSmsRequest();
+        //必填:待发送手机号
+        request.setPhoneNumbers(phone);
+        //必填:短信签名-可在短信控制台中找到
+        request.setSignName(dySmsEnum.getSignName());
+        //必填:短信模板-可在短信控制台中找到
+        request.setTemplateCode(dySmsEnum.getTemplateCode());
+        //可选:模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为
+        request.setTemplateParam(templateParamJson.toJSONString());
+        
+        //选填-上行短信扩展码(无特殊需求用户请忽略此字段)
+        //request.setSmsUpExtendCode("90997");
+
+        //可选:outId为提供给业务方扩展字段,最终在短信回执消息中将此值带回给调用者
+        //request.setOutId("yourOutId");
+
+        boolean result = false;
+
+        //hint 此处可能会抛出异常,注意catch
+        SendSmsResponse sendSmsResponse = acsClient.getAcsResponse(request);
+        logger.info("短信接口返回的数据----------------");
+        logger.info("{Code:" + sendSmsResponse.getCode()+",Message:" + sendSmsResponse.getMessage()+",RequestId:"+ sendSmsResponse.getRequestId()+",BizId:"+sendSmsResponse.getBizId()+"}");
+        if ("OK".equals(sendSmsResponse.getCode())) {
+            result = true;
+        }
+        return result;
+        
+    }
+    
+    private static void validateParam(JSONObject templateParamJson,DySmsEnum dySmsEnum) {
+    	String keys = dySmsEnum.getKeys();
+    	String [] keyArr = keys.split(",");
+    	for(String item :keyArr) {
+    		if(!templateParamJson.containsKey(item)) {
+    			throw new RuntimeException("模板缺少参数:"+item);
+    		}
+    	}
+    }
+    
+
+//    public static void main(String[] args) throws ClientException, InterruptedException {
+//    	JSONObject obj = new JSONObject();
+//    	obj.put("code", "1234");
+//    	sendSms("13800138000", obj, DySmsEnum.FORGET_PASSWORD_TEMPLATE_CODE);
+//    }
+}

+ 57 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/FillRuleUtil.java

@@ -0,0 +1,57 @@
+package org.jeecg.common.util;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.jeecg.common.handler.IFillRuleHandler;
+
+
+/**
+ * 规则值自动生成工具类
+ *
+ * @author qinfeng
+ * @举例: 自动生成订单号;自动生成当前日期
+ */
+@Slf4j
+public class FillRuleUtil {
+
+    /**
+     * @param ruleCode ruleCode
+     * @return
+     */
+    @SuppressWarnings("unchecked")
+    public static Object executeRule(String ruleCode, JSONObject formData) {
+        if (!StringUtils.isEmpty(ruleCode)) {
+            try {
+                // 获取 Service
+                ServiceImpl impl = (ServiceImpl) SpringContextUtils.getBean("sysFillRuleServiceImpl");
+                // 根据 ruleCode 查询出实体
+                QueryWrapper queryWrapper = new QueryWrapper();
+                queryWrapper.eq("rule_code", ruleCode);
+                JSONObject entity = JSON.parseObject(JSON.toJSONString(impl.getOne(queryWrapper)));
+                if (entity == null) {
+                    log.warn("填值规则:" + ruleCode + " 不存在");
+                    return null;
+                }
+                // 获取必要的参数
+                String ruleClass = entity.getString("ruleClass");
+                JSONObject params = entity.getJSONObject("ruleParams");
+                if (params == null) {
+                    params = new JSONObject();
+                }
+                if (formData == null) {
+                    formData = new JSONObject();
+                }
+                // 通过反射执行配置的类里的方法
+                IFillRuleHandler ruleHandler = (IFillRuleHandler) Class.forName(ruleClass).newInstance();
+                return ruleHandler.execute(params, formData);
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+        return null;
+    }
+}

+ 29 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/HTMLUtils.java

@@ -0,0 +1,29 @@
+package org.jeecg.common.util;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.web.util.HtmlUtils;
+
+/**
+ * HTML 工具类
+ */
+public class HTMLUtils {
+
+    /**
+     * 获取HTML内的文本,不包含标签
+     *
+     * @param html HTML 代码
+     */
+    public static String getInnerText(String html) {
+        if (StringUtils.isNotBlank(html)) {
+            //去掉 html 的标签
+            String content = html.replaceAll("</?[^>]+>", "");
+            // 将多个空格合并成一个空格
+            content = content.replaceAll("(&nbsp;)+", "&nbsp;");
+            // 反向转义字符
+            content = HtmlUtils.htmlUnescape(content);
+            return content.trim();
+        }
+        return "";
+    }
+
+}

+ 58 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/IPUtils.java

@@ -0,0 +1,58 @@
+package org.jeecg.common.util;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * IP地址
+ * 
+ * @Author scott
+ * @email jeecgos@163.com
+ * @Date 2019年01月14日
+ */
+public class IPUtils {
+	private static Logger logger = LoggerFactory.getLogger(IPUtils.class);
+
+	/**
+	 * 获取IP地址
+	 * 
+	 * 使用Nginx等反向代理软件, 则不能通过request.getRemoteAddr()获取IP地址
+	 * 如果使用了多级反向代理的话,X-Forwarded-For的值并不止一个,而是一串IP地址,X-Forwarded-For中第一个非unknown的有效IP字符串,则为真实IP地址
+	 */
+	public static String getIpAddr(HttpServletRequest request) {
+    	String ip = null;
+        try {
+            ip = request.getHeader("x-forwarded-for");
+            if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
+                ip = request.getHeader("Proxy-Client-IP");
+            }
+            if (StringUtils.isEmpty(ip) || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+                ip = request.getHeader("WL-Proxy-Client-IP");
+            }
+            if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
+                ip = request.getHeader("HTTP_CLIENT_IP");
+            }
+            if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
+                ip = request.getHeader("HTTP_X_FORWARDED_FOR");
+            }
+            if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
+                ip = request.getRemoteAddr();
+            }
+        } catch (Exception e) {
+        	logger.error("IPUtils ERROR ", e);
+        }
+        
+//        //使用代理,则获取第一个IP地址
+//        if(StringUtils.isEmpty(ip) && ip.length() > 15) {
+//			if(ip.indexOf(",") > 0) {
+//				ip = ip.substring(0, ip.indexOf(","));
+//			}
+//		}
+        
+        return ip;
+    }
+	
+}

+ 96 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/ImportExcelUtil.java

@@ -0,0 +1,96 @@
+package org.jeecg.common.util;
+
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.extension.service.IService;
+import lombok.extern.slf4j.Slf4j;
+import org.jeecg.common.api.vo.Result;
+import org.jeecg.common.constant.CommonConstant;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * 导出返回信息
+ */
+@Slf4j
+public class ImportExcelUtil {
+
+    public static Result<?> imporReturnRes(int errorLines,int successLines,List<String> errorMessage) throws IOException {
+        if (errorLines == 0) {
+            return Result.ok("共" + successLines + "行数据全部导入成功!");
+        } else {
+            JSONObject result = new JSONObject(5);
+            int totalCount = successLines + errorLines;
+            result.put("totalCount", totalCount);
+            result.put("errorCount", errorLines);
+            result.put("successCount", successLines);
+            result.put("msg", "总上传行数:" + totalCount + ",已导入行数:" + successLines + ",错误行数:" + errorLines);
+            String fileUrl = PmsUtil.saveErrorTxtByList(errorMessage, "userImportExcelErrorLog");
+            int lastIndex = fileUrl.lastIndexOf(File.separator);
+            String fileName = fileUrl.substring(lastIndex + 1);
+            result.put("fileUrl", "/sys/common/static/" + fileUrl);
+            result.put("fileName", fileName);
+            Result res = Result.ok(result);
+            res.setCode(201);
+            res.setMessage("文件导入成功,但有错误。");
+            return res;
+        }
+    }
+
+    public static List<String> importDateSave(List<Object> list, Class serviceClass,List<String> errorMessage,String errorFlag)  {
+        IService bean =(IService) SpringContextUtils.getBean(serviceClass);
+        for (int i = 0; i < list.size(); i++) {
+            try {
+                boolean save = bean.save(list.get(i));
+                if(!save){
+                    throw new Exception(errorFlag);
+                }
+            } catch (Exception e) {
+                String message = e.getMessage().toLowerCase();
+                int lineNumber = i + 1;
+                // 通过索引名判断出错信息
+                if (message.contains(CommonConstant.SQL_INDEX_UNIQ_SYS_ROLE_CODE)) {
+                    errorMessage.add("第 " + lineNumber + " 行:角色编码已经存在,忽略导入。");
+                } else if (message.contains(CommonConstant.SQL_INDEX_UNIQ_JOB_CLASS_NAME)) {
+                    errorMessage.add("第 " + lineNumber + " 行:任务类名已经存在,忽略导入。");
+                }else if (message.contains(CommonConstant.SQL_INDEX_UNIQ_CODE)) {
+                    errorMessage.add("第 " + lineNumber + " 行:职务编码已经存在,忽略导入。");
+                }else if (message.contains(CommonConstant.SQL_INDEX_UNIQ_DEPART_ORG_CODE)) {
+                    errorMessage.add("第 " + lineNumber + " 行:部门编码已经存在,忽略导入。");
+                }else {
+                    errorMessage.add("第 " + lineNumber + " 行:未知错误,忽略导入");
+                    log.error(e.getMessage(), e);
+                }
+            }
+        }
+        return errorMessage;
+    }
+
+    public static List<String> importDateSaveOne(Object obj, Class serviceClass,List<String> errorMessage,int i,String errorFlag)  {
+        IService bean =(IService) SpringContextUtils.getBean(serviceClass);
+        try {
+            boolean save = bean.save(obj);
+            if(!save){
+                throw new Exception(errorFlag);
+            }
+        } catch (Exception e) {
+            String message = e.getMessage().toLowerCase();
+            int lineNumber = i + 1;
+            // 通过索引名判断出错信息
+            if (message.contains(CommonConstant.SQL_INDEX_UNIQ_SYS_ROLE_CODE)) {
+                errorMessage.add("第 " + lineNumber + " 行:角色编码已经存在,忽略导入。");
+            } else if (message.contains(CommonConstant.SQL_INDEX_UNIQ_JOB_CLASS_NAME)) {
+                errorMessage.add("第 " + lineNumber + " 行:任务类名已经存在,忽略导入。");
+            }else if (message.contains(CommonConstant.SQL_INDEX_UNIQ_CODE)) {
+                errorMessage.add("第 " + lineNumber + " 行:职务编码已经存在,忽略导入。");
+            }else if (message.contains(CommonConstant.SQL_INDEX_UNIQ_DEPART_ORG_CODE)) {
+                errorMessage.add("第 " + lineNumber + " 行:部门编码已经存在,忽略导入。");
+            }else {
+                errorMessage.add("第 " + lineNumber + " 行:未知错误,忽略导入");
+                log.error(e.getMessage(), e);
+            }
+        }
+        return errorMessage;
+    }
+}

+ 43 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/MD5Util.java

@@ -0,0 +1,43 @@
+package org.jeecg.common.util;
+
+import java.security.MessageDigest;
+
+public class MD5Util {
+
+	public static String byteArrayToHexString(byte b[]) {
+		StringBuffer resultSb = new StringBuffer();
+		for (int i = 0; i < b.length; i++){
+			resultSb.append(byteToHexString(b[i]));
+		}
+		return resultSb.toString();
+	}
+
+	private static String byteToHexString(byte b) {
+		int n = b;
+		if (n < 0) {
+			n += 256;
+		}
+		int d1 = n / 16;
+		int d2 = n % 16;
+		return hexDigits[d1] + hexDigits[d2];
+	}
+
+	public static String MD5Encode(String origin, String charsetname) {
+		String resultString = null;
+		try {
+			resultString = new String(origin);
+			MessageDigest md = MessageDigest.getInstance("MD5");
+			if (charsetname == null || "".equals(charsetname)) {
+				resultString = byteArrayToHexString(md.digest(resultString.getBytes()));
+			} else {
+				resultString = byteArrayToHexString(md.digest(resultString.getBytes(charsetname)));
+			}
+		} catch (Exception exception) {
+		}
+		return resultString;
+	}
+
+	private static final String hexDigits[] = { "0", "1", "2", "3", "4", "5",
+			"6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };
+
+}

+ 213 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/MinioUtil.java

@@ -0,0 +1,213 @@
+package org.jeecg.common.util;
+
+import io.minio.*;
+import lombok.extern.slf4j.Slf4j;
+import org.jeecg.common.util.filter.StrAttackFilter;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.InputStream;
+import java.net.URLDecoder;
+
+/**
+ * minio文件上传工具类
+ */
+@Slf4j
+public class MinioUtil {
+    private static String minioUrl;
+    private static String minioName;
+    private static String minioPass;
+    private static String bucketName;
+
+    public static void setMinioUrl(String minioUrl) {
+        MinioUtil.minioUrl = minioUrl;
+    }
+
+    public static void setMinioName(String minioName) {
+        MinioUtil.minioName = minioName;
+    }
+
+    public static void setMinioPass(String minioPass) {
+        MinioUtil.minioPass = minioPass;
+    }
+
+    public static void setBucketName(String bucketName) {
+        MinioUtil.bucketName = bucketName;
+    }
+
+    public static String getMinioUrl() {
+        return minioUrl;
+    }
+
+    public static String getBucketName() {
+        return bucketName;
+    }
+
+    private static MinioClient minioClient = null;
+
+    /**
+     * 上传文件
+     * @param file
+     * @return
+     */
+    public static String upload(MultipartFile file, String bizPath, String customBucket) {
+        String file_url = "";
+        //update-begin-author:wangshuai date:20201012 for: 过滤上传文件夹名特殊字符,防止攻击
+        bizPath=StrAttackFilter.filter(bizPath);
+        //update-end-author:wangshuai date:20201012 for: 过滤上传文件夹名特殊字符,防止攻击
+        String newBucket = bucketName;
+        if(oConvertUtils.isNotEmpty(customBucket)){
+            newBucket = customBucket;
+        }
+        try {
+            initMinio(minioUrl, minioName,minioPass);
+            // 检查存储桶是否已经存在
+            if(minioClient.bucketExists(BucketExistsArgs.builder().bucket(newBucket).build())) {
+                log.info("Bucket already exists.");
+            } else {
+                // 创建一个名为ota的存储桶
+                minioClient.makeBucket(MakeBucketArgs.builder().bucket(newBucket).build());
+                log.info("create a new bucket.");
+            }
+            InputStream stream = file.getInputStream();
+            // 获取文件名
+            String orgName = file.getOriginalFilename();
+            if("".equals(orgName)){
+                orgName=file.getName();
+            }
+            orgName = CommonUtils.getFileName(orgName);
+            String objectName = bizPath+"/"
+                                +( orgName.indexOf(".")==-1
+                                   ?orgName + "_" + System.currentTimeMillis()
+                                   :orgName.substring(0, orgName.lastIndexOf(".")) + "_" + System.currentTimeMillis() + orgName.substring(orgName.lastIndexOf("."))
+                                 );
+
+            // 使用putObject上传一个本地文件到存储桶中。
+            if(objectName.startsWith("/")){
+                objectName = objectName.substring(1);
+            }
+            PutObjectArgs objectArgs = PutObjectArgs.builder().object(objectName)
+                    .bucket(newBucket)
+                    .contentType("application/octet-stream")
+                    .stream(stream,stream.available(),-1).build();
+            minioClient.putObject(objectArgs);
+            stream.close();
+            file_url = minioUrl+newBucket+"/"+objectName;
+        }catch (Exception e){
+            log.error(e.getMessage(), e);
+        }
+        return file_url;
+    }
+
+    /**
+     * 文件上传
+     * @param file
+     * @param bizPath
+     * @return
+     */
+    public static String upload(MultipartFile file, String bizPath) {
+        return  upload(file,bizPath,null);
+    }
+
+    /**
+     * 获取文件流
+     * @param bucketName
+     * @param objectName
+     * @return
+     */
+    public static InputStream getMinioFile(String bucketName,String objectName){
+        InputStream inputStream = null;
+        try {
+            initMinio(minioUrl, minioName, minioPass);
+            GetObjectArgs objectArgs = GetObjectArgs.builder().object(objectName)
+                    .bucket(bucketName).build();
+            inputStream = minioClient.getObject(objectArgs);
+        } catch (Exception e) {
+            log.info("文件获取失败" + e.getMessage());
+        }
+        return inputStream;
+    }
+
+    /**
+     * 删除文件
+     * @param bucketName
+     * @param objectName
+     * @throws Exception
+     */
+    public static void removeObject(String bucketName, String objectName) {
+        try {
+            initMinio(minioUrl, minioName,minioPass);
+            RemoveObjectArgs objectArgs = RemoveObjectArgs.builder().object(objectName)
+                    .bucket(bucketName).build();
+            minioClient.removeObject(objectArgs);
+        }catch (Exception e){
+            log.info("文件删除失败" + e.getMessage());
+        }
+    }
+
+    /**
+     * 获取文件外链
+     * @param bucketName
+     * @param objectName
+     * @param expires
+     * @return
+     */
+    public static String getObjectURL(String bucketName, String objectName, Integer expires) {
+        initMinio(minioUrl, minioName,minioPass);
+        try{
+            GetPresignedObjectUrlArgs objectArgs = GetPresignedObjectUrlArgs.builder().object(objectName)
+                    .bucket(bucketName)
+                    .expiry(expires).build();
+            String url = minioClient.getPresignedObjectUrl(objectArgs);
+            return URLDecoder.decode(url,"UTF-8");
+        }catch (Exception e){
+            log.info("文件路径获取失败" + e.getMessage());
+        }
+        return null;
+    }
+
+    /**
+     * 初始化客户端
+     * @param minioUrl
+     * @param minioName
+     * @param minioPass
+     * @return
+     */
+    private static MinioClient initMinio(String minioUrl, String minioName,String minioPass) {
+        if (minioClient == null) {
+            try {
+                minioClient = MinioClient.builder()
+                        .endpoint(minioUrl)
+                        .credentials(minioName, minioPass)
+                        .build();
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+        return minioClient;
+    }
+
+    /**
+     * 上传文件到minio
+     * @param stream
+     * @param relativePath
+     * @return
+     */
+    public static String upload(InputStream stream,String relativePath) throws Exception {
+        initMinio(minioUrl, minioName,minioPass);
+        if(minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build())) {
+            log.info("Bucket already exists.");
+        } else {
+            // 创建一个名为ota的存储桶
+            minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
+            log.info("create a new bucket.");
+        }
+        PutObjectArgs objectArgs = PutObjectArgs.builder().object(relativePath)
+                .bucket(bucketName)
+                .contentType("application/octet-stream")
+                .stream(stream,stream.available(),-1).build();
+        minioClient.putObject(objectArgs);
+        stream.close();
+        return minioUrl+bucketName+"/"+relativePath;
+    }
+
+}

+ 92 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/MyClassLoader.java

@@ -0,0 +1,92 @@
+package org.jeecg.common.util;
+
+/**
+ * @Author  张代浩
+ */
+public class MyClassLoader extends ClassLoader {
+	public static Class getClassByScn(String className) {
+		Class myclass = null;
+		try {
+			myclass = Class.forName(className);
+		} catch (ClassNotFoundException e) {
+			e.printStackTrace();
+			throw new RuntimeException(className+" not found!");
+		}
+		return myclass;
+	}
+
+	// 获得类的全名,包括包名
+	public static String getPackPath(Object object) {
+		// 检查用户传入的参数是否为空
+		if (object == null) {
+			throw new java.lang.IllegalArgumentException("参数不能为空!");
+		}
+		// 获得类的全名,包括包名
+		String clsName = object.getClass().getName();
+		return clsName;
+	}
+
+	public static String getAppPath(Class cls) {
+		// 检查用户传入的参数是否为空
+		if (cls == null) {
+			throw new java.lang.IllegalArgumentException("参数不能为空!");
+		}
+		ClassLoader loader = cls.getClassLoader();
+		// 获得类的全名,包括包名
+		String clsName = cls.getName() + ".class";
+		// 获得传入参数所在的包
+		Package pack = cls.getPackage();
+		String path = "";
+		// 如果不是匿名包,将包名转化为路径
+		if (pack != null) {
+			String packName = pack.getName();
+			// 此处简单判定是否是Java基础类库,防止用户传入JDK内置的类库
+			if (packName.startsWith("java.") || packName.startsWith("javax.")) {
+				throw new java.lang.IllegalArgumentException("不要传送系统类!");
+			}
+			// 在类的名称中,去掉包名的部分,获得类的文件名
+			clsName = clsName.substring(packName.length() + 1);
+			// 判定包名是否是简单包名,如果是,则直接将包名转换为路径,
+			if (packName.indexOf(".") < 0) {
+				path = packName + "/";
+			} else {// 否则按照包名的组成部分,将包名转换为路径
+				int start = 0, end = 0;
+				end = packName.indexOf(".");
+				while (end != -1) {
+					path = path + packName.substring(start, end) + "/";
+					start = end + 1;
+					end = packName.indexOf(".", start);
+				}
+				path = path + packName.substring(start) + "/";
+			}
+		}
+		// 调用ClassLoader的getResource方法,传入包含路径信息的类文件名
+		java.net.URL url = loader.getResource(path + clsName);
+		// 从URL对象中获取路径信息
+		String realPath = url.getPath();
+		// 去掉路径信息中的协议名"file:"
+		int pos = realPath.indexOf("file:");
+		if (pos > -1) {
+			realPath = realPath.substring(pos + 5);
+		}
+		// 去掉路径信息最后包含类文件信息的部分,得到类所在的路径
+		pos = realPath.indexOf(path + clsName);
+		realPath = realPath.substring(0, pos - 1);
+		// 如果类文件被打包到JAR等文件中时,去掉对应的JAR等打包文件名
+		if (realPath.endsWith("!")) {
+			realPath = realPath.substring(0, realPath.lastIndexOf("/"));
+		}
+		/*------------------------------------------------------------  
+		 ClassLoader的getResource方法使用了utf-8对路径信息进行了编码,当路径  
+		  中存在中文和空格时,他会对这些字符进行转换,这样,得到的往往不是我们想要  
+		  的真实路径,在此,调用了URLDecoder的decode方法进行解码,以便得到原始的  
+		  中文及空格路径  
+		-------------------------------------------------------------*/
+		try {
+			realPath = java.net.URLDecoder.decode(realPath, "utf-8");
+		} catch (Exception e) {
+			throw new RuntimeException(e);
+		}
+		return realPath;
+	}// getAppPath定义结束
+}

+ 180 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/PasswordUtil.java

@@ -0,0 +1,180 @@
+package org.jeecg.common.util;
+
+import java.security.Key;
+import java.security.SecureRandom;
+import javax.crypto.Cipher;
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.PBEKeySpec;
+import javax.crypto.spec.PBEParameterSpec;
+public class PasswordUtil {
+
+	/**
+	 * JAVA6支持以下任意一种算法 PBEWITHMD5ANDDES PBEWITHMD5ANDTRIPLEDES
+	 * PBEWITHSHAANDDESEDE PBEWITHSHA1ANDRC2_40 PBKDF2WITHHMACSHA1
+	 * */
+
+	/**
+	 * 定义使用的算法为:PBEWITHMD5andDES算法
+	 */
+	public static final String ALGORITHM = "PBEWithMD5AndDES";//加密算法
+	public static final String Salt = "63293188";//密钥
+
+	/**
+	 * 定义迭代次数为1000次
+	 */
+	private static final int ITERATIONCOUNT = 1000;
+
+	/**
+	 * 获取加密算法中使用的盐值,解密中使用的盐值必须与加密中使用的相同才能完成操作. 盐长度必须为8字节
+	 * 
+	 * @return byte[] 盐值
+	 * */
+	public static byte[] getSalt() throws Exception {
+		// 实例化安全随机数
+		SecureRandom random = new SecureRandom();
+		// 产出盐
+		return random.generateSeed(8);
+	}
+
+	public static byte[] getStaticSalt() {
+		// 产出盐
+		return Salt.getBytes();
+	}
+
+	/**
+	 * 根据PBE密码生成一把密钥
+	 * 
+	 * @param password
+	 *            生成密钥时所使用的密码
+	 * @return Key PBE算法密钥
+	 * */
+	private static Key getPBEKey(String password) {
+		// 实例化使用的算法
+		SecretKeyFactory keyFactory;
+		SecretKey secretKey = null;
+		try {
+			keyFactory = SecretKeyFactory.getInstance(ALGORITHM);
+			// 设置PBE密钥参数
+			PBEKeySpec keySpec = new PBEKeySpec(password.toCharArray());
+			// 生成密钥
+			secretKey = keyFactory.generateSecret(keySpec);
+		} catch (Exception e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+
+		return secretKey;
+	}
+
+	/**
+	 * 加密明文字符串
+	 * 
+	 * @param plaintext
+	 *            待加密的明文字符串
+	 * @param password
+	 *            生成密钥时所使用的密码
+	 * @param salt
+	 *            盐值
+	 * @return 加密后的密文字符串
+	 * @throws Exception
+	 */
+	public static String encrypt(String plaintext, String password, String salt) {
+
+		Key key = getPBEKey(password);
+		byte[] encipheredData = null;
+		PBEParameterSpec parameterSpec = new PBEParameterSpec(salt.getBytes(), ITERATIONCOUNT);
+		try {
+			Cipher cipher = Cipher.getInstance(ALGORITHM);
+
+			cipher.init(Cipher.ENCRYPT_MODE, key, parameterSpec);
+			//update-begin-author:sccott date:20180815 for:中文作为用户名时,加密的密码windows和linux会得到不同的结果 gitee/issues/IZUD7
+			encipheredData = cipher.doFinal(plaintext.getBytes("utf-8"));
+			//update-end-author:sccott date:20180815 for:中文作为用户名时,加密的密码windows和linux会得到不同的结果 gitee/issues/IZUD7
+		} catch (Exception e) {
+		}
+		return bytesToHexString(encipheredData);
+	}
+
+	/**
+	 * 解密密文字符串
+	 * 
+	 * @param ciphertext
+	 *            待解密的密文字符串
+	 * @param password
+	 *            生成密钥时所使用的密码(如需解密,该参数需要与加密时使用的一致)
+	 * @param salt
+	 *            盐值(如需解密,该参数需要与加密时使用的一致)
+	 * @return 解密后的明文字符串
+	 * @throws Exception
+	 */
+	public static String decrypt(String ciphertext, String password, String salt) {
+
+		Key key = getPBEKey(password);
+		byte[] passDec = null;
+		PBEParameterSpec parameterSpec = new PBEParameterSpec(salt.getBytes(), ITERATIONCOUNT);
+		try {
+			Cipher cipher = Cipher.getInstance(ALGORITHM);
+
+			cipher.init(Cipher.DECRYPT_MODE, key, parameterSpec);
+
+			passDec = cipher.doFinal(hexStringToBytes(ciphertext));
+		}
+
+		catch (Exception e) {
+			// TODO: handle exception
+		}
+		return new String(passDec);
+	}
+
+	/**
+	 * 将字节数组转换为十六进制字符串
+	 * 
+	 * @param src
+	 *            字节数组
+	 * @return
+	 */
+	public static String bytesToHexString(byte[] src) {
+		StringBuilder stringBuilder = new StringBuilder("");
+		if (src == null || src.length <= 0) {
+			return null;
+		}
+		for (int i = 0; i < src.length; i++) {
+			int v = src[i] & 0xFF;
+			String hv = Integer.toHexString(v);
+			if (hv.length() < 2) {
+				stringBuilder.append(0);
+			}
+			stringBuilder.append(hv);
+		}
+		return stringBuilder.toString();
+	}
+
+	/**
+	 * 将十六进制字符串转换为字节数组
+	 * 
+	 * @param hexString
+	 *            十六进制字符串
+	 * @return
+	 */
+	public static byte[] hexStringToBytes(String hexString) {
+		if (hexString == null || hexString.equals("")) {
+			return null;
+		}
+		hexString = hexString.toUpperCase();
+		int length = hexString.length() / 2;
+		char[] hexChars = hexString.toCharArray();
+		byte[] d = new byte[length];
+		for (int i = 0; i < length; i++) {
+			int pos = i * 2;
+			d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
+		}
+		return d;
+	}
+
+	private static byte charToByte(char c) {
+		return (byte) "0123456789ABCDEF".indexOf(c);
+	}
+
+
+}

+ 84 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/PathMatcherUtil.java

@@ -0,0 +1,84 @@
+package org.jeecg.common.util;
+
+import org.springframework.util.AntPathMatcher;
+
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ * 使用Spring自身提供的地址匹配工具匹配URL
+ */
+public class PathMatcherUtil {
+
+    public static void main(String[] args) {
+        String url = "/sys/dict/loadDictOrderByValue/tree,s2,2";
+        String p = "/sys/dict/loadDictOrderByValue/*";
+
+        System.out.println(PathMatcherUtil.match(p,url));
+    }
+
+    /**
+     * 实际验证路径匹配权限
+     *
+     * @param matchPath 权限url
+     * @param path      访问路径
+     * @return 是否拥有权限
+     */
+    public static boolean match(String matchPath, String path) {
+        SpringAntMatcher springAntMatcher = new SpringAntMatcher(matchPath, true);
+        return springAntMatcher.matches(path);
+    }
+
+    /**
+     * 实际验证路径匹配权限
+     *
+     * @param list 权限url
+     * @param path 访问路径
+     * @return 是否拥有权限
+     */
+    public static boolean matches(Collection<String> list, String path) {
+        for (String s : list) {
+            SpringAntMatcher springAntMatcher = new SpringAntMatcher(s, true);
+            if (springAntMatcher.matches(path)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 地址表达式匹配工具
+     */
+    private static class SpringAntMatcher implements Matcher {
+        private final AntPathMatcher antMatcher;
+        private final String pattern;
+
+        private SpringAntMatcher(String pattern, boolean caseSensitive) {
+            this.pattern = pattern;
+            this.antMatcher = createMatcher(caseSensitive);
+        }
+
+        @Override
+        public boolean matches(String path) {
+            return this.antMatcher.match(this.pattern, path);
+        }
+
+        @Override
+        public Map<String, String> extractUriTemplateVariables(String path) {
+            return this.antMatcher.extractUriTemplateVariables(this.pattern, path);
+        }
+
+        private static AntPathMatcher createMatcher(boolean caseSensitive) {
+            AntPathMatcher matcher = new AntPathMatcher();
+            matcher.setTrimTokens(false);
+            matcher.setCaseSensitive(caseSensitive);
+            return matcher;
+        }
+    }
+
+    private interface Matcher {
+        boolean matches(String var1);
+
+        Map<String, String> extractUriTemplateVariables(String var1);
+    }
+}

+ 61 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/PmsUtil.java

@@ -0,0 +1,61 @@
+package org.jeecg.common.util;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.util.Date;
+import java.util.List;
+
+@Slf4j
+@Component
+public class PmsUtil {
+
+
+    private static String uploadPath;
+
+    @Value("${jeecg.path.upload}")
+    public void setUploadPath(String uploadPath) {
+        PmsUtil.uploadPath = uploadPath;
+    }
+
+    public static String saveErrorTxtByList(List<String> msg, String name) {
+        Date d = new Date();
+        String saveDir = "logs" + File.separator + DateUtils.yyyyMMdd.get().format(d) + File.separator;
+        String saveFullDir = uploadPath + File.separator + saveDir;
+
+        File saveFile = new File(saveFullDir);
+        if (!saveFile.exists()) {
+            saveFile.mkdirs();
+        }
+        name += DateUtils.yyyymmddhhmmss.get().format(d) + Math.round(Math.random() * 10000);
+        String saveFilePath = saveFullDir + name + ".txt";
+
+        try {
+            //封装目的地
+            BufferedWriter bw = new BufferedWriter(new FileWriter(saveFilePath));
+            //遍历集合
+            for (String s : msg) {
+                //写数据
+                if (s.indexOf("_") > 0) {
+                    String arr[] = s.split("_");
+                    bw.write("第" + arr[0] + "行:" + arr[1]);
+                } else {
+                    bw.write(s);
+                }
+                //bw.newLine();
+                bw.write("\r\n");
+            }
+            //释放资源
+            bw.flush();
+            bw.close();
+        } catch (Exception e) {
+            log.info("excel导入生成错误日志文件异常:" + e.getMessage());
+        }
+        return saveDir + name + ".txt";
+    }
+
+}

+ 248 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/ReflectHelper.java

@@ -0,0 +1,248 @@
+package org.jeecg.common.util;
+
+import lombok.extern.slf4j.Slf4j;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.*;
+import java.util.Map.Entry;
+import java.util.regex.Pattern;
+
+/**
+ * @author 张代浩
+ * @desc 通过反射来动态调用get 和 set 方法
+ */
+@Slf4j
+public class ReflectHelper {
+
+    private Class cls;
+
+    /**
+     * 传过来的对象
+     */
+    private Object obj;
+
+    /**
+     * 存放get方法
+     */
+    private Hashtable<String, Method> getMethods = null;
+    /**
+     * 存放set方法
+     */
+    private Hashtable<String, Method> setMethods = null;
+
+    /**
+     * 定义构造方法 -- 一般来说是个pojo
+     *
+     * @param o 目标对象
+     */
+    public ReflectHelper(Object o) {
+        obj = o;
+        initMethods();
+    }
+
+    /**
+     * @desc 初始化
+     */
+    public void initMethods() {
+        getMethods = new Hashtable<String, Method>();
+        setMethods = new Hashtable<String, Method>();
+        cls = obj.getClass();
+        Method[] methods = cls.getMethods();
+        // 定义正则表达式,从方法中过滤出getter / setter 函数.
+        String gs = "get(\\w+)";
+        Pattern getM = Pattern.compile(gs);
+        String ss = "set(\\w+)";
+        Pattern setM = Pattern.compile(ss);
+        // 把方法中的"set" 或者 "get" 去掉
+        String rapl = "$1";
+        String param;
+        for (int i = 0; i < methods.length; ++i) {
+            Method m = methods[i];
+            String methodName = m.getName();
+            if (Pattern.matches(gs, methodName)) {
+                param = getM.matcher(methodName).replaceAll(rapl).toLowerCase();
+                getMethods.put(param, m);
+            } else if (Pattern.matches(ss, methodName)) {
+                param = setM.matcher(methodName).replaceAll(rapl).toLowerCase();
+                setMethods.put(param, m);
+            } else {
+                // logger.info(methodName + " 不是getter,setter方法!");
+            }
+        }
+    }
+
+    /**
+     * @desc 调用set方法
+     */
+    public boolean setMethodValue(String property, Object object) {
+        Method m = setMethods.get(property.toLowerCase());
+        if (m != null) {
+            try {
+                // 获取属性的类型
+                Class<?> parameterType = m.getParameterTypes()[0];
+                // 判断属性类型是否为int
+                if (parameterType.equals(int.class) || parameterType.equals(Integer.class)) {
+                    // 将object参数转换为int类型
+                    int value = Integer.parseInt(object.toString());
+                    // 调用目标类的setter函数
+                    m.invoke(obj, value);
+                } else {
+                    // 调用目标类的setter函数
+                    m.invoke(obj, object);
+                }
+                return true;
+            } catch (Exception ex) {
+                log.info("invoke getter on " + property + " error: " + ex.toString());
+                return false;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * @desc 调用set方法
+     */
+    public Object getMethodValue(String property) {
+        Object value = null;
+        Method m = getMethods.get(property.toLowerCase());
+        if (m != null) {
+            try {
+                /*
+                 * 调用obj类的setter函数
+                 */
+                value = m.invoke(obj, new Object[]{});
+
+            } catch (Exception ex) {
+                log.info("invoke getter on " + property + " error: " + ex.toString());
+            }
+        }
+        return value;
+    }
+
+    /**
+     * 把map中的内容全部注入到obj中
+     *
+     * @param data
+     * @return
+     */
+    public Object setAll(Map<String, Object> data) {
+        if (data == null || data.keySet().size() <= 0) {
+            return null;
+        }
+        for (Entry<String, Object> entry : data.entrySet()) {
+            this.setMethodValue(entry.getKey(), entry.getValue());
+        }
+        return obj;
+    }
+
+    /**
+     * 把map中的内容全部注入到obj中
+     *
+     * @param o
+     * @param data
+     * @return
+     */
+    public static Object setAll(Object o, Map<String, Object> data) {
+        ReflectHelper reflectHelper = new ReflectHelper(o);
+        reflectHelper.setAll(data);
+        return o;
+    }
+
+    /**
+     * 把map中的内容全部注入到新实例中
+     *
+     * @param clazz
+     * @param data
+     * @return
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> T setAll(Class<T> clazz, Map<String, Object> data) {
+        T o = null;
+        try {
+            o = clazz.newInstance();
+        } catch (Exception e) {
+            e.printStackTrace();
+            o = null;
+            return o;
+        }
+        return (T) setAll(o, data);
+    }
+
+    /**
+     * 根据传入的class将mapList转换为实体类list
+     *
+     * @param mapist
+     * @param clazz
+     * @return
+     */
+    public static <T> List<T> transList2Entrys(List<Map<String, Object>> mapist, Class<T> clazz) {
+        List<T> list = new ArrayList<T>();
+        if (mapist != null && mapist.size() > 0) {
+            for (Map<String, Object> data : mapist) {
+                list.add(ReflectHelper.setAll(clazz, data));
+            }
+        }
+        return list;
+    }
+
+    /**
+     * 根据属性名获取属性值
+     */
+    public static Object getFieldValueByName(String fieldName, Object o) {
+        try {
+            String firstLetter = fieldName.substring(0, 1).toUpperCase();
+            String getter = "get" + firstLetter + fieldName.substring(1);
+            Method method = o.getClass().getMethod(getter, new Class[]{});
+            Object value = method.invoke(o, new Object[]{});
+            return value;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    /**
+     * 获取属性名数组
+     */
+    public static String[] getFiledName(Object o) {
+        Field[] fields = o.getClass().getDeclaredFields();
+        String[] fieldNames = new String[fields.length];
+        for (int i = 0; i < fields.length; i++) {
+            //log.info(fields[i].getType());
+            fieldNames[i] = fields[i].getName();
+        }
+        return fieldNames;
+    }
+
+    /**
+     * 获取属性类型(type),属性名(name),属性值(value)的map组成的list
+     */
+    public static List<Map> getFiledsInfo(Object o) {
+        Field[] fields = o.getClass().getDeclaredFields();
+        String[] fieldNames = new String[fields.length];
+        List<Map> list = new ArrayList<Map>();
+        Map<String, Object> infoMap = null;
+        for (int i = 0; i < fields.length; i++) {
+            infoMap = new HashMap<String, Object>();
+            infoMap.put("type", fields[i].getType().toString());
+            infoMap.put("name", fields[i].getName());
+            infoMap.put("value", getFieldValueByName(fields[i].getName(), o));
+            list.add(infoMap);
+        }
+        return list;
+    }
+
+    /**
+     * 获取对象的所有属性值,返回一个对象数组
+     */
+    public static Object[] getFiledValues(Object o) {
+        String[] fieldNames = getFiledName(o);
+        Object[] value = new Object[fieldNames.length];
+        for (int i = 0; i < fieldNames.length; i++) {
+            value[i] = getFieldValueByName(fieldNames[i], o);
+        }
+        return value;
+    }
+
+}

+ 121 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/RestDesformUtil.java

@@ -0,0 +1,121 @@
+package org.jeecg.common.util;
+
+import com.alibaba.fastjson.JSONObject;
+import org.jeecg.common.api.vo.Result;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+
+/**
+ * 通过 RESTful 风格的接口操纵 desform 里的数据
+ *
+ * @author sunjianlei
+ */
+public class RestDesformUtil {
+
+    private static String domain = null;
+    private static String path = null;
+
+    static {
+        domain = SpringContextUtils.getDomain();
+        path = oConvertUtils.getString(SpringContextUtils.getApplicationContext().getEnvironment().getProperty("server.servlet.context-path"));
+    }
+
+    /**
+     * 查询数据
+     *
+     * @param desformCode
+     * @param dataId
+     * @param token
+     * @return
+     */
+    public static Result queryOne(String desformCode, String dataId, String token) {
+        String url = getBaseUrl(desformCode, dataId).toString();
+        HttpHeaders headers = getHeaders(token);
+        ResponseEntity<JSONObject> result = RestUtil.request(url, HttpMethod.GET, headers, null, null, JSONObject.class);
+        return packageReturn(result);
+    }
+
+    /**
+     * 新增数据
+     *
+     * @param desformCode
+     * @param formData
+     * @param token
+     * @return
+     */
+    public static Result addOne(String desformCode, JSONObject formData, String token) {
+        return addOrEditOne(desformCode, formData, token, HttpMethod.POST);
+    }
+
+    /**
+     * 修改数据
+     *
+     * @param desformCode
+     * @param formData
+     * @param token
+     * @return
+     */
+    public static Result editOne(String desformCode, JSONObject formData, String token) {
+        return addOrEditOne(desformCode, formData, token, HttpMethod.PUT);
+    }
+
+    private static Result addOrEditOne(String desformCode, JSONObject formData, String token, HttpMethod method) {
+        String url = getBaseUrl(desformCode).toString();
+        HttpHeaders headers = getHeaders(token);
+        ResponseEntity<JSONObject> result = RestUtil.request(url, method, headers, null, formData, JSONObject.class);
+        return packageReturn(result);
+    }
+
+    /**
+     * 删除数据
+     *
+     * @param desformCode
+     * @param dataId
+     * @param token
+     * @return
+     */
+    public static Result removeOne(String desformCode, String dataId, String token) {
+        String url = getBaseUrl(desformCode, dataId).toString();
+        HttpHeaders headers = getHeaders(token);
+        ResponseEntity<JSONObject> result = RestUtil.request(url, HttpMethod.DELETE, headers, null, null, JSONObject.class);
+        return packageReturn(result);
+    }
+
+    private static Result packageReturn(ResponseEntity<JSONObject> result) {
+        if (result.getBody() != null) {
+            return result.getBody().toJavaObject(Result.class);
+        }
+        return Result.error("操作失败");
+    }
+
+    private static StringBuilder getBaseUrl() {
+        StringBuilder builder = new StringBuilder(domain).append(path);
+        builder.append("/desform/api");
+        return builder;
+    }
+
+    private static StringBuilder getBaseUrl(String desformCode, String dataId) {
+        StringBuilder builder = getBaseUrl();
+        builder.append("/").append(desformCode);
+        if (dataId != null) {
+            builder.append("/").append(dataId);
+        }
+        return builder;
+    }
+
+    private static StringBuilder getBaseUrl(String desformCode) {
+        return getBaseUrl(desformCode, null);
+    }
+
+    private static HttpHeaders getHeaders(String token) {
+        HttpHeaders headers = new HttpHeaders();
+        String mediaType = MediaType.APPLICATION_JSON_UTF8_VALUE;
+        headers.setContentType(MediaType.parseMediaType(mediaType));
+        headers.set("Accept", mediaType);
+        headers.set("X-Access-Token", token);
+        return headers;
+    }
+
+}

+ 257 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/RestUtil.java

@@ -0,0 +1,257 @@
+package org.jeecg.common.util;
+
+import com.alibaba.fastjson.JSONObject;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.http.*;
+import org.springframework.http.client.SimpleClientHttpRequestFactory;
+import org.springframework.http.converter.StringHttpMessageConverter;
+import org.springframework.web.client.RestTemplate;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * 调用 Restful 接口 Util
+ *
+ * @author sunjianlei
+ */
+@Slf4j
+public class RestUtil {
+
+    private static String domain = null;
+
+    public static String getDomain() {
+        if (domain == null) {
+            domain = SpringContextUtils.getDomain();
+        }
+        return domain;
+    }
+
+    public static String path = null;
+
+    public static String getPath() {
+        if (path == null) {
+            path = SpringContextUtils.getApplicationContext().getEnvironment().getProperty("server.servlet.context-path");
+        }
+        return oConvertUtils.getString(path);
+    }
+
+    public static String getBaseUrl() {
+        String basepath = getDomain() + getPath();
+        log.info(" RestUtil.getBaseUrl: " + basepath);
+        return basepath;
+    }
+
+    /**
+     * RestAPI 调用器
+     */
+    private final static RestTemplate RT;
+
+    static {
+        SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
+        requestFactory.setConnectTimeout(3000);
+        requestFactory.setReadTimeout(3000);
+        RT = new RestTemplate(requestFactory);
+        // 解决乱码问题
+        RT.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
+    }
+
+    public static RestTemplate getRestTemplate() {
+        return RT;
+    }
+
+    /**
+     * 发送 get 请求
+     */
+    public static JSONObject get(String url) {
+        return getNative(url, null, null).getBody();
+    }
+
+    /**
+     * 发送 get 请求
+     */
+    public static JSONObject get(String url, JSONObject variables) {
+        return getNative(url, variables, null).getBody();
+    }
+
+    /**
+     * 发送 get 请求
+     */
+    public static JSONObject get(String url, JSONObject variables, JSONObject params) {
+        return getNative(url, variables, params).getBody();
+    }
+
+    /**
+     * 发送 get 请求,返回原生 ResponseEntity 对象
+     */
+    public static ResponseEntity<JSONObject> getNative(String url, JSONObject variables, JSONObject params) {
+        return request(url, HttpMethod.GET, variables, params);
+    }
+
+    /**
+     * 发送 Post 请求
+     */
+    public static JSONObject post(String url) {
+        return postNative(url, null, null).getBody();
+    }
+
+    /**
+     * 发送 Post 请求
+     */
+    public static JSONObject post(String url, JSONObject params) {
+        return postNative(url, null, params).getBody();
+    }
+
+    /**
+     * 发送 Post 请求
+     */
+    public static JSONObject post(String url, JSONObject variables, JSONObject params) {
+        return postNative(url, variables, params).getBody();
+    }
+
+    /**
+     * 发送 POST 请求,返回原生 ResponseEntity 对象
+     */
+    public static ResponseEntity<JSONObject> postNative(String url, JSONObject variables, JSONObject params) {
+        return request(url, HttpMethod.POST, variables, params);
+    }
+
+    /**
+     * 发送 put 请求
+     */
+    public static JSONObject put(String url) {
+        return putNative(url, null, null).getBody();
+    }
+
+    /**
+     * 发送 put 请求
+     */
+    public static JSONObject put(String url, JSONObject params) {
+        return putNative(url, null, params).getBody();
+    }
+
+    /**
+     * 发送 put 请求
+     */
+    public static JSONObject put(String url, JSONObject variables, JSONObject params) {
+        return putNative(url, variables, params).getBody();
+    }
+
+    /**
+     * 发送 put 请求,返回原生 ResponseEntity 对象
+     */
+    public static ResponseEntity<JSONObject> putNative(String url, JSONObject variables, JSONObject params) {
+        return request(url, HttpMethod.PUT, variables, params);
+    }
+
+    /**
+     * 发送 delete 请求
+     */
+    public static JSONObject delete(String url) {
+        return deleteNative(url, null, null).getBody();
+    }
+
+    /**
+     * 发送 delete 请求
+     */
+    public static JSONObject delete(String url, JSONObject variables, JSONObject params) {
+        return deleteNative(url, variables, params).getBody();
+    }
+
+    /**
+     * 发送 delete 请求,返回原生 ResponseEntity 对象
+     */
+    public static ResponseEntity<JSONObject> deleteNative(String url, JSONObject variables, JSONObject params) {
+        return request(url, HttpMethod.DELETE, null, variables, params, JSONObject.class);
+    }
+
+    /**
+     * 发送请求
+     */
+    public static ResponseEntity<JSONObject> request(String url, HttpMethod method, JSONObject variables, JSONObject params) {
+        return request(url, method, getHeaderApplicationJson(), variables, params, JSONObject.class);
+    }
+
+    /**
+     * 发送请求
+     *
+     * @param url          请求地址
+     * @param method       请求方式
+     * @param headers      请求头  可空
+     * @param variables    请求url参数 可空
+     * @param params       请求body参数 可空
+     * @param responseType 返回类型
+     * @return ResponseEntity<responseType>
+     */
+    public static <T> ResponseEntity<T> request(String url, HttpMethod method, HttpHeaders headers, JSONObject variables, Object params, Class<T> responseType) {
+        log.info(" RestUtil  --- request ---  url = "+ url);
+        if (StringUtils.isEmpty(url)) {
+            throw new RuntimeException("url 不能为空");
+        }
+        if (method == null) {
+            throw new RuntimeException("method 不能为空");
+        }
+        if (headers == null) {
+            headers = new HttpHeaders();
+        }
+        // 请求体
+        String body = "";
+        if (params != null) {
+            if (params instanceof JSONObject) {
+                body = ((JSONObject) params).toJSONString();
+
+            } else {
+                body = params.toString();
+            }
+        }
+        // 拼接 url 参数
+        if (variables != null) {
+            url += ("?" + asUrlVariables(variables));
+        }
+        // 发送请求
+        HttpEntity<String> request = new HttpEntity<>(body, headers);
+        return RT.exchange(url, method, request, responseType);
+    }
+
+    /**
+     * 获取JSON请求头
+     */
+    public static HttpHeaders getHeaderApplicationJson() {
+        return getHeader(MediaType.APPLICATION_JSON_UTF8_VALUE);
+    }
+
+    /**
+     * 获取请求头
+     */
+    public static HttpHeaders getHeader(String mediaType) {
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(MediaType.parseMediaType(mediaType));
+        headers.add("Accept", mediaType);
+        return headers;
+    }
+
+    /**
+     * 将 JSONObject 转为 a=1&b=2&c=3...&n=n 的形式
+     */
+    public static String asUrlVariables(JSONObject variables) {
+        Map<String, Object> source = variables.getInnerMap();
+        Iterator<String> it = source.keySet().iterator();
+        StringBuilder urlVariables = new StringBuilder();
+        while (it.hasNext()) {
+            String key = it.next();
+            String value = "";
+            Object object = source.get(key);
+            if (object != null) {
+                if (!StringUtils.isEmpty(object.toString())) {
+                    value = object.toString();
+                }
+            }
+            urlVariables.append("&").append(key).append("=").append(value);
+        }
+        // 去掉第一个&
+        return urlVariables.substring(1);
+    }
+
+}

+ 94 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/SpringContextUtils.java

@@ -0,0 +1,94 @@
+package org.jeecg.common.util;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.jeecg.common.constant.ServiceNameConstants;
+import org.springframework.beans.BeansException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.stereotype.Component;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+@Component
+public class SpringContextUtils implements ApplicationContextAware {
+
+	/**
+	 * 上下文对象实例
+	 */
+	private static ApplicationContext applicationContext;
+
+	@Override
+	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+		SpringContextUtils.applicationContext = applicationContext;
+	}
+
+	/**
+	 * 获取applicationContext
+	 *
+	 * @return
+	 */
+	public static ApplicationContext getApplicationContext() {
+		return applicationContext;
+	}
+
+	/**
+	  * 获取HttpServletRequest
+	 */
+	public static HttpServletRequest getHttpServletRequest() {
+		return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+	}
+
+	/**
+	*  获取项目根路径 basePath
+	*/
+	public static String getDomain(){
+		HttpServletRequest request = getHttpServletRequest();
+		StringBuffer url = request.getRequestURL();
+		//微服务情况下,获取gateway的basePath
+		String basePath = request.getHeader(ServiceNameConstants.X_GATEWAY_BASE_PATH);
+		if(oConvertUtils.isNotEmpty(basePath)){
+			return basePath;
+		}else{
+			return url.delete(url.length() - request.getRequestURI().length(), url.length()).toString();
+		}
+	}
+
+	public static String getOrigin(){
+		HttpServletRequest request = getHttpServletRequest();
+		return request.getHeader("Origin");
+	}
+	
+	/**
+	 * 通过name获取 Bean.
+	 *
+	 * @param name
+	 * @return
+	 */
+	public static Object getBean(String name) {
+		return getApplicationContext().getBean(name);
+	}
+
+	/**
+	 * 通过class获取Bean.
+	 *
+	 * @param clazz
+	 * @param       <T>
+	 * @return
+	 */
+	public static <T> T getBean(Class<T> clazz) {
+		return getApplicationContext().getBean(clazz);
+	}
+
+	/**
+	 * 通过name,以及Clazz返回指定的Bean
+	 *
+	 * @param name
+	 * @param clazz
+	 * @param       <T>
+	 * @return
+	 */
+	public static <T> T getBean(String name, Class<T> clazz) {
+		return getApplicationContext().getBean(name, clazz);
+	}
+}

+ 139 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/SqlInjectionUtil.java

@@ -0,0 +1,139 @@
+package org.jeecg.common.util;
+
+import cn.hutool.crypto.SecureUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.jeecg.common.exception.JeecgBootException;
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * sql注入处理工具类
+ * 
+ * @author zhoujf
+ */
+@Slf4j
+public class SqlInjectionUtil {
+	/**
+	 * sign 用于表字典加签的盐值【SQL漏洞】
+	 * (上线修改值 20200501,同步修改前端的盐值)
+	 */
+	private final static String TABLE_DICT_SIGN_SALT = "20200501";
+	private final static String xssStr = "'|and |exec |insert |select |delete |update |drop |count |chr |mid |master |truncate |char |declare |;|or |+";
+
+	/*
+	* 针对表字典进行额外的sign签名校验(增加安全机制)
+	* @param dictCode:
+	* @param sign:
+	* @param request:
+	* @Return: void
+	*/
+	public static void checkDictTableSign(String dictCode, String sign, HttpServletRequest request) {
+		//表字典SQL注入漏洞,签名校验
+		String accessToken = request.getHeader("X-Access-Token");
+		String signStr = dictCode + SqlInjectionUtil.TABLE_DICT_SIGN_SALT + accessToken;
+		String javaSign = SecureUtil.md5(signStr);
+		if (!javaSign.equals(sign)) {
+			log.error("表字典,SQL注入漏洞签名校验失败 :" + sign + "!=" + javaSign+ ",dictCode=" + dictCode);
+			throw new JeecgBootException("无权限访问!");
+		}
+		log.info(" 表字典,SQL注入漏洞签名校验成功!sign=" + sign + ",dictCode=" + dictCode);
+	}
+
+
+	/**
+	 * sql注入过滤处理,遇到注入关键字抛异常
+	 * 
+	 * @param value
+	 * @return
+	 */
+	public static void filterContent(String value) {
+		if (value == null || "".equals(value)) {
+			return;
+		}
+		// 统一转为小写
+		value = value.toLowerCase();
+		String[] xssArr = xssStr.split("\\|");
+		for (int i = 0; i < xssArr.length; i++) {
+			if (value.indexOf(xssArr[i]) > -1) {
+				log.error("请注意,存在SQL注入关键词---> {}", xssArr[i]);
+				log.error("请注意,值可能存在SQL注入风险!---> {}", value);
+				throw new RuntimeException("请注意,值可能存在SQL注入风险!--->" + value);
+			}
+		}
+		return;
+	}
+
+	/**
+	 * sql注入过滤处理,遇到注入关键字抛异常
+	 * 
+	 * @param values
+	 * @return
+	 */
+	public static void filterContent(String[] values) {
+		String[] xssArr = xssStr.split("\\|");
+		for (String value : values) {
+			if (value == null || "".equals(value)) {
+				return;
+			}
+			// 统一转为小写
+			value = value.toLowerCase();
+			for (int i = 0; i < xssArr.length; i++) {
+				if (value.indexOf(xssArr[i]) > -1) {
+					log.error("请注意,存在SQL注入关键词---> {}", xssArr[i]);
+					log.error("请注意,值可能存在SQL注入风险!---> {}", value);
+					throw new RuntimeException("请注意,值可能存在SQL注入风险!--->" + value);
+				}
+			}
+		}
+		return;
+	}
+
+	/**
+	 * @特殊方法(不通用) 仅用于字典条件SQL参数,注入过滤
+	 * @param value
+	 * @return
+	 */
+	@Deprecated
+	public static void specialFilterContent(String value) {
+		String specialXssStr = " exec | insert | select | delete | update | drop | count | chr | mid | master | truncate | char | declare |;|+|";
+		String[] xssArr = specialXssStr.split("\\|");
+		if (value == null || "".equals(value)) {
+			return;
+		}
+		// 统一转为小写
+		value = value.toLowerCase();
+		for (int i = 0; i < xssArr.length; i++) {
+			if (value.indexOf(xssArr[i]) > -1 || value.startsWith(xssArr[i].trim())) {
+				log.error("请注意,存在SQL注入关键词---> {}", xssArr[i]);
+				log.error("请注意,值可能存在SQL注入风险!---> {}", value);
+				throw new RuntimeException("请注意,值可能存在SQL注入风险!--->" + value);
+			}
+		}
+		return;
+	}
+
+
+    /**
+     * @特殊方法(不通用) 仅用于Online报表SQL解析,注入过滤
+     * @param value
+     * @return
+     */
+	@Deprecated
+	public static void specialFilterContentForOnlineReport(String value) {
+		String specialXssStr = " exec | insert | delete | update | drop | chr | mid | master | truncate | char | declare |";
+		String[] xssArr = specialXssStr.split("\\|");
+		if (value == null || "".equals(value)) {
+			return;
+		}
+		// 统一转为小写
+		value = value.toLowerCase();
+		for (int i = 0; i < xssArr.length; i++) {
+			if (value.indexOf(xssArr[i]) > -1 || value.startsWith(xssArr[i].trim())) {
+				log.error("请注意,存在SQL注入关键词---> {}", xssArr[i]);
+				log.error("请注意,值可能存在SQL注入风险!---> {}", value);
+				throw new RuntimeException("请注意,值可能存在SQL注入风险!--->" + value);
+			}
+		}
+		return;
+	}
+
+}

+ 70 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/SysAnnmentTypeEnum.java

@@ -0,0 +1,70 @@
+package org.jeecg.common.util;
+
+/**
+ * 系统公告自定义跳转方式
+ */
+public enum SysAnnmentTypeEnum {
+    /**
+     * 邮件跳转组件
+     */
+    EMAIL("email", "component", "modules/eoa/email/modals/EoaEmailInForm"),
+    /**
+     * 工作流跳转链接我的办公
+     */
+    BPM("bpm", "url", "/bpm/task/MyTaskList");
+
+    /**
+     * 业务类型(email:邮件 bpm:流程)
+     */
+    private String type;
+    /**
+     * 打开方式 组件:component 路由:url
+     */
+    private String openType;
+    /**
+     * 组件/路由 地址
+     */
+    private String openPage;
+
+    SysAnnmentTypeEnum(String type, String openType, String openPage) {
+        this.type = type;
+        this.openType = openType;
+        this.openPage = openPage;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    public String getOpenType() {
+        return openType;
+    }
+
+    public void setOpenType(String openType) {
+        this.openType = openType;
+    }
+
+    public String getOpenPage() {
+        return openPage;
+    }
+
+    public void setOpenPage(String openPage) {
+        this.openPage = openPage;
+    }
+
+    public static SysAnnmentTypeEnum getByType(String type) {
+        if (oConvertUtils.isEmpty(type)) {
+            return null;
+        }
+        for (SysAnnmentTypeEnum val : values()) {
+            if (val.getType().equals(type)) {
+                return val;
+            }
+        }
+        return null;
+    }
+}

+ 128 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/TokenUtils.java

@@ -0,0 +1,128 @@
+package org.jeecg.common.util;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.shiro.authc.AuthenticationException;
+import org.jeecg.common.api.CommonAPI;
+import org.jeecg.common.constant.CommonConstant;
+import org.jeecg.common.system.util.JwtUtil;
+import org.jeecg.common.system.vo.LoginUser;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * @Author scott
+ * @Date 2019/9/23 14:12
+ * @Description: 编程校验token有效性
+ */
+@Slf4j
+public class TokenUtils {
+
+    /**
+     * 获取 request 里传递的 token
+     *
+     * @param request
+     * @return
+     */
+    public static String getTokenByRequest(HttpServletRequest request) {
+        String token = request.getParameter("token");
+        if (token == null) {
+            token = request.getHeader("X-Access-Token");
+        }
+        return token;
+    }
+
+    /**
+     * 验证Token
+     */
+    public static boolean verifyToken(HttpServletRequest request, CommonAPI commonAPI, RedisUtil redisUtil) {
+        log.debug(" -- url --" + request.getRequestURL());
+        String token = getTokenByRequest(request);
+
+        if (StringUtils.isBlank(token)) {
+            throw new AuthenticationException("Token不能为空!");
+        }
+
+        // 解密获得username,用于和数据库进行对比
+        String username = JwtUtil.getUsername(token);
+        if (username == null) {
+            throw new AuthenticationException("Token非法无效!");
+        }
+
+        // 查询用户信息
+        LoginUser user = commonAPI.getUserByName(username);
+        if (user == null) {
+            throw new AuthenticationException("用户不存在!");
+        }
+        // 判断用户状态
+        if (user.getStatus() != 1) {
+            throw new AuthenticationException("账号已锁定,请联系管理员!");
+        }
+        // 校验token是否超时失效 & 或者账号密码是否错误
+        if (!jwtTokenRefresh(token, username, user.getPassword(), redisUtil)) {
+            throw new AuthenticationException("Token失效,请重新登录");
+        }
+        return true;
+    }
+
+    /**
+     * 刷新token(保证用户在线操作不掉线)
+     * @param token
+     * @param userName
+     * @param passWord
+     * @param redisUtil
+     * @return
+     */
+    private static boolean jwtTokenRefresh(String token, String userName, String passWord, RedisUtil redisUtil) {
+        String cacheToken = String.valueOf(redisUtil.get(CommonConstant.PREFIX_USER_TOKEN + token));
+        if (oConvertUtils.isNotEmpty(cacheToken)) {
+            // 校验token有效性
+            if (!JwtUtil.verify(cacheToken, userName, passWord)) {
+                String newAuthorization = JwtUtil.sign(userName, passWord);
+                // 设置Toekn缓存有效时间
+                redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, newAuthorization);
+                redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME*2 / 1000);
+            }
+            //update-begin--Author:scott  Date:20191005  for:解决每次请求,都重写redis中 token缓存问题
+//            else {
+//                redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, cacheToken);
+//                // 设置超时时间
+//                redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME / 1000);
+//            }
+            //update-end--Author:scott  Date:20191005  for:解决每次请求,都重写redis中 token缓存问题
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * 验证Token
+     */
+    public static boolean verifyToken(String token, CommonAPI commonAPI, RedisUtil redisUtil) {
+        if (StringUtils.isBlank(token)) {
+            throw new AuthenticationException("token不能为空!");
+        }
+
+        // 解密获得username,用于和数据库进行对比
+        String username = JwtUtil.getUsername(token);
+        if (username == null) {
+            throw new AuthenticationException("token非法无效!");
+        }
+
+        // 查询用户信息
+        LoginUser user = commonAPI.getUserByName(username);
+        if (user == null) {
+            throw new AuthenticationException("用户不存在!");
+        }
+        // 判断用户状态
+        if (user.getStatus() != 1) {
+            throw new AuthenticationException("账号已被锁定,请联系管理员!");
+        }
+        // 校验token是否超时失效 & 或者账号密码是否错误
+        if (!jwtTokenRefresh(token, username, user.getPassword(), redisUtil)) {
+            throw new AuthenticationException("Token失效,请重新登录!");
+        }
+        return true;
+    }
+
+}

+ 95 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/UUIDGenerator.java

@@ -0,0 +1,95 @@
+package org.jeecg.common.util;
+
+
+import java.net.InetAddress;
+
+/**
+ * 
+ * @Author  张代浩
+ *
+ */
+public class UUIDGenerator {
+
+	
+	/**
+	 * 产生一个32位的UUID
+	 * 
+	 * @return
+	 */
+
+	public static String generate() {
+		return new StringBuilder(32).append(format(getIP())).append(
+				format(getJVM())).append(format(getHiTime())).append(
+				format(getLoTime())).append(format(getCount())).toString();
+		
+	}
+
+	private static final int IP;
+	static {
+		int ipadd;
+		try {
+			ipadd = toInt(InetAddress.getLocalHost().getAddress());
+		} catch (Exception e) {
+			ipadd = 0;
+		}
+		IP = ipadd;
+	}
+
+	private static short counter = (short) 0;
+
+	private static final int JVM = (int) (System.currentTimeMillis() >>> 8);
+
+	private final static String format(int intval) {
+		String formatted = Integer.toHexString(intval);
+		StringBuilder buf = new StringBuilder("00000000");
+		buf.replace(8 - formatted.length(), 8, formatted);
+		return buf.toString();
+	}
+
+	private final static String format(short shortval) {
+		String formatted = Integer.toHexString(shortval);
+		StringBuilder buf = new StringBuilder("0000");
+		buf.replace(4 - formatted.length(), 4, formatted);
+		return buf.toString();
+	}
+
+	private final static int getJVM() {
+		return JVM;
+	}
+
+	private final static short getCount() {
+		synchronized (UUIDGenerator.class) {
+			if (counter < 0) {
+				counter = 0;
+			}
+			return counter++;
+		}
+	}
+
+	/**
+	 * Unique in a local network
+	 */
+	private final static int getIP() {
+		return IP;
+	}
+
+	/**
+	 * Unique down to millisecond
+	 */
+	private final static short getHiTime() {
+		return (short) (System.currentTimeMillis() >>> 32);
+	}
+
+	private final static int getLoTime() {
+		return (int) System.currentTimeMillis();
+	}
+
+	private final static int toInt(byte[] bytes) {
+		int result = 0;
+		for (int i = 0; i < 4; i++) {
+			result = (result << 8) - Byte.MIN_VALUE + (int) bytes[i];
+		}
+		return result;
+	}
+
+}

+ 173 - 0
jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/YouBianCodeUtil.java

@@ -0,0 +1,173 @@
+package org.jeecg.common.util;
+
+import io.netty.util.internal.StringUtil;
+
+/**
+ * 流水号生成规则(按默认规则递增,数字从1-99开始递增,数字到99,递增字母;位数不够增加位数)
+ * A001
+ * A001A002
+ * @Author zhangdaihao
+ *
+ */
+public class YouBianCodeUtil {
+
+	// 数字位数(默认生成3位的数字)
+
+	private static final int numLength = 2;//代表数字位数
+
+	public static final int zhanweiLength = 1+numLength;
+
+	/**
+	 * 根据前一个code,获取同级下一个code
+	 * 例如:当前最大code为D01A04,下一个code为:D01A05
+	 * 
+	 * @param code
+	 * @return
+	 */
+	public static synchronized String getNextYouBianCode(String code) {
+		String newcode = "";
+		if (code == null || code =="") {
+			String zimu = "A";
+			String num = getStrNum(1);
+			newcode = zimu + num;
+		} else {
+			String before_code = code.substring(0, code.length() - 1- numLength);
+			String after_code = code.substring(code.length() - 1 - numLength,code.length());
+			char after_code_zimu = after_code.substring(0, 1).charAt(0);
+			Integer after_code_num = Integer.parseInt(after_code.substring(1));
+//			org.jeecgframework.core.util.LogUtil.info(after_code);
+//			org.jeecgframework.core.util.LogUtil.info(after_code_zimu);
+//			org.jeecgframework.core.util.LogUtil.info(after_code_num);
+
+			String nextNum = "";
+			char nextZimu = 'A';
+			// 先判断数字等于999*,则计数从1重新开始,递增
+			if (after_code_num == getMaxNumByLength(numLength)) {
+				nextNum = getNextStrNum(0);
+			} else {
+				nextNum = getNextStrNum(after_code_num);
+			}
+			// 先判断数字等于999*,则字母从A重新开始,递增
+			if(after_code_num == getMaxNumByLength(numLength)) {
+				nextZimu = getNextZiMu(after_code_zimu);
+			}else{
+				nextZimu = after_code_zimu;
+			}
+
+			// 例如Z99,下一个code就是Z99A01
+			if ('Z' == after_code_zimu && getMaxNumByLength(numLength) == after_code_num) {
+				newcode = code + (nextZimu + nextNum);
+			} else {
+				newcode = before_code + (nextZimu + nextNum);
+			}
+		}
+		return newcode;
+
+	}
+
+	/**
+	 * 根据父亲code,获取下级的下一个code
+	 * 
+	 * 例如:父亲CODE:A01
+	 *       当前CODE:A01B03
+	 *       获取的code:A01B04
+	 *       
+	 * @param parentCode   上级code
+	 * @param localCode    同级code
+	 * @return
+	 */
+	public static synchronized String getSubYouBianCode(String parentCode,String localCode) {
+		if(localCode!=null && localCode!=""){
+
+//			return parentCode + getNextYouBianCode(localCode);
+			return getNextYouBianCode(localCode);
+
+		}else{
+			parentCode = parentCode + "A"+ getNextStrNum(0);
+		}
+		return parentCode;
+	}
+
+	
+
+	/**
+	 * 将数字前面位数补零
+	 * 
+	 * @param num
+	 * @return
+	 */
+	private static String getNextStrNum(int num) {
+		return getStrNum(getNextNum(num));
+	}
+
+	/**
+	 * 将数字前面位数补零
+	 * 
+	 * @param num
+	 * @return
+	 */
+	private static String getStrNum(int num) {
+		String s = String.format("%0" + numLength + "d", num);
+		return s;
+	}
+
+	/**
+	 * 递增获取下个数字
+	 * 
+	 * @param num
+	 * @return
+	 */
+	private static int getNextNum(int num) {
+		num++;
+		return num;
+	}
+
+	/**
+	 * 递增获取下个字母
+	 * 
+	 * @param num
+	 * @return
+	 */
+	private static char getNextZiMu(char zimu) {
+		if (zimu == 'Z') {
+			return 'A';
+		}
+		zimu++;
+		return zimu;
+	}
+	
+	/**
+	 * 根据数字位数获取最大值
+	 * @param length
+	 * @return
+	 */
+	private static int getMaxNumByLength(int length){
+		if(length==0){
+			return 0;
+		}
+		String max_num = "";
+		for (int i=0;i<length;i++){
+			max_num = max_num + "9";
+		}
+		return Integer.parseInt(max_num);
+	}
+	public static String[] cutYouBianCode(String code){
+		if(code==null || StringUtil.isNullOrEmpty(code)){
+			return null;
+		}else{
+			//获取标准长度为numLength+1,截取的数量为code.length/numLength+1
+			int c = code.length()/(numLength+1);
+			String[] cutcode = new String[c];
+			for(int i =0 ; i <c;i++){
+				cutcode[i] = code.substring(0,(i+1)*(numLength+1));
+			}
+			return cutcode;
+		}
+		
+	}
+//	public static void main(String[] args) {
+//		// org.jeecgframework.core.util.LogUtil.info(getNextZiMu('C'));
+//		// org.jeecgframework.core.util.LogUtil.info(getNextNum(8));
+//	    // org.jeecgframework.core.util.LogUtil.info(cutYouBianCode("C99A01B01")[2]);
+//	}
+}

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio