Преглед изворни кода

Merge branch 'master' of http://60.171.161.56:20000/tjf/rongzidanbao

wangmengwei пре 8 месеци
родитељ
комит
c5bd51d0db
100 измењених фајлова са 11034 додато и 352 уклоњено
  1. 5 5
      pom.xml
  2. 26 4
      ruoyi-admin/pom.xml
  3. 5 0
      ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java
  4. 113 0
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/banner/BannerController.java
  5. 125 0
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/category/IndustryCategoryController.java
  6. 79 0
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/AppletController.java
  7. 136 44
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java
  8. 82 0
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/OcrController.java
  9. 69 0
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/SendSmsController.java
  10. 58 0
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/WordController.java
  11. 158 0
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/conference/SysUserConferenceController.java
  12. 103 0
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/document/ExplainDocumentController.java
  13. 128 0
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/enterprise/SysUserEnterpriseController.java
  14. 103 0
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/guarantee/GuaranteeInfoController.java
  15. 103 0
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/guarantee/GuaranteeInfoFjController.java
  16. 104 0
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/hyperlink/HyperlinkController.java
  17. 118 0
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/idcard/SysUserIdcardController.java
  18. 257 0
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/loan/LoanApplicationController.java
  19. 105 0
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/loan/LoanApplicationFjController.java
  20. 96 0
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/loan/LoanScheduleController.java
  21. 112 0
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/loan/ShareholderFjController.java
  22. 3 3
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/CacheController.java
  23. 2 2
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysLogininforController.java
  24. 2 2
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysOperlogController.java
  25. 1 1
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysUserOnlineController.java
  26. 56 0
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/qichacha/QiChaCha.java
  27. 96 0
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/remind/WaitRemindController.java
  28. 95 0
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/review/ReviewCommentsController.java
  29. 56 0
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/statistics/StatisticsController.java
  30. 3 3
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysConfigController.java
  31. 2 2
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDeptController.java
  32. 2 2
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictDataController.java
  33. 3 3
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictTypeController.java
  34. 1 1
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java
  35. 2 2
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysMenuController.java
  36. 2 2
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysNoticeController.java
  37. 2 2
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysPostController.java
  38. 22 26
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java
  39. 7 7
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java
  40. 44 9
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java
  41. 100 0
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/UpdateAppController.java
  42. 2 2
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/TestController.java
  43. 41 0
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/webOffice/ConsoleController.java
  44. 15 2
      ruoyi-admin/src/main/resources/application-druid.yml
  45. 12 5
      ruoyi-admin/src/main/resources/application-prod.yml
  46. 3 1
      ruoyi-admin/src/main/resources/application.yml
  47. 25 0
      ruoyi-admin/src/main/resources/docx4j.properties
  48. BIN
      ruoyi-admin/src/main/resources/traineddata/chi_sim.traineddata
  49. 124 8
      ruoyi-common/pom.xml
  50. 11 0
      ruoyi-common/src/main/java/com/ruoyi/common/config/RuoYiConfig.java
  51. 18 0
      ruoyi-common/src/main/java/com/ruoyi/common/constant/CommonConstants.java
  52. 1 1
      ruoyi-common/src/main/java/com/ruoyi/common/constant/UserConstants.java
  53. 71 0
      ruoyi-common/src/main/java/com/ruoyi/common/core/domain/IdCardVo.java
  54. 203 0
      ruoyi-common/src/main/java/com/ruoyi/common/core/domain/SysUserIdcardVo.java
  55. 8 0
      ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeSelect.java
  56. 138 0
      ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/IndustryCategory.java
  57. 35 0
      ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java
  58. 13 0
      ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginBody.java
  59. 13 0
      ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/RegisterBody.java
  60. 28 0
      ruoyi-common/src/main/java/com/ruoyi/common/encoder/AesPasswordEncoder.java
  61. 64 0
      ruoyi-common/src/main/java/com/ruoyi/common/enums/FjType.java
  62. 206 0
      ruoyi-common/src/main/java/com/ruoyi/common/utils/AesUtil.java
  63. 65 0
      ruoyi-common/src/main/java/com/ruoyi/common/utils/Base64Util.java
  64. 114 5
      ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java
  65. 72 0
      ruoyi-common/src/main/java/com/ruoyi/common/utils/FileUtil.java
  66. 77 0
      ruoyi-common/src/main/java/com/ruoyi/common/utils/HttpUtil.java
  67. 77 0
      ruoyi-common/src/main/java/com/ruoyi/common/utils/HttpUtils.java
  68. 1478 0
      ruoyi-common/src/main/java/com/ruoyi/common/utils/IdCardUtil.java
  69. 100 0
      ruoyi-common/src/main/java/com/ruoyi/common/utils/ImageSizeUtil.java
  70. 260 0
      ruoyi-common/src/main/java/com/ruoyi/common/utils/QRCodeUtils.java
  71. 11 4
      ruoyi-common/src/main/java/com/ruoyi/common/utils/SecurityUtils.java
  72. 133 0
      ruoyi-common/src/main/java/com/ruoyi/common/utils/SendSmsUtils.java
  73. 53 6
      ruoyi-common/src/main/java/com/ruoyi/common/utils/StringUtils.java
  74. 86 0
      ruoyi-common/src/main/java/com/ruoyi/common/utils/Text2PdfUtil.java
  75. 553 0
      ruoyi-common/src/main/java/com/ruoyi/common/utils/ThumbnailUtil.java
  76. 224 0
      ruoyi-common/src/main/java/com/ruoyi/common/utils/WordUtil.java
  77. 243 71
      ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java
  78. 3 1
      ruoyi-common/src/main/java/com/ruoyi/common/utils/file/MimeTypeUtils.java
  79. 80 0
      ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java
  80. 140 0
      ruoyi-common/src/main/java/com/ruoyi/common/utils/jPush/AbstractJPushToolUtil.java
  81. 62 0
      ruoyi-common/src/main/java/com/ruoyi/common/utils/jPush/JPushConfig.java
  82. 37 0
      ruoyi-common/src/main/java/com/ruoyi/common/utils/jPush/JPushToolUtil.java
  83. 51 0
      ruoyi-common/src/main/java/com/ruoyi/common/utils/jPush/JPushVO.java
  84. 228 0
      ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelFillUtils.java
  85. 87 0
      ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/FileUtils.java
  86. 100 0
      ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/WordUtil.java
  87. BIN
      ruoyi-common/src/main/java/resources/word/zdd.docx
  88. 12 0
      ruoyi-framework/pom.xml
  89. 18 2
      ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java
  90. 384 25
      ruoyi-framework/src/main/java/com/ruoyi/framework/manager/factory/AsyncFactory.java
  91. 2503 0
      ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/LoanApplicationServiceImpl.java
  92. 62 45
      ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java
  93. 58 45
      ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysRegisterService.java
  94. 4 0
      ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/TokenService.java
  95. 2 2
      ruoyi-generator/src/main/java/com/ruoyi/generator/controller/GenController.java
  96. 1 1
      ruoyi-generator/src/main/resources/generator.yml
  97. 1 0
      ruoyi-generator/src/main/resources/vm/xml/mapper.xml.vm
  98. 4 4
      ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobController.java
  99. 2 2
      ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobLogController.java
  100. 32 0
      ruoyi-system/pom.xml

+ 5 - 5
pom.xml

@@ -2,8 +2,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">
-	<modelVersion>4.0.0</modelVersion>
-	
+    <modelVersion>4.0.0</modelVersion>
+
     <groupId>com.ruoyi</groupId>
     <artifactId>ruoyi</artifactId>
     <version>3.8.7</version>
@@ -11,7 +11,7 @@
     <name>ruoyi</name>
     <url>http://www.ruoyi.vip</url>
     <description>若依管理系统</description>
-    
+
     <properties>
         <ruoyi.version>3.8.7</ruoyi.version>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
@@ -27,7 +27,8 @@
         <fastjson.version>2.0.43</fastjson.version>
         <oshi.version>6.5.0</oshi.version>
         <commons.io.version>2.13.0</commons.io.version>
-        <poi.version>4.1.2</poi.version>
+        <!-- <poi.version>4.1.2</poi.version>-->
+        <poi.version>5.2.3</poi.version>
         <velocity.version>2.3</velocity.version>
         <jwt.version>0.9.1</jwt.version>
     </properties>
@@ -171,7 +172,6 @@
                 <artifactId>ruoyi-common</artifactId>
                 <version>${ruoyi.version}</version>
             </dependency>
-
         </dependencies>
     </dependencyManagement>
 

+ 26 - 4
ruoyi-admin/pom.xml

@@ -9,14 +9,13 @@
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <packaging>jar</packaging>
-    <artifactId>ruoyi-admin</artifactId>
+    <artifactId>rongzidanbao</artifactId>
 
     <description>
         web服务入口
     </description>
 
     <dependencies>
-
         <!-- spring-boot-devtools -->
         <dependency>
             <groupId>org.springframework.boot</groupId>
@@ -61,6 +60,29 @@
             <artifactId>ruoyi-generator</artifactId>
         </dependency>
 
+        <dependency>
+            <groupId>com.zhuozhengsoft</groupId>
+            <artifactId>pageoffice</artifactId>
+            <version>6.1.0.2-javax</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.qiniu</groupId>
+            <artifactId>qiniu-java-sdk</artifactId>
+            <version>7.15.0</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi-scratchpad</artifactId>
+            <version>5.2.3</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.pdfbox</groupId>
+            <artifactId>pdfbox</artifactId>
+            <version>2.0.24</version>
+        </dependency>
     </dependencies>
 
     <build>
@@ -87,8 +109,8 @@
                 <configuration>
                     <failOnMissingWebXml>false</failOnMissingWebXml>
                     <warName>${project.artifactId}</warName>
-                </configuration>   
-           </plugin>   
+                </configuration>
+           </plugin>
         </plugins>
         <finalName>${project.artifactId}</finalName>
     </build>

+ 5 - 0
ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java

@@ -3,12 +3,17 @@ package com.ruoyi;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.data.map.repository.config.EnableMapRepositories;
+import org.springframework.scheduling.annotation.EnableAsync;
+import org.springframework.scheduling.annotation.EnableScheduling;
 
 /**
  * 启动程序
  * 
  * @author ruoyi
  */
+@EnableAsync
+@EnableScheduling
 @SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
 public class RuoYiApplication
 {

+ 113 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/controller/banner/BannerController.java

@@ -0,0 +1,113 @@
+package com.ruoyi.web.controller.banner;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.system.domain.banner.Banner;
+import com.ruoyi.system.service.banner.IBannerService;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.core.page.TableDataInfo;
+
+/**
+ * 轮播图Controller
+ * 
+ * @author boman
+ * @date 2024-01-22
+ */
+@RestController
+@RequestMapping("/banner")
+public class BannerController extends BaseController
+{
+    @Autowired
+    private IBannerService bannerService;
+
+    /**
+     * 查询轮播图列表
+     */
+    @PreAuthorize("@ss.hasPermi('banner:banner:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(Banner banner)
+    {
+        startPage();
+        List<Banner> list = bannerService.selectBannerList(banner);
+        return getDataTable(list);
+    }
+
+    /**
+     * 查询轮播图列表不分页
+     */
+    @GetMapping("/listNoPage")
+    public TableDataInfo listNoPage(Banner banner)
+    {
+        List<Banner> list = bannerService.selectBannerList(banner);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出轮播图列表
+     */
+    @PreAuthorize("@ss.hasPermi('banner:banner:export')")
+    @Log(title = "轮播图", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, Banner banner)
+    {
+        List<Banner> list = bannerService.selectBannerList(banner);
+        ExcelUtil<Banner> util = new ExcelUtil<Banner>(Banner.class);
+        util.exportExcel(response, list, "轮播图数据");
+    }
+
+    /**
+     * 获取轮播图详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('banner:banner:query')")
+    @GetMapping(value = "/{bannerId}")
+    public AjaxResult getInfo(@PathVariable("bannerId") Long bannerId)
+    {
+        return success(bannerService.selectBannerByBannerId(bannerId));
+    }
+
+    /**
+     * 新增轮播图
+     */
+    @PreAuthorize("@ss.hasPermi('banner:banner:add')")
+    @Log(title = "轮播图", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody Banner banner)
+    {
+        return toAjax(bannerService.insertBanner(banner));
+    }
+
+    /**
+     * 修改轮播图
+     */
+    @PreAuthorize("@ss.hasPermi('banner:banner:edit')")
+    @Log(title = "轮播图", businessType = BusinessType.UPDATE)
+    @PostMapping("/put")
+    public AjaxResult edit(@RequestBody Banner banner)
+    {
+        return toAjax(bannerService.updateBanner(banner));
+    }
+
+    /**
+     * 删除轮播图
+     */
+    @PreAuthorize("@ss.hasPermi('banner:banner:remove')")
+    @Log(title = "轮播图", businessType = BusinessType.DELETE)
+	@GetMapping("/delete/{bannerIds}")
+    public AjaxResult remove(@PathVariable Long[] bannerIds)
+    {
+        return toAjax(bannerService.deleteBannerByBannerIds(bannerIds));
+    }
+}

+ 125 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/controller/category/IndustryCategoryController.java

@@ -0,0 +1,125 @@
+package com.ruoyi.web.controller.category;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+
+import com.ruoyi.common.utils.StringUtils;
+import org.apache.commons.lang3.ArrayUtils;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.core.domain.entity.IndustryCategory;
+import com.ruoyi.system.service.IIndustryCategoryService;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.common.core.page.TableDataInfo;
+
+/**
+ * 行业类别Controller
+ *
+ * @author ruoyi
+ * @date 2024-04-23
+ */
+@RestController
+@RequestMapping("/system/category")
+public class IndustryCategoryController extends BaseController
+{
+    @Autowired
+    private IIndustryCategoryService industryCategoryService;
+
+    /**
+     * 查询行业类别列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:category:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(IndustryCategory industryCategory)
+    {
+        //startPage();
+        List<IndustryCategory> list = industryCategoryService.selectIndustryCategoryList(industryCategory);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出行业类别列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:category:export')")
+    @Log(title = "行业类别", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, IndustryCategory industryCategory)
+    {
+        List<IndustryCategory> list = industryCategoryService.selectIndustryCategoryList(industryCategory);
+        ExcelUtil<IndustryCategory> util = new ExcelUtil<IndustryCategory>(IndustryCategory.class);
+        util.exportExcel(response, list, "行业类别数据");
+    }
+
+    /**
+     * 获取行业类别详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('system:category:query')")
+    @GetMapping(value = "/{categoryId}")
+    public AjaxResult getInfo(@PathVariable("categoryId") Long categoryId)
+    {
+        return success(industryCategoryService.selectIndustryCategoryByCategoryId(categoryId));
+    }
+
+    /**
+     * 新增行业类别
+     */
+    @PreAuthorize("@ss.hasPermi('system:category:add')")
+    @Log(title = "行业类别", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody IndustryCategory industryCategory)
+    {
+        return toAjax(industryCategoryService.insertIndustryCategory(industryCategory));
+    }
+
+    /**
+     * 修改行业类别
+     */
+    @PreAuthorize("@ss.hasPermi('system:category:edit')")
+    @Log(title = "行业类别", businessType = BusinessType.UPDATE)
+    @PostMapping("/put")
+    public AjaxResult edit(@RequestBody IndustryCategory industryCategory)
+    {
+        return toAjax(industryCategoryService.updateIndustryCategory(industryCategory));
+    }
+
+    /**
+     * 删除行业类别
+     */
+    @PreAuthorize("@ss.hasPermi('system:category:remove')")
+    @Log(title = "行业类别", businessType = BusinessType.DELETE)
+    @GetMapping("/delete/{categoryIds}")
+    public AjaxResult remove(@PathVariable Long[] categoryIds)
+    {
+        return toAjax(industryCategoryService.deleteIndustryCategoryByCategoryIds(categoryIds));
+    }
+
+    /**
+     * 获取行业类别树列表
+     */
+    @GetMapping("/categoryTree")
+    public AjaxResult categoryTree(IndustryCategory industryCategory)
+    {
+        return success(industryCategoryService.selectCategoryTreeList(industryCategory));
+    }
+
+    /**
+     * 查询行业类别列表(排除节点)
+     */
+    @GetMapping("/list/exclude/{categoryId}")
+    public AjaxResult excludeChild(@PathVariable(value = "categoryId", required = false) Long categoryId)
+    {
+        List<IndustryCategory> list = industryCategoryService.selectIndustryCategoryList(new IndustryCategory());
+        list.removeIf(d -> d.getCategoryId().intValue() == categoryId || ArrayUtils.contains(StringUtils.split(d.getAncestors(), ","), categoryId + ""));
+        return success(list);
+    }
+}

+ 79 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/AppletController.java

@@ -0,0 +1,79 @@
+package com.ruoyi.web.controller.common;
+
+
+
+import com.ruoyi.common.annotation.RepeatSubmit;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.core.redis.RedisCache;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.common.utils.SendSmsUtils;
+import com.ruoyi.system.service.ISysUserService;
+import org.apache.commons.lang3.ObjectUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import java.util.concurrent.TimeUnit;
+
+import static com.ruoyi.common.constant.CommonConstants.ONE;
+
+/**小程序公共接口
+ * @Author: tjf
+ * @Date: 2023/5/25 11:46
+ * @Describe:
+ */
+@RestController
+@RequestMapping("/applet")
+public class AppletController extends BaseController {
+    @Autowired
+    private ISysUserService userService;
+    @Resource
+    private RedisCache redisCache;
+
+
+    /**
+     *忘记密码发送验证短信
+     */
+    @RepeatSubmit(interval = 1000,message = "请求过于频繁")
+    @GetMapping("/appForgetPW/{phone}")
+    public AjaxResult appForgetPW(@PathVariable String phone)
+    {
+        SysUser sysUser = userService.selectUserByPhonenumber(phone);
+        if (sysUser == null || sysUser.getUserId() == null){
+            return  AjaxResult.error("当前手机号系统内不存在,无法修改密码");
+        }
+        String code = SendSmsUtils.getCode(4);
+        SendSmsUtils.sendSms(phone,"SMS_219525380","{\"code\":\"" + code + "\"}");
+        String key = "SMS_CODE:"+phone;
+        redisCache.setCacheObject(key,code, 5,TimeUnit.MINUTES);
+        return  AjaxResult.success(code);
+    }
+    /**
+     *忘记密码校验验证码,修改密码
+     */
+
+    @GetMapping("/appCheck")
+    public AjaxResult appCheck(@RequestParam("code") String code, @RequestParam("phone") String phone, @RequestParam("password") String password)
+    {
+        String key = "SMS_CODE:"+phone;
+        Object cacheObject = redisCache.getCacheObject(key);
+        if (ObjectUtils.isNotEmpty(cacheObject)){
+            if (code.equals(String.valueOf(cacheObject))){
+                redisCache.deleteObject(key);
+                SysUser user = new SysUser();
+                user.setPassword(password);
+               //修改密码
+                if (ONE.equals(userService.checkStrongPwd(user))) {
+                    return AjaxResult.error("密码必须包含数字、大小写字母、特殊符号且大于8位");
+                }
+                user.setPhonenumber(phone);
+                user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
+                return toAjax(userService.resetUserPwdByPhonenumber(user));
+            }
+        }
+        return  AjaxResult.error();
+    }
+
+}

+ 136 - 44
ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java

@@ -1,17 +1,32 @@
 package com.ruoyi.web.controller.common;
 
+import java.io.File;
+import java.time.temporal.TemporalUnit;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+
+import com.alibaba.fastjson2.JSONArray;
+import com.alibaba.fastjson2.JSONObject;
+import com.ruoyi.common.utils.IdCardUtil;
+import com.ruoyi.common.utils.ImageSizeUtil;
+import com.ruoyi.common.utils.ThumbnailUtil;
+import com.ruoyi.system.domain.vo.UploadVo;
+import net.lingala.zip4j.ZipFile;
+import net.lingala.zip4j.exception.ZipException;
+import net.lingala.zip4j.model.ZipParameters;
+import net.lingala.zip4j.model.enums.EncryptionMethod;
+import net.sourceforge.tess4j.ITesseract;
+import net.sourceforge.tess4j.Tesseract;
+import net.sourceforge.tess4j.TesseractException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.MediaType;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
 import com.ruoyi.common.config.RuoYiConfig;
 import com.ruoyi.common.constant.Constants;
@@ -23,13 +38,12 @@ import com.ruoyi.framework.config.ServerConfig;
 
 /**
  * 通用请求处理
- * 
+ *
  * @author ruoyi
  */
 @RestController
 @RequestMapping("/common")
-public class CommonController
-{
+public class CommonController {
     private static final Logger log = LoggerFactory.getLogger(CommonController.class);
 
     @Autowired
@@ -39,17 +53,14 @@ public class CommonController
 
     /**
      * 通用下载请求
-     * 
+     *
      * @param fileName 文件名称
-     * @param delete 是否删除
+     * @param delete   是否删除
      */
     @GetMapping("/download")
-    public void fileDownload(String fileName, Boolean delete, HttpServletResponse response, HttpServletRequest request)
-    {
-        try
-        {
-            if (!FileUtils.checkAllowDownload(fileName))
-            {
+    public void fileDownload(String fileName, Boolean delete, HttpServletResponse response, HttpServletRequest request) {
+        try {
+            if (!FileUtils.checkAllowDownload(fileName)) {
                 throw new Exception(StringUtils.format("文件名称({})非法,不允许下载。 ", fileName));
             }
             String realFileName = System.currentTimeMillis() + fileName.substring(fileName.indexOf("_") + 1);
@@ -58,13 +69,10 @@ public class CommonController
             response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
             FileUtils.setAttachmentResponseHeader(response, realFileName);
             FileUtils.writeBytes(filePath, response.getOutputStream());
-            if (delete)
-            {
+            if (delete) {
                 FileUtils.deleteFile(filePath);
             }
-        }
-        catch (Exception e)
-        {
+        } catch (Exception e) {
             log.error("下载文件失败", e);
         }
     }
@@ -73,24 +81,116 @@ public class CommonController
      * 通用上传请求(单个)
      */
     @PostMapping("/upload")
-    public AjaxResult uploadFile(MultipartFile file) throws Exception
-    {
-        try
-        {
+    public AjaxResult uploadFile(MultipartFile file) throws Exception {
+        try {
+            String extension = FileUploadUtils.getExtension(file);
+            if("bmp".equals(extension) || "gif".equals(extension) || "jpg".equals(extension) || "jpeg".equals(extension) || "png".equals(extension)){
+                //压缩图片
+                MultipartFile multipartFileCorrection = ImageSizeUtil.compressImg(file);
+                //矫正
+                file = FileUploadUtils.imageCorrection(multipartFileCorrection);
+                if (file == null){
+                    return AjaxResult.error("图片不合规");
+                }
+            }
             // 上传文件路径
             String filePath = RuoYiConfig.getUploadPath();
             // 上传并返回新文件名称
             String fileName = FileUploadUtils.upload(filePath, file);
             String url = serverConfig.getUrl() + fileName;
+            //服务器路径
+            String urlOnline = filePath + fileName.replace("/profile/upload", "");
+            AjaxResult ajax = AjaxResult.success();
+            ajax.put("url", url);
+            ajax.put("urlOnline", urlOnline);
+            ajax.put("fileName", fileName);
+            ajax.put("newFileName", FileUtils.getName(fileName));
+            ajax.put("originalFilename", file.getOriginalFilename());
+            return ajax;
+        } catch (Exception e) {
+            return AjaxResult.error(e.getMessage());
+        }
+    }
+
+    /**
+     * 按照项目编号创建文件夹通用上传请求(单个)
+     */
+    @PostMapping("/uploadNew")
+    public AjaxResult uploadNewFile(@RequestParam("file") MultipartFile file, @RequestParam("loanApplicationNumber") String loanApplicationNumber, @RequestParam("fileName") String originalFilename) throws Exception {
+        try {
+            String extension = FileUploadUtils.getExtension(file);
+            if("bmp".equals(extension) || "gif".equals(extension) || "jpg".equals(extension) || "jpeg".equals(extension) || "png".equals(extension)){
+                //压缩图片
+                MultipartFile multipartFileCorrection = ImageSizeUtil.compressImg(file);
+                //矫正
+                file = FileUploadUtils.imageCorrection(multipartFileCorrection);
+                if (file == null){
+                    return AjaxResult.error("图片不合规");
+                }
+            }
+
+
+            // 上传文件路径
+            String filePath = RuoYiConfig.getUploadPath();
+            if ("其他附件".equals(originalFilename)) {
+                originalFilename = file.getOriginalFilename();
+            }
+            // 上传并返回新文件名称
+            String fileName = FileUploadUtils.uploadLoanApplicationNumber(filePath, file, loanApplicationNumber, originalFilename);
+            String url = serverConfig.getUrl() + fileName;
             AjaxResult ajax = AjaxResult.success();
+            //服务器路径
+            String urlOnline = filePath + fileName.replace("/profile/upload", "");
             ajax.put("url", url);
+            ajax.put("urlOnline", urlOnline);
             ajax.put("fileName", fileName);
             ajax.put("newFileName", FileUtils.getName(fileName));
             ajax.put("originalFilename", file.getOriginalFilename());
             return ajax;
+        } catch (Exception e) {
+            return AjaxResult.error(e.getMessage());
         }
-        catch (Exception e)
-        {
+    }
+
+    /**
+     * 按照项目编号创建文件夹通用上传请求(单个)带识别图片转文字
+     */
+    @PostMapping("/uploadNewOcr")
+    @PreAuthorize("@ss.hasPermi('common:upload:uploadNewOcr')")
+    public AjaxResult uploadNewOcrFile(@RequestParam("file") MultipartFile file, @RequestParam("loanApplicationNumber") String loanApplicationNumber, @RequestParam("fileName") String originalFilename) throws Exception {
+        try {
+            String extension = FileUploadUtils.getExtension(file);
+            if("bmp".equals(extension) || "gif".equals(extension) || "jpg".equals(extension) || "jpeg".equals(extension) || "png".equals(extension)){
+                //压缩图片
+                MultipartFile multipartFileCorrection = ImageSizeUtil.compressImg(file);
+                //矫正
+                file = FileUploadUtils.imageCorrection(multipartFileCorrection);
+                if (file == null){
+                    return AjaxResult.error("图片不合规");
+                }
+            }
+            // 上传文件路径
+            String filePath = RuoYiConfig.getUploadPath();
+            // 上传并返回新文件名称
+            String fileName = FileUploadUtils.uploadLoanApplicationNumber(filePath, file, loanApplicationNumber, originalFilename);
+            String url = serverConfig.getUrl() + fileName;
+            AjaxResult ajax = AjaxResult.success();
+            //服务器路径
+            String urlOnline = filePath + fileName.replace("/profile/upload", "");
+            //百度图片识别
+            Map<String, Object> map = IdCardUtil.accurateBasic(urlOnline);
+            if (map == null || map.size() == 0) {
+                return AjaxResult.error("当前图片不是借据或者无法识别");
+            }
+            ajax.put("url", url);
+            ajax.put("urlOnline", urlOnline);
+            ajax.put("fileName", fileName);
+            ajax.put("newFileName", FileUtils.getName(fileName));
+            ajax.put("originalFilename", file.getOriginalFilename());
+            ajax.put("actuallyAmount", map.get("actuallyAmount"));
+            ajax.put("actuallyTime", map.get("actuallyTime"));
+            return ajax;
+        } catch (Exception e) {
             return AjaxResult.error(e.getMessage());
         }
     }
@@ -99,18 +199,15 @@ public class CommonController
      * 通用上传请求(多个)
      */
     @PostMapping("/uploads")
-    public AjaxResult uploadFiles(List<MultipartFile> files) throws Exception
-    {
-        try
-        {
+    public AjaxResult uploadFiles(List<MultipartFile> files) throws Exception {
+        try {
             // 上传文件路径
             String filePath = RuoYiConfig.getUploadPath();
             List<String> urls = new ArrayList<String>();
             List<String> fileNames = new ArrayList<String>();
             List<String> newFileNames = new ArrayList<String>();
             List<String> originalFilenames = new ArrayList<String>();
-            for (MultipartFile file : files)
-            {
+            for (MultipartFile file : files) {
                 // 上传并返回新文件名称
                 String fileName = FileUploadUtils.upload(filePath, file);
                 String url = serverConfig.getUrl() + fileName;
@@ -125,9 +222,7 @@ public class CommonController
             ajax.put("newFileNames", StringUtils.join(newFileNames, FILE_DELIMETER));
             ajax.put("originalFilenames", StringUtils.join(originalFilenames, FILE_DELIMETER));
             return ajax;
-        }
-        catch (Exception e)
-        {
+        } catch (Exception e) {
             return AjaxResult.error(e.getMessage());
         }
     }
@@ -137,12 +232,9 @@ public class CommonController
      */
     @GetMapping("/download/resource")
     public void resourceDownload(String resource, HttpServletRequest request, HttpServletResponse response)
-            throws Exception
-    {
-        try
-        {
-            if (!FileUtils.checkAllowDownload(resource))
-            {
+            throws Exception {
+        try {
+            if (!FileUtils.checkAllowDownload(resource)) {
                 throw new Exception(StringUtils.format("资源文件({})非法,不允许下载。 ", resource));
             }
             // 本地资源路径
@@ -154,10 +246,10 @@ public class CommonController
             response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
             FileUtils.setAttachmentResponseHeader(response, downloadName);
             FileUtils.writeBytes(downloadPath, response.getOutputStream());
-        }
-        catch (Exception e)
-        {
+        } catch (Exception e) {
             log.error("下载文件失败", e);
         }
     }
+
+
 }

+ 82 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/OcrController.java

@@ -0,0 +1,82 @@
+package com.ruoyi.web.controller.common;
+
+
+import com.ruoyi.common.annotation.RepeatSubmit;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.domain.IdCardVo;
+import com.ruoyi.common.core.domain.SysUserIdcardVo;
+import com.ruoyi.common.utils.IdCardUtil;
+import com.ruoyi.system.domain.idcard.SysUserIdcard;
+import net.sourceforge.tess4j.ITesseract;
+import net.sourceforge.tess4j.Tesseract;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.io.File;
+
+/**
+ * @Author: tjf
+ * @Date: 2024/4/22 14:24
+ * @Describe:
+ */
+@RestController
+@RequestMapping("/ocr")
+public class OcrController {
+    /**
+     * 身份证识别
+     *
+     * @return
+     */
+    @PostMapping("/ocrIdCard")
+    @RepeatSubmit(interval = 1000, message = "请求过于频繁")
+    public AjaxResult ocrIdCard(@RequestBody IdCardVo idCardVo) {
+        return IdCardUtil.idCard(idCardVo.getImage(),idCardVo.getIdCardSide());
+    }
+
+    /**
+     * 营业执照识别
+     *
+     * @return
+     */
+    @PostMapping("/ocrBusinessLicense")
+    @RepeatSubmit(interval = 1000, message = "请求过于频繁")
+    public AjaxResult ocrBusinessLicense(@RequestBody IdCardVo idCardVo) {
+        return IdCardUtil.businessLicense(idCardVo.getImage());
+    }
+
+    /**
+     * 人脸识别百度V4版本
+     *
+     * @return
+     */
+    @PostMapping("/ocrSample")
+    @RepeatSubmit(interval = 1000, message = "请求过于频繁")
+    public AjaxResult ocrSample(@RequestBody SysUserIdcardVo sysUserIdcardVo) {
+        return IdCardUtil.sample(sysUserIdcardVo);
+    }
+
+    /**
+     * 人脸识别阿里云金融级实人认证
+     *
+     * @return
+     */
+    @PostMapping("/ocrSampleAliYun")
+    @RepeatSubmit(interval = 1000, message = "请求过于频繁")
+    public AjaxResult ocrSampleAliYun(@RequestBody SysUserIdcardVo sysUserIdcardVo) {
+        return IdCardUtil.ocrSampleAliYun(sysUserIdcardVo);
+    }
+
+    /**
+     * 手写识别
+     *
+     * @return
+     */
+    @PostMapping("/ocrHandWriting")
+    @RepeatSubmit(interval = 1000, message = "请求过于频繁")
+    public AjaxResult ocrHandWriting(@RequestBody IdCardVo idCardVo) {
+        return IdCardUtil.ocrHandWriting(idCardVo.getImage());
+    }
+
+}

+ 69 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/SendSmsController.java

@@ -0,0 +1,69 @@
+package com.ruoyi.web.controller.common;
+
+import com.ruoyi.common.annotation.RepeatSubmit;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.core.domain.model.LoginBody;
+import com.ruoyi.common.core.redis.RedisCache;
+import com.ruoyi.common.utils.SendSmsUtils;
+import com.ruoyi.system.service.ISysUserService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.concurrent.TimeUnit;
+
+import static com.ruoyi.common.constant.CommonConstants.LOGIN_USER_SMS;
+
+
+/**
+ * @Author: tjf
+ * @Date: 2024/03/05 17:15
+ * @Describe:
+ */
+@RestController
+@RequestMapping("/sendSms")
+public class SendSmsController {
+    @Autowired
+    private RedisCache redisCache;
+    @Autowired
+    private ISysUserService sysUserService;
+
+    /**
+     * 发送登录短信接口
+     *
+     * @return
+     */
+    @PostMapping("/sendLoginSms")
+    @RepeatSubmit(interval = 1000, message = "请求过于频繁")
+    public AjaxResult sendLoginSms(@RequestBody LoginBody user) {
+        String code = SendSmsUtils.getCode(4);
+        String username = user.getUsername();
+        SysUser sysUser = sysUserService.selectUserByPhonenumber(username);
+        if (sysUser != null) {
+            redisCache.setCacheObject(LOGIN_USER_SMS + username, code, 5, TimeUnit.MINUTES);
+            String msg = SendSmsUtils.sendPassword(code, username);
+            System.out.println(username + "登录短信发送回复:" + msg);
+            return AjaxResult.success();
+        }
+        return AjaxResult.error("当前手机号不存在");
+    }
+
+    /**
+     * 发送注册短信接口
+     *
+     * @return
+     */
+    @PostMapping("/sendRegisterSms")
+    @RepeatSubmit(interval = 1000, message = "请求过于频繁")
+    public AjaxResult sendRegisterSms(@RequestBody LoginBody user) {
+        String code = SendSmsUtils.getCode(4);
+        String username = user.getUsername();
+        redisCache.setCacheObject(LOGIN_USER_SMS + username, code, 5, TimeUnit.MINUTES);
+        String msg = SendSmsUtils.sendPassword(code, username);
+        System.out.println(username + "登录短信发送回复:" + msg);
+        return AjaxResult.success(msg);
+    }
+}

+ 58 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/WordController.java

@@ -0,0 +1,58 @@
+package com.ruoyi.web.controller.common;
+
+import com.ruoyi.common.annotation.RepeatSubmit;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.domain.model.LoginBody;
+import com.ruoyi.common.utils.SendSmsUtils;
+import com.ruoyi.common.utils.WordUtil;
+import com.ruoyi.system.domain.vo.WordVo;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import org.xlsx4j.sml.Worksheet;
+
+import java.util.concurrent.TimeUnit;
+
+import static com.ruoyi.common.constant.CommonConstants.LOGIN_USER_SMS;
+
+/**
+ * @Author: tjf
+ * @Date: 2024/5/15 10:35
+ * @Describe:
+ */
+@RestController
+@RequestMapping("/word")
+public class WordController {
+    /**
+     * word文档签名
+     *
+     * @return
+     */
+    @PostMapping("/wordFilePath")
+    @PreAuthorize("@ss.hasPermi('word:wordFilePath:wordFilePath')")
+    @RepeatSubmit(interval = 1000, message = "请求过于频繁")
+    public AjaxResult wordFilePath(@RequestBody WordVo wordVo) {
+        String wordFilePath = wordVo.getWordFilePath();
+        String image = wordVo.getImage();
+        AjaxResult ajaxResult = WordUtil.wordFilePath(wordFilePath, image);
+        return ajaxResult;
+    }
+
+    /**
+     * Excel文档签名
+     *
+     * @return
+     */
+    @PostMapping("/excelFilePath")
+    @PreAuthorize("@ss.hasPermi('word:excelFilePath:excelFilePath')")
+    @RepeatSubmit(interval = 1000, message = "请求过于频繁")
+    public AjaxResult excelFilePath(@RequestBody WordVo wordVo) {
+        //excel表格位置
+        String excelFilePath = wordVo.getWordFilePath();
+        //图片
+        String image = wordVo.getImage();
+        return AjaxResult.success();
+    }
+}

+ 158 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/controller/conference/SysUserConferenceController.java

@@ -0,0 +1,158 @@
+package com.ruoyi.web.controller.conference;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+
+import com.ruoyi.system.domain.conference.SysUserConference;
+import com.ruoyi.system.service.conference.ISysUserConferenceService;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.common.core.page.TableDataInfo;
+
+/**
+ * 参会人员Controller
+ *
+ * @author boman
+ * @date 2024-05-06
+ */
+@RestController
+@RequestMapping("/conference")
+public class SysUserConferenceController extends BaseController {
+    @Autowired
+    private ISysUserConferenceService sysUserConferenceService;
+
+    /**
+     * 查询参会人员列表
+     */
+    @PreAuthorize("@ss.hasPermi('c:conference:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(SysUserConference sysUserConference) {
+        startPage();
+        List<SysUserConference> list = sysUserConferenceService.selectSysUserConferenceList(sysUserConference);
+        return getDataTable(list);
+    }
+
+    /**
+     * 按照时间分组
+     */
+    @PreAuthorize("@ss.hasPermi('c:conference:list:time')")
+    @GetMapping("/app/time/list")
+    public AjaxResult timeTist(SysUserConference sysUserConference) {
+        return sysUserConferenceService.timeTist(sysUserConference);
+    }
+
+    /**
+     * 按照时间分组
+     */
+    @PreAuthorize("@ss.hasPermi('c:conference:list:time')")
+    @GetMapping("/pc/time/list")
+    public AjaxResult pcTimeTist(SysUserConference sysUserConference) {
+        return sysUserConferenceService.pcTimeTist(sysUserConference);
+    }
+
+
+    /**
+     * 导出参会人员列表
+     */
+    @PreAuthorize("@ss.hasPermi('c:conference:export')")
+    @Log(title = "参会人员", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, SysUserConference sysUserConference) {
+        List<SysUserConference> list = sysUserConferenceService.selectSysUserConferenceList(sysUserConference);
+        ExcelUtil<SysUserConference> util = new ExcelUtil<SysUserConference>(SysUserConference.class);
+        util.exportExcel(response, list, "参会人员数据");
+    }
+
+    /**
+     * 获取参会人员详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('c:conference:query')")
+    @GetMapping(value = "/{conferenceId}")
+    public AjaxResult getInfo(@PathVariable("conferenceId") Long conferenceId) {
+        return success(sysUserConferenceService.selectSysUserConferenceByConferenceId(conferenceId));
+    }
+
+    /**
+     * 新增参会人员
+     */
+    @PreAuthorize("@ss.hasPermi('c:conference:add')")
+    @Log(title = "参会人员", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody SysUserConference sysUserConference) {
+        return toAjax(sysUserConferenceService.insertSysUserConference(sysUserConference));
+    }
+
+    /**
+     * 随机生成参会人员
+     * loanApplicationId 贷款id
+     */
+    @PreAuthorize("@ss.hasPermi('c:conference:randomAdd')")
+    @Log(title = "参会人员", businessType = BusinessType.INSERT)
+    @PostMapping(value = "/random/five")
+    public AjaxResult randomAdd(@RequestBody SysUserConference sysUserConference) {
+        return sysUserConferenceService.randomAdd(sysUserConference);
+    }
+
+    /**
+     * 修改参会人员
+     */
+    @PreAuthorize("@ss.hasPermi('c:conference:edit')")
+    @Log(title = "参会人员", businessType = BusinessType.UPDATE)
+    @PostMapping("/put")
+    public AjaxResult edit(@RequestBody SysUserConference sysUserConference) {
+        return toAjax(sysUserConferenceService.updateSysUserConference(sysUserConference));
+    }
+
+    /**
+     * 投票
+     */
+    @PreAuthorize("@ss.hasPermi('c:conference:vote')")
+    @Log(title = "参会人员", businessType = BusinessType.UPDATE)
+    @PostMapping("/vote")
+    public AjaxResult vote(@RequestBody SysUserConference sysUserConference) {
+        return sysUserConferenceService.vote(sysUserConference);
+    }
+
+    /**
+     * 管理员发起重新投票(最新一次的投票人员不变)
+     */
+    @PreAuthorize("@ss.hasPermi('c:conference:again')")
+    @Log(title = "参会人员", businessType = BusinessType.UPDATE)
+    @PostMapping("/again")
+    public AjaxResult again(@RequestBody SysUserConference sysUserConference) {
+        return sysUserConferenceService.again(sysUserConference);
+    }
+
+    /**
+     * 董事长一票否决
+     */
+    @PreAuthorize("@ss.hasPermi('c:conference:finish')")
+    @Log(title = "参会人员", businessType = BusinessType.UPDATE)
+    @PostMapping("/finish")
+    public AjaxResult finish(@RequestBody SysUserConference sysUserConference) {
+        return sysUserConferenceService.finish(sysUserConference);
+    }
+
+    /**
+     * 删除参会人员
+     */
+    @PreAuthorize("@ss.hasPermi('c:conference:remove')")
+    @Log(title = "参会人员", businessType = BusinessType.DELETE)
+    @GetMapping("/delete/{conferenceIds}")
+    public AjaxResult remove(@PathVariable Long[] conferenceIds) {
+        return toAjax(sysUserConferenceService.deleteSysUserConferenceByConferenceIds(conferenceIds));
+    }
+}

+ 103 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/controller/document/ExplainDocumentController.java

@@ -0,0 +1,103 @@
+package com.ruoyi.web.controller.document;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+
+import com.ruoyi.system.domain.document.ExplainDocument;
+import com.ruoyi.system.service.document.IExplainDocumentService;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.common.core.page.TableDataInfo;
+
+/**
+ * 说明文档Controller
+ *
+ * @author boman
+ * @date 2024-04-29
+ */
+@RestController
+@RequestMapping("/document")
+public class ExplainDocumentController extends BaseController
+{
+    @Autowired
+    private IExplainDocumentService explainDocumentService;
+
+/**
+ * 查询说明文档列表
+ */
+@PreAuthorize("@ss.hasPermi('system:document:list')")
+@GetMapping("/list")
+    public TableDataInfo list(ExplainDocument explainDocument)
+    {
+        startPage();
+        List<ExplainDocument> list = explainDocumentService.selectExplainDocumentList(explainDocument);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出说明文档列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:document:export')")
+    @Log(title = "说明文档", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, ExplainDocument explainDocument)
+    {
+        List<ExplainDocument> list = explainDocumentService.selectExplainDocumentList(explainDocument);
+        ExcelUtil<ExplainDocument> util = new ExcelUtil<ExplainDocument>(ExplainDocument.class);
+        util.exportExcel(response, list, "说明文档数据");
+    }
+
+    /**
+     * 获取说明文档详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('system:document:query')")
+    @GetMapping(value = "/{explainId}")
+    public AjaxResult getInfo(@PathVariable("explainId") Integer explainId)
+    {
+        return success(explainDocumentService.selectExplainDocumentByExplainId(explainId));
+    }
+
+    /**
+     * 新增说明文档
+     */
+    @PreAuthorize("@ss.hasPermi('system:document:add')")
+    @Log(title = "说明文档", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody ExplainDocument explainDocument)
+    {
+        return toAjax(explainDocumentService.insertExplainDocument(explainDocument));
+    }
+
+    /**
+     * 修改说明文档
+     */
+    @PreAuthorize("@ss.hasPermi('system:document:edit')")
+    @Log(title = "说明文档", businessType = BusinessType.UPDATE)
+    @PostMapping("/put")
+    public AjaxResult edit(@RequestBody ExplainDocument explainDocument)
+    {
+        return toAjax(explainDocumentService.updateExplainDocument(explainDocument));
+    }
+
+    /**
+     * 删除说明文档
+     */
+    @PreAuthorize("@ss.hasPermi('system:document:remove')")
+    @Log(title = "说明文档", businessType = BusinessType.DELETE)
+    @GetMapping("/delete/{explainIds}")
+    public AjaxResult remove(@PathVariable Integer[] explainIds)
+    {
+        return toAjax(explainDocumentService.deleteExplainDocumentByExplainIds(explainIds));
+    }
+}

+ 128 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/controller/enterprise/SysUserEnterpriseController.java

@@ -0,0 +1,128 @@
+package com.ruoyi.web.controller.enterprise;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.system.domain.enterprise.SysUserEnterprise;
+import com.ruoyi.system.service.enterprise.ISysUserEnterpriseService;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.core.page.TableDataInfo;
+
+/**
+ * 用户企业信息Controller
+ *
+ * @author boman
+ * @date 2024-04-22
+ */
+@RestController
+@RequestMapping("/enterprise")
+public class SysUserEnterpriseController extends BaseController {
+    @Autowired
+    private ISysUserEnterpriseService sysUserEnterpriseService;
+
+    /**
+     * 查询用户企业信息列表
+     */
+    @PreAuthorize("@ss.hasPermi('enterprise:enterprise:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(SysUserEnterprise sysUserEnterprise) {
+        startPage();
+        List<SysUserEnterprise> list = sysUserEnterpriseService.selectSysUserEnterpriseList(sysUserEnterprise);
+        return getDataTable(list);
+    }
+
+    /**
+     * 查询用户企业信息列表
+     */
+    @PreAuthorize("@ss.hasPermi('enterprise:enterprise:listNoPage')")
+    @GetMapping("/listNoPage")
+    public TableDataInfo listNoPage(SysUserEnterprise sysUserEnterprise) {
+        List<SysUserEnterprise> list = sysUserEnterpriseService.selectSysUserEnterpriseList(sysUserEnterprise);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出用户企业信息列表
+     */
+    @PreAuthorize("@ss.hasPermi('enterprise:enterprise:export')")
+    @Log(title = "用户企业信息", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, SysUserEnterprise sysUserEnterprise) {
+        List<SysUserEnterprise> list = sysUserEnterpriseService.selectSysUserEnterpriseList(sysUserEnterprise);
+        ExcelUtil<SysUserEnterprise> util = new ExcelUtil<SysUserEnterprise>(SysUserEnterprise.class);
+        util.exportExcel(response, list, "用户企业信息数据");
+    }
+
+/*    *//**
+     * 获取用户企业信息详细信息
+     *//*
+    @PreAuthorize("@ss.hasPermi('enterprise:enterprise:query')")
+    @GetMapping(value = "/{userId}")
+    public AjaxResult getInfo(@PathVariable("userId") Long userId) {
+        return success(sysUserEnterpriseService.selectSysUserEnterpriseByUserId(userId));
+    }*/
+
+    /**
+     * 获取用户企业信息详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('enterprise:enterprise:query')")
+    @GetMapping(value = "/{enterpriseId}")
+    public AjaxResult getInfo(@PathVariable("enterpriseId") Long enterpriseId) {
+        return success(sysUserEnterpriseService.selectSysUserEnterpriseByEnterpriseId(enterpriseId));
+    }
+
+    /**
+     * 新增用户企业信息
+     */
+    @PreAuthorize("@ss.hasPermi('enterprise:enterprise:add')")
+    @Log(title = "用户企业信息", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody List<SysUserEnterprise> sysUserEnterpriseList) {
+        for (SysUserEnterprise sysUserEnterprise : sysUserEnterpriseList) {
+            return toAjax(sysUserEnterpriseService.insertSysUserEnterprise(sysUserEnterprise));
+        }
+        return AjaxResult.success();
+    }
+
+    /**
+     * 修改用户企业信息
+     */
+    @PreAuthorize("@ss.hasPermi('enterprise:enterprise:edit')")
+    @Log(title = "用户企业信息", businessType = BusinessType.UPDATE)
+    @PostMapping("/put")
+    public AjaxResult edit(@RequestBody SysUserEnterprise sysUserEnterprise) {
+        return toAjax(sysUserEnterpriseService.updateSysUserEnterprise(sysUserEnterprise));
+    }
+
+/*    *//**
+     * 删除用户企业信息
+     *//*
+    @PreAuthorize("@ss.hasPermi('enterprise:enterprise:remove')")
+    @Log(title = "用户企业信息", businessType = BusinessType.DELETE)
+    @GetMapping("/delete/{userIds}")
+    public AjaxResult remove(@PathVariable Long[] userIds) {
+        return toAjax(sysUserEnterpriseService.deleteSysUserEnterpriseByUserIds(userIds));
+    }*/
+
+    /**
+     * 删除用户企业信息
+     */
+    @PreAuthorize("@ss.hasPermi('enterprise:enterprise:remove')")
+    @Log(title = "用户企业信息", businessType = BusinessType.DELETE)
+    @GetMapping("/delete/{enterpriseIds}")
+    public AjaxResult remove(@PathVariable Long[] enterpriseIds) {
+        return toAjax(sysUserEnterpriseService.deleteSysUserEnterpriseByEnterpriseIds(enterpriseIds));
+    }
+}

+ 103 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/controller/guarantee/GuaranteeInfoController.java

@@ -0,0 +1,103 @@
+package com.ruoyi.web.controller.guarantee;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.system.domain.guarantee.GuaranteeInfo;
+import com.ruoyi.system.service.guarantee.IGuaranteeInfoService;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.core.page.TableDataInfo;
+
+/**
+ * 反担保基础信息Controller
+ *
+ * @author boman
+ * @date 2024-08-01
+ */
+@RestController
+@RequestMapping("/guarantee/info")
+public class GuaranteeInfoController extends BaseController
+{
+    @Autowired
+    private IGuaranteeInfoService guaranteeInfoService;
+
+/**
+ * 查询反担保基础信息列表
+ */
+@PreAuthorize("@ss.hasPermi('guarantee:info:list')")
+@GetMapping("/list")
+    public TableDataInfo list(GuaranteeInfo guaranteeInfo)
+    {
+        startPage();
+        List<GuaranteeInfo> list = guaranteeInfoService.selectGuaranteeInfoList(guaranteeInfo);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出反担保基础信息列表
+     */
+    @PreAuthorize("@ss.hasPermi('guarantee:info:export')")
+    @Log(title = "反担保基础信息", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, GuaranteeInfo guaranteeInfo)
+    {
+        List<GuaranteeInfo> list = guaranteeInfoService.selectGuaranteeInfoList(guaranteeInfo);
+        ExcelUtil<GuaranteeInfo> util = new ExcelUtil<GuaranteeInfo>(GuaranteeInfo.class);
+        util.exportExcel(response, list, "反担保基础信息数据");
+    }
+
+    /**
+     * 获取反担保基础信息详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('guarantee:info:query')")
+    @GetMapping(value = "/{guaranteeInfoId}")
+    public AjaxResult getInfo(@PathVariable("guaranteeInfoId") Long guaranteeInfoId)
+    {
+        return success(guaranteeInfoService.selectGuaranteeInfoByGuaranteeInfoId(guaranteeInfoId));
+    }
+
+    /**
+     * 新增反担保基础信息
+     */
+    @PreAuthorize("@ss.hasPermi('guarantee:info:add')")
+    @Log(title = "反担保基础信息", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody GuaranteeInfo guaranteeInfo)
+    {
+        return toAjax(guaranteeInfoService.insertGuaranteeInfo(guaranteeInfo));
+    }
+
+    /**
+     * 修改反担保基础信息
+     */
+    @PreAuthorize("@ss.hasPermi('guarantee:info:edit')")
+    @Log(title = "反担保基础信息", businessType = BusinessType.UPDATE)
+    @PostMapping("/put")
+    public AjaxResult edit(@RequestBody GuaranteeInfo guaranteeInfo)
+    {
+        return toAjax(guaranteeInfoService.updateGuaranteeInfo(guaranteeInfo));
+    }
+
+    /**
+     * 删除反担保基础信息
+     */
+    @PreAuthorize("@ss.hasPermi('guarantee:info:remove')")
+    @Log(title = "反担保基础信息", businessType = BusinessType.DELETE)
+    @GetMapping("/delete/{guaranteeInfoIds}")
+    public AjaxResult remove(@PathVariable Long[] guaranteeInfoIds)
+    {
+        return toAjax(guaranteeInfoService.deleteGuaranteeInfoByGuaranteeInfoIds(guaranteeInfoIds));
+    }
+}

+ 103 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/controller/guarantee/GuaranteeInfoFjController.java

@@ -0,0 +1,103 @@
+package com.ruoyi.web.controller.guarantee;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.system.domain.guarantee.GuaranteeInfoFj;
+import com.ruoyi.system.service.guarantee.IGuaranteeInfoFjService;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.core.page.TableDataInfo;
+
+/**
+ * 反担保基础信息附件Controller
+ *
+ * @author boman
+ * @date 2024-08-01
+ */
+@RestController
+@RequestMapping("/guarantee/fj")
+public class GuaranteeInfoFjController extends BaseController
+{
+    @Autowired
+    private IGuaranteeInfoFjService guaranteeInfoFjService;
+
+/**
+ * 查询反担保基础信息附件列表
+ */
+@PreAuthorize("@ss.hasPermi('guarantee:fj:list')")
+@GetMapping("/list")
+    public TableDataInfo list(GuaranteeInfoFj guaranteeInfoFj)
+    {
+        startPage();
+        List<GuaranteeInfoFj> list = guaranteeInfoFjService.selectGuaranteeInfoFjList(guaranteeInfoFj);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出反担保基础信息附件列表
+     */
+    @PreAuthorize("@ss.hasPermi('guarantee:fj:export')")
+    @Log(title = "反担保基础信息附件", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, GuaranteeInfoFj guaranteeInfoFj)
+    {
+        List<GuaranteeInfoFj> list = guaranteeInfoFjService.selectGuaranteeInfoFjList(guaranteeInfoFj);
+        ExcelUtil<GuaranteeInfoFj> util = new ExcelUtil<GuaranteeInfoFj>(GuaranteeInfoFj.class);
+        util.exportExcel(response, list, "反担保基础信息附件数据");
+    }
+
+    /**
+     * 获取反担保基础信息附件详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('guarantee:fj:query')")
+    @GetMapping(value = "/{guaranteeInfoFjId}")
+    public AjaxResult getInfo(@PathVariable("guaranteeInfoFjId") Long guaranteeInfoFjId)
+    {
+        return success(guaranteeInfoFjService.selectGuaranteeInfoFjByGuaranteeInfoFjId(guaranteeInfoFjId));
+    }
+
+    /**
+     * 新增反担保基础信息附件
+     */
+    @PreAuthorize("@ss.hasPermi('guarantee:fj:add')")
+    @Log(title = "反担保基础信息附件", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody GuaranteeInfoFj guaranteeInfoFj)
+    {
+        return toAjax(guaranteeInfoFjService.insertGuaranteeInfoFj(guaranteeInfoFj));
+    }
+
+    /**
+     * 修改反担保基础信息附件
+     */
+    @PreAuthorize("@ss.hasPermi('guarantee:fj:edit')")
+    @Log(title = "反担保基础信息附件", businessType = BusinessType.UPDATE)
+    @PostMapping("/put")
+    public AjaxResult edit(@RequestBody GuaranteeInfoFj guaranteeInfoFj)
+    {
+        return toAjax(guaranteeInfoFjService.updateGuaranteeInfoFj(guaranteeInfoFj));
+    }
+
+    /**
+     * 删除反担保基础信息附件
+     */
+    @PreAuthorize("@ss.hasPermi('guarantee:fj:remove')")
+    @Log(title = "反担保基础信息附件", businessType = BusinessType.DELETE)
+    @GetMapping("/delete/{guaranteeInfoFjIds}")
+    public AjaxResult remove(@PathVariable Long[] guaranteeInfoFjIds)
+    {
+        return toAjax(guaranteeInfoFjService.deleteGuaranteeInfoFjByGuaranteeInfoFjIds(guaranteeInfoFjIds));
+    }
+}

+ 104 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/controller/hyperlink/HyperlinkController.java

@@ -0,0 +1,104 @@
+package com.ruoyi.web.controller.hyperlink;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.system.domain.Hyperlink;
+import com.ruoyi.system.service.IHyperlinkService;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.common.core.page.TableDataInfo;
+
+/**
+ * 超链接Controller
+ *
+ * @author boman
+ * @date 2024-04-30
+ */
+@RestController
+@RequestMapping("/system/hyperlink")
+public class HyperlinkController extends BaseController
+{
+    @Autowired
+    private IHyperlinkService hyperlinkService;
+
+/**
+ * 查询超链接列表
+ */
+@PreAuthorize("@ss.hasPermi('system:hyperlink:list')")
+@GetMapping("/list")
+    public TableDataInfo list(Hyperlink hyperlink)
+    {
+        startPage();
+        List<Hyperlink> list = hyperlinkService.selectHyperlinkList(hyperlink);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出超链接列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:hyperlink:export')")
+    @Log(title = "超链接", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, Hyperlink hyperlink)
+    {
+        List<Hyperlink> list = hyperlinkService.selectHyperlinkList(hyperlink);
+        ExcelUtil<Hyperlink> util = new ExcelUtil<Hyperlink>(Hyperlink.class);
+        util.exportExcel(response, list, "超链接数据");
+    }
+
+    /**
+     * 获取超链接详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('system:hyperlink:query')")
+    @GetMapping(value = "/{hyperlinkId}")
+    public AjaxResult getInfo(@PathVariable("hyperlinkId") Long hyperlinkId)
+    {
+        return success(hyperlinkService.selectHyperlinkByHyperlinkId(hyperlinkId));
+    }
+
+    /**
+     * 新增超链接
+     */
+    @PreAuthorize("@ss.hasPermi('system:hyperlink:add')")
+    @Log(title = "超链接", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody Hyperlink hyperlink)
+    {
+        return toAjax(hyperlinkService.insertHyperlink(hyperlink));
+    }
+
+    /**
+     * 修改超链接
+     */
+    @PreAuthorize("@ss.hasPermi('system:hyperlink:edit')")
+    @Log(title = "超链接", businessType = BusinessType.UPDATE)
+    @PostMapping("/put")
+    public AjaxResult edit(@RequestBody Hyperlink hyperlink)
+    {
+        return toAjax(hyperlinkService.updateHyperlink(hyperlink));
+    }
+
+    /**
+     * 删除超链接
+     */
+    @PreAuthorize("@ss.hasPermi('system:hyperlink:remove')")
+    @Log(title = "超链接", businessType = BusinessType.DELETE)
+    @GetMapping("/delete/{hyperlinkIds}")
+    public AjaxResult remove(@PathVariable Long[] hyperlinkIds)
+    {
+        return toAjax(hyperlinkService.deleteHyperlinkByHyperlinkIds(hyperlinkIds));
+    }
+}

+ 118 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/controller/idcard/SysUserIdcardController.java

@@ -0,0 +1,118 @@
+package com.ruoyi.web.controller.idcard;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.core.domain.model.LoginUser;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.framework.web.service.TokenService;
+import com.ruoyi.system.domain.idcard.SysUserIdcard;
+import com.ruoyi.system.service.ISysUserService;
+import com.ruoyi.system.service.idcard.ISysUserIdcardService;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.core.page.TableDataInfo;
+
+/**
+ * 用户身份证信息Controller
+ *
+ * @author boman
+ * @date 2024-04-22
+ */
+@RestController
+@RequestMapping("/idCard")
+public class SysUserIdcardController extends BaseController {
+    @Autowired
+    private ISysUserIdcardService sysUserIdcardService;
+
+    @Autowired
+    private ISysUserService userService;
+
+    @Autowired
+    private TokenService tokenService;
+
+    /**
+     * 查询用户身份证信息列表
+     */
+    @PreAuthorize("@ss.hasPermi('idcard:idcard:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(SysUserIdcard sysUserIdcard) {
+        startPage();
+        List<SysUserIdcard> list = sysUserIdcardService.selectSysUserIdcardList(sysUserIdcard);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出用户身份证信息列表
+     */
+    @PreAuthorize("@ss.hasPermi('idcard:idcard:export')")
+    @Log(title = "用户身份证信息", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, SysUserIdcard sysUserIdcard) {
+        List<SysUserIdcard> list = sysUserIdcardService.selectSysUserIdcardList(sysUserIdcard);
+        ExcelUtil<SysUserIdcard> util = new ExcelUtil<SysUserIdcard>(SysUserIdcard.class);
+        util.exportExcel(response, list, "用户身份证信息数据");
+    }
+
+    /**
+     * 获取用户身份证信息详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('idcard:idcard:query')")
+    @GetMapping(value = "/{userId}")
+    public AjaxResult getInfo(@PathVariable("userId") Long userId) {
+        return success(sysUserIdcardService.selectSysUserIdcardByUserId(userId));
+    }
+
+    /**
+     * 新增用户身份证信息
+     */
+    @PreAuthorize("@ss.hasPermi('idcard:idcard:add')")
+    @Log(title = "用户身份证信息", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody SysUserIdcard sysUserIdcard) {
+        LoginUser loginUser = getLoginUser();
+        SysUser currentUser = loginUser.getUser();
+        currentUser.setInitFace("Y");
+        userService.checkUserAllowed(currentUser);
+        userService.checkUserDataScope(currentUser.getUserId());
+        currentUser.setUpdateBy(getUsername());
+        if (userService.updateUserStatus(currentUser) > 0) {
+            currentUser.setInitFace("Y");
+            // 更新缓存用户信息
+            tokenService.setLoginUser(loginUser);
+            return toAjax(sysUserIdcardService.insertSysUserIdcard(sysUserIdcard));
+        }
+        return  error("人脸认证更新失败");
+    }
+
+    /**
+     * 修改用户身份证信息
+     */
+    @PreAuthorize("@ss.hasPermi('idcard:idcard:edit')")
+    @Log(title = "用户身份证信息", businessType = BusinessType.UPDATE)
+    @PostMapping("/put")
+    public AjaxResult edit(@RequestBody SysUserIdcard sysUserIdcard) {
+        return toAjax(sysUserIdcardService.updateSysUserIdcard(sysUserIdcard));
+    }
+
+    /**
+     * 删除用户身份证信息
+     */
+    @PreAuthorize("@ss.hasPermi('idcard:idcard:remove')")
+    @Log(title = "用户身份证信息", businessType = BusinessType.DELETE)
+    @GetMapping("/delete/{userIds}")
+    public AjaxResult remove(@PathVariable Long[] userIds) {
+        return toAjax(sysUserIdcardService.deleteSysUserIdcardByUserIds(userIds));
+    }
+}

+ 257 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/controller/loan/LoanApplicationController.java

@@ -0,0 +1,257 @@
+package com.ruoyi.web.controller.loan;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+
+import com.ruoyi.common.annotation.RepeatSubmit;
+import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.common.utils.SendSmsUtils;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.system.domain.loan.LoanApplication;
+import com.ruoyi.system.domain.remind.WaitRemind;
+import com.ruoyi.system.domain.review.ReviewComments;
+import com.ruoyi.system.service.loan.ILoanApplicationService;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.core.page.TableDataInfo;
+
+import static com.ruoyi.common.constant.CommonConstants.RZDB;
+
+/**
+ * 贷款申请主Controller
+ *
+ * @author boman
+ * @date 2024-04-24
+ */
+@RestController
+@RequestMapping("/application")
+public class LoanApplicationController extends BaseController {
+    @Autowired
+    private ILoanApplicationService loanApplicationService;
+
+    /**
+     * 查询贷款申请主列表
+     */
+    //@PreAuthorize("@ss.hasPermi('system:application:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(LoanApplication loanApplication) {
+        startPage();
+        List<LoanApplication> list = loanApplicationService.selectLoanApplicationList(loanApplication);
+        return getDataTable(list);
+    }
+
+
+    /**
+     * 查询需要保后的数据
+     *
+     * @param loanApplication
+     * @return
+     */
+    @PreAuthorize("@ss.hasPermi('system:application:loanAfterList')")
+    @GetMapping("/loanAfterList")
+    public TableDataInfo loanAfterList(LoanApplication loanApplication) {
+        startPage();
+        List<LoanApplication> list = loanApplicationService.selectLoanAfterList(loanApplication);
+        return getDataTable(list);
+    }
+
+    /**
+     * 参会人员查看列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:application:conference:list')")
+    @GetMapping("/conference/list")
+    public TableDataInfo conferenceList(LoanApplication loanApplication) {
+        startPage();
+        List<LoanApplication> list = loanApplicationService.conferenceList(loanApplication);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出贷款申请主列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:application:export')")
+    @Log(title = "贷款申请主", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, LoanApplication loanApplication) {
+        List<LoanApplication> list = loanApplicationService.selectLoanApplicationList(loanApplication);
+        ExcelUtil<LoanApplication> util = new ExcelUtil<LoanApplication>(LoanApplication.class);
+        util.exportExcel(response, list, "贷款申请主数据");
+    }
+
+    /**
+     * 获取贷款申请主详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('system:application:query')")
+    @GetMapping(value = "/{loanApplicationId}")
+    public AjaxResult getInfo(@PathVariable("loanApplicationId") Long loanApplicationId) {
+        return loanApplicationService.selectLoanApplicationByLoanApplicationId(loanApplicationId);
+    }
+
+    /**
+     * 获取贷款申请编号
+     */
+    @PostMapping("/getLoanApplicationNumber")
+    public AjaxResult getLoanApplicationNumber() {
+        //自定义项目编号 = RZDB + 时间戳 + 随机数
+        String loanApplicationNumber = RZDB + DateUtils.getTodayChar() + SendSmsUtils.getCode(4);
+        return AjaxResult.success("操作成功",loanApplicationNumber);
+    }
+    /**
+     * 新增贷款申请主
+     */
+    @RepeatSubmit(interval = 1000, message = "请求过于频繁")
+    @PreAuthorize("@ss.hasPermi('system:application:add')")
+    @Log(title = "贷款申请主", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody LoanApplication loanApplication) {
+        return toAjax(loanApplicationService.insertLoanApplication(loanApplication));
+    }
+
+    /**
+     * 修改贷款申请主
+     */
+    @RepeatSubmit(interval = 1000, message = "请求过于频繁")
+    @PreAuthorize("@ss.hasPermi('system:application:edit')")
+    @Log(title = "贷款申请主", businessType = BusinessType.UPDATE)
+    @PostMapping("/put")
+    public AjaxResult edit(@RequestBody LoanApplication loanApplication) {
+        return loanApplicationService.updateLoanApplication(loanApplication);
+    }
+
+
+    /**
+     * 修改贷款申请主新只新增实际放款金额(万元)实际放款时间
+     */
+    @RepeatSubmit(interval = 1000, message = "请求过于频繁")
+    @PreAuthorize("@ss.hasPermi('system:application:editActually')")
+    @Log(title = "贷款申请主", businessType = BusinessType.UPDATE)
+    @PostMapping("/putActually")
+    public AjaxResult editActually(@RequestBody LoanApplication loanApplication) {
+        return loanApplicationService.updateLoanApplicationActually(loanApplication);
+    }
+
+    /**
+     * 删除贷款申请主
+     */
+    @PreAuthorize("@ss.hasPermi('system:application:remove')")
+    @Log(title = "贷款申请主", businessType = BusinessType.DELETE)
+    @GetMapping("/delete/{loanApplicationIds}")
+    public AjaxResult remove(@PathVariable Long[] loanApplicationIds) {
+        return toAjax(loanApplicationService.deleteLoanApplicationByLoanApplicationIds(loanApplicationIds));
+    }
+
+    /**
+     *暂存
+     */
+    @RepeatSubmit(interval = 1000, message = "请求过于频繁")
+    @PreAuthorize("@ss.hasPermi('system:application:temporary')")
+    @PostMapping("/temporary")
+    public AjaxResult temporary(@RequestBody LoanApplication loanApplication) {
+        return loanApplicationService.temporary(loanApplication);
+    }
+
+    /**
+     * 7:合同签约 8:放款合规风险审核
+     */
+    @PreAuthorize("@ss.hasPermi('system:application:schedule')")
+    @PostMapping("/schedule")
+    public AjaxResult schedule(@RequestBody LoanApplication loanApplication) {
+        return loanApplicationService.schedule(loanApplication);
+    }
+    /**
+     * 审核
+     */
+    @PreAuthorize("@ss.hasPermi('system:application:sh')")
+    @PostMapping("/sh")
+    public AjaxResult sh(@RequestBody ReviewComments reviewComments) {
+        return loanApplicationService.sh(reviewComments);
+    }
+
+    /**
+     * 管理员同意上会审核按钮
+     */
+    @PreAuthorize("@ss.hasPermi('system:application:review')")
+    @PostMapping("/review")
+    public AjaxResult review(@RequestBody LoanApplication loanApplication) {
+        return loanApplicationService.review(loanApplication);
+    }
+
+
+    /**
+     * 申诉
+     */
+    @PreAuthorize("@ss.hasPermi('system:application:ss')")
+    @PostMapping("/ss")
+    public AjaxResult ss(@RequestBody LoanApplication loanApplication) {
+        return loanApplicationService.ss(loanApplication);
+    }
+    /**
+     * 撤销
+     */
+    @PreAuthorize("@ss.hasPermi('system:application:cx')")
+    @PostMapping("/cx")
+    public AjaxResult cx(@RequestBody LoanApplication loanApplication) {
+        return loanApplicationService.cx(loanApplication);
+    }
+
+    /**
+     * 归档
+     */
+    @PreAuthorize("@ss.hasPermi('system:application:gd')")
+    @PostMapping("/gd")
+    public AjaxResult gd(@RequestBody LoanApplication loanApplication) {
+        return loanApplicationService.gd(loanApplication);
+    }
+
+    /**
+     * 暂缓出具放款合规表-风险使用
+     */
+    @PreAuthorize("@ss.hasPermi('system:application:zanHuan')")
+    @PostMapping("/zanHuan")
+    public AjaxResult zanHuan(@RequestBody LoanApplication loanApplication) {
+        return loanApplicationService.zanHuan(loanApplication);
+    }
+
+    /**
+     * 管理员授权A角色开具放款通知书
+     */
+    @PreAuthorize("@ss.hasPermi('system:application:authorize')")
+    @PostMapping("/authorize")
+    public AjaxResult authorize(@RequestBody LoanApplication loanApplication) {
+        return loanApplicationService.authorize(loanApplication);
+    }
+
+    /**
+     * 导出模板附件
+     */
+    @PreAuthorize("@ss.hasPermi('system:export:mb')")
+    @Log(title = "导出模板附件", businessType = BusinessType.DELETE)
+    @PostMapping("/export/mb")
+    public AjaxResult exportMb(@RequestBody LoanApplication loanApplication) {
+        return loanApplicationService.exportMb(loanApplication);
+    }
+
+    /**
+     * 文件管理列表
+     * @param loanApplication
+     * @return
+     */
+    @GetMapping("/listOss")
+    @PreAuthorize("@ss.hasPermi('system:application:listOss')")
+    public TableDataInfo listOss(LoanApplication loanApplication) {
+        startPage();
+        List<LoanApplication> list = loanApplicationService.listOss(loanApplication);
+        return getDataTable(list);
+    }
+}

+ 105 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/controller/loan/LoanApplicationFjController.java

@@ -0,0 +1,105 @@
+package com.ruoyi.web.controller.loan;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.system.domain.loan.LoanApplicationFj;
+import com.ruoyi.system.service.loan.ILoanApplicationFjService;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.core.page.TableDataInfo;
+
+/**
+ * 贷款申请_附件Controller
+ *
+ * @author boman
+ * @date 2024-04-24
+ */
+@RestController
+@RequestMapping("/fj")
+public class LoanApplicationFjController extends BaseController {
+    @Autowired
+    private ILoanApplicationFjService loanApplicationFjService;
+
+    /**
+     * 查询贷款申请_附件列表
+     */
+    //@PreAuthorize("@ss.hasPermi('system:fj:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(LoanApplicationFj loanApplicationFj) {
+        startPage();
+        List<LoanApplicationFj> list = loanApplicationFjService.selectLoanApplicationFjList(loanApplicationFj);
+        return getDataTable(list);
+    }
+
+    /**
+     * 查询贷款申请_附件列表(二维码)
+     */
+    //@PreAuthorize("@ss.hasPermi('system:fj:list')")
+    @GetMapping("/ewmList")
+    public AjaxResult ewmList(LoanApplicationFj loanApplicationFj) {
+        return loanApplicationFjService.ewmList(loanApplicationFj);
+    }
+
+    /**
+     * 导出贷款申请_附件列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:fj:export')")
+    @Log(title = "贷款申请_附件", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, LoanApplicationFj loanApplicationFj) {
+        List<LoanApplicationFj> list = loanApplicationFjService.selectLoanApplicationFjList(loanApplicationFj);
+        ExcelUtil<LoanApplicationFj> util = new ExcelUtil<LoanApplicationFj>(LoanApplicationFj.class);
+        util.exportExcel(response, list, "贷款申请_附件数据");
+    }
+
+    /**
+     * 获取贷款申请_附件详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('system:fj:query')")
+    @GetMapping(value = "/{fjId}")
+    public AjaxResult getInfo(@PathVariable("fjId") Long fjId) {
+        return success(loanApplicationFjService.selectLoanApplicationFjByFjId(fjId));
+    }
+
+    /**
+     * 新增贷款申请_附件
+     */
+    @PreAuthorize("@ss.hasPermi('system:fj:add')")
+    @Log(title = "贷款申请_附件", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody List<LoanApplicationFj> loanApplicationFj) {
+        return toAjax(loanApplicationFjService.insertLoanApplicationFj(loanApplicationFj));
+    }
+
+    /**
+     * 修改贷款申请_附件
+     */
+    @PreAuthorize("@ss.hasPermi('system:fj:edit')")
+    @Log(title = "贷款申请_附件", businessType = BusinessType.UPDATE)
+    @PostMapping("/put")
+    public AjaxResult edit(@RequestBody List<LoanApplicationFj> loanApplicationFj) {
+        return toAjax(loanApplicationFjService.updateLoanApplicationFj(loanApplicationFj));
+    }
+
+    /**
+     * 删除贷款申请_附件
+     */
+    @PreAuthorize("@ss.hasPermi('system:fj:remove')")
+    @Log(title = "贷款申请_附件", businessType = BusinessType.DELETE)
+    @GetMapping("/delete/{fjIds}")
+    public AjaxResult remove(@PathVariable Long[] fjIds) {
+        return toAjax(loanApplicationFjService.deleteLoanApplicationFjByFjIds(fjIds));
+    }
+}

+ 96 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/controller/loan/LoanScheduleController.java

@@ -0,0 +1,96 @@
+package com.ruoyi.web.controller.loan;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.system.domain.loan.LoanSchedule;
+import com.ruoyi.system.service.loan.ILoanScheduleService;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.core.page.TableDataInfo;
+
+/**
+ * 业务进度Controller
+ *
+ * @author boman
+ * @date 2024-04-24
+ */
+@RestController
+@RequestMapping("/schedule")
+public class LoanScheduleController extends BaseController {
+    @Autowired
+    private ILoanScheduleService loanScheduleService;
+
+    /**
+     * 查询业务进度列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:schedule:list')")
+    @GetMapping("/list")
+    public AjaxResult list(LoanSchedule loanSchedule) {
+        return loanScheduleService.selectLoanScheduleList(loanSchedule);
+    }
+
+/*    *//**
+     * 导出业务进度列表
+     *//*
+    @PreAuthorize("@ss.hasPermi('system:schedule:export')")
+    @Log(title = "业务进度", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, LoanSchedule loanSchedule) {
+        List<LoanSchedule> list = loanScheduleService.selectLoanScheduleList(loanSchedule);
+        ExcelUtil<LoanSchedule> util = new ExcelUtil<LoanSchedule>(LoanSchedule.class);
+        util.exportExcel(response, list, "业务进度数据");
+    }*/
+
+    /**
+     * 获取业务进度详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('system:schedule:query')")
+    @GetMapping(value = "/{loanScheduleId}")
+    public AjaxResult getInfo(@PathVariable("loanScheduleId") Long loanScheduleId) {
+        return success(loanScheduleService.selectLoanScheduleByLoanScheduleId(loanScheduleId));
+    }
+
+    /**
+     * 新增业务进度
+     */
+    @PreAuthorize("@ss.hasPermi('system:schedule:add')")
+    @Log(title = "业务进度", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody LoanSchedule loanSchedule) {
+        return toAjax(loanScheduleService.insertLoanSchedule(loanSchedule));
+    }
+
+    /**
+     * 修改业务进度
+     */
+    @PreAuthorize("@ss.hasPermi('system:schedule:edit')")
+    @Log(title = "业务进度", businessType = BusinessType.UPDATE)
+    @PostMapping("/put")
+    public AjaxResult edit(@RequestBody LoanSchedule loanSchedule) {
+        return toAjax(loanScheduleService.updateLoanSchedule(loanSchedule));
+    }
+
+    /**
+     * 删除业务进度
+     */
+    @PreAuthorize("@ss.hasPermi('system:schedule:remove')")
+    @Log(title = "业务进度", businessType = BusinessType.DELETE)
+    @GetMapping("/delete/{loanScheduleIds}")
+    public AjaxResult remove(@PathVariable Long[] loanScheduleIds) {
+        return toAjax(loanScheduleService.deleteLoanScheduleByLoanScheduleIds(loanScheduleIds));
+    }
+}

+ 112 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/controller/loan/ShareholderFjController.java

@@ -0,0 +1,112 @@
+package com.ruoyi.web.controller.loan;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+
+import com.ruoyi.system.domain.loan.ShareholderFj;
+import com.ruoyi.system.service.loan.IShareholderFjService;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.enums.BusinessType;
+
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.common.core.page.TableDataInfo;
+
+/**
+ * 全体股东附件Controller
+ *
+ * @author boman
+ * @date 2024-04-24
+ */
+@RestController
+@RequestMapping("/shareholderFj")
+public class ShareholderFjController extends BaseController {
+    @Autowired
+    private IShareholderFjService shareholderFjService;
+
+    /**
+     * 查询全体股东附件列表
+     */
+    //@PreAuthorize("@ss.hasPermi('system:shareholderFj:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(ShareholderFj shareholderFj) {
+        startPage();
+        List<ShareholderFj> list = shareholderFjService.selectShareholderFjList(shareholderFj);
+        return getDataTable(list);
+    }
+
+    /**
+     * 只查询股东是企业的
+     * @param shareholderFj
+     * @return
+     */
+    @PreAuthorize("@ss.hasPermi('system:shareholderFj:listNoPage')")
+    @GetMapping("/listNoPage")
+    public AjaxResult listNoPage(ShareholderFj shareholderFj) {
+        List<ShareholderFj> list = shareholderFjService.selectShareholderFjListNoPage(shareholderFj);
+        return AjaxResult.success(list);
+    }
+
+    /**
+     * 导出全体股东附件列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:shareholderFj:export')")
+    @Log(title = "全体股东附件", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, ShareholderFj shareholderFj) {
+        List<ShareholderFj> list = shareholderFjService.selectShareholderFjList(shareholderFj);
+        ExcelUtil<ShareholderFj> util = new ExcelUtil<ShareholderFj>(ShareholderFj.class);
+        util.exportExcel(response, list, "全体股东附件数据");
+    }
+
+    /**
+     * 获取全体股东附件详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('system:shareholderFj:query')")
+    @GetMapping(value = "/{shareholderFjId}")
+    public AjaxResult getInfo(@PathVariable("shareholderFjId") Long shareholderFjId) {
+        return success(shareholderFjService.selectShareholderFjByShareholderFjId(shareholderFjId));
+    }
+
+    /**
+     * 新增全体股东附件
+     */
+    @PreAuthorize("@ss.hasPermi('system:shareholderFj:add')")
+    @Log(title = "全体股东附件", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody ShareholderFj shareholderFj) {
+        return toAjax(shareholderFjService.insertShareholderFj(shareholderFj));
+    }
+
+    /**
+     * 修改全体股东附件
+     */
+    @PreAuthorize("@ss.hasPermi('system:shareholderFj:edit')")
+    @Log(title = "全体股东附件", businessType = BusinessType.UPDATE)
+    @PostMapping("/put")
+    public AjaxResult edit(@RequestBody ShareholderFj shareholderFj) {
+        return toAjax(shareholderFjService.updateShareholderFj(shareholderFj));
+    }
+
+    /**
+     * 删除全体股东附件
+     */
+    @PreAuthorize("@ss.hasPermi('system:shareholderFj:remove')")
+    @Log(title = "全体股东附件", businessType = BusinessType.DELETE)
+    @GetMapping("/delete/{shareholderFjIds}")
+    public AjaxResult remove(@PathVariable Long[] shareholderFjIds) {
+        return toAjax(shareholderFjService.deleteShareholderFjByShareholderFjIds(shareholderFjIds));
+    }
+
+}

+ 3 - 3
ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/CacheController.java

@@ -93,7 +93,7 @@ public class CacheController
     }
 
     @PreAuthorize("@ss.hasPermi('monitor:cache:list')")
-    @DeleteMapping("/clearCacheName/{cacheName}")
+    @GetMapping("/clearCacheName/delete/{cacheName}")
     public AjaxResult clearCacheName(@PathVariable String cacheName)
     {
         Collection<String> cacheKeys = redisTemplate.keys(cacheName + "*");
@@ -102,7 +102,7 @@ public class CacheController
     }
 
     @PreAuthorize("@ss.hasPermi('monitor:cache:list')")
-    @DeleteMapping("/clearCacheKey/{cacheKey}")
+    @GetMapping("/clearCacheKey/delete/{cacheKey}")
     public AjaxResult clearCacheKey(@PathVariable String cacheKey)
     {
         redisTemplate.delete(cacheKey);
@@ -110,7 +110,7 @@ public class CacheController
     }
 
     @PreAuthorize("@ss.hasPermi('monitor:cache:list')")
-    @DeleteMapping("/clearCacheAll")
+    @GetMapping("/clearCacheAll/delete")
     public AjaxResult clearCacheAll()
     {
         Collection<String> cacheKeys = redisTemplate.keys("*");

+ 2 - 2
ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysLogininforController.java

@@ -56,7 +56,7 @@ public class SysLogininforController extends BaseController
 
     @PreAuthorize("@ss.hasPermi('monitor:logininfor:remove')")
     @Log(title = "登录日志", businessType = BusinessType.DELETE)
-    @DeleteMapping("/{infoIds}")
+    @GetMapping("/delete/{infoIds}")
     public AjaxResult remove(@PathVariable Long[] infoIds)
     {
         return toAjax(logininforService.deleteLogininforByIds(infoIds));
@@ -64,7 +64,7 @@ public class SysLogininforController extends BaseController
 
     @PreAuthorize("@ss.hasPermi('monitor:logininfor:remove')")
     @Log(title = "登录日志", businessType = BusinessType.CLEAN)
-    @DeleteMapping("/clean")
+    @GetMapping("/delete/clean")
     public AjaxResult clean()
     {
         logininforService.cleanLogininfor();

+ 2 - 2
ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysOperlogController.java

@@ -52,7 +52,7 @@ public class SysOperlogController extends BaseController
 
     @Log(title = "操作日志", businessType = BusinessType.DELETE)
     @PreAuthorize("@ss.hasPermi('monitor:operlog:remove')")
-    @DeleteMapping("/{operIds}")
+    @GetMapping("/delete/{operIds}")
     public AjaxResult remove(@PathVariable Long[] operIds)
     {
         return toAjax(operLogService.deleteOperLogByIds(operIds));
@@ -60,7 +60,7 @@ public class SysOperlogController extends BaseController
 
     @Log(title = "操作日志", businessType = BusinessType.CLEAN)
     @PreAuthorize("@ss.hasPermi('monitor:operlog:remove')")
-    @DeleteMapping("/clean")
+    @GetMapping("/clean/delete")
     public AjaxResult clean()
     {
         operLogService.cleanOperLog();

+ 1 - 1
ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysUserOnlineController.java

@@ -74,7 +74,7 @@ public class SysUserOnlineController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('monitor:online:forceLogout')")
     @Log(title = "在线用户", businessType = BusinessType.FORCE)
-    @DeleteMapping("/{tokenId}")
+    @GetMapping("/delete/{tokenId}")
     public AjaxResult forceLogout(@PathVariable String tokenId)
     {
         redisCache.deleteObject(CacheConstants.LOGIN_TOKEN_KEY + tokenId);

+ 56 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/controller/qichacha/QiChaCha.java

@@ -0,0 +1,56 @@
+package com.ruoyi.web.controller.qichacha;
+
+import com.alibaba.fastjson2.JSONArray;
+import com.alibaba.fastjson2.JSONObject;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.http.HttpUtils;
+import com.ruoyi.common.utils.sign.Md5Utils;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @Author: tjf
+ * @Date: 2024/4/17 10:24
+ * @Describe:
+ */
+public class QiChaCha extends BaseController {
+    /**
+     * 企查查
+     */
+    private static final String KEY = "e50f4b2011ea41a3ad489f0476160041";
+    private static final String SECRET_KEY = "BD8D23FCD36CDEE7E0B25DAB28588163";
+    /**
+     * 通过企查查,查询企业信息
+     *
+     * @param searchKey
+     * @return
+     */
+    @GetMapping("/qichachaSearch/{searchKey}")
+    public AjaxResult qichachaSearch(@PathVariable("searchKey") String searchKey) {
+        if (StringUtils.isNotBlank(searchKey)){
+            //Headers头信息
+            Map<String,String> map = new HashMap<>();
+            StringBuilder sb = new StringBuilder();
+            String unix = DateUtils.getUnix();
+            map.put("Timespan", unix);
+            sb.append(KEY).append(unix).append(SECRET_KEY);
+            map.put("Token", Md5Utils.hash(sb.toString()).toUpperCase());
+            StringBuilder sbd = new StringBuilder();
+            sbd.append("key=").append(KEY).append("&").append("searchKey=").append(searchKey);
+            String s = HttpUtils.sendGetMap("https://api.qichacha.com/FuzzySearch/GetList",sbd.toString(),map);
+            JSONObject result = JSONObject.parseObject(s);
+            JSONArray resultOut = result.getJSONArray("Result");
+            if (resultOut != null){
+                return AjaxResult.success(resultOut);
+            }
+        }
+        return AjaxResult.success(new ArrayList<>());
+    }
+}

+ 96 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/controller/remind/WaitRemindController.java

@@ -0,0 +1,96 @@
+package com.ruoyi.web.controller.remind;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.system.domain.remind.WaitRemind;
+import com.ruoyi.system.service.remind.IWaitRemindService;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.core.page.TableDataInfo;
+
+/**
+ * 待办提醒Controller
+ *
+ * @author boman
+ * @date 2024-04-29
+ */
+@RestController
+@RequestMapping("/remind")
+public class WaitRemindController extends BaseController {
+    @Autowired
+    private IWaitRemindService waitRemindService;
+
+    /**
+     * 查询待办提醒列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:remind:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(WaitRemind waitRemind) {
+        startPage();
+        List<WaitRemind> list = waitRemindService.selectWaitRemindList(waitRemind);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出待办提醒列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:remind:export')")
+    @Log(title = "待办提醒", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, WaitRemind waitRemind) {
+        List<WaitRemind> list = waitRemindService.selectWaitRemindList(waitRemind);
+        ExcelUtil<WaitRemind> util = new ExcelUtil<WaitRemind>(WaitRemind.class);
+        util.exportExcel(response, list, "待办提醒数据");
+    }
+
+    /**
+     * 获取待办提醒详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('system:remind:query')")
+    @GetMapping(value = "/{remindId}")
+    public AjaxResult getInfo(@PathVariable("remindId") Integer remindId) {
+        return success(waitRemindService.selectWaitRemindByRemindId(remindId));
+    }
+
+    /**
+     * 新增待办提醒
+     */
+    @PreAuthorize("@ss.hasPermi('system:remind:add')")
+    @Log(title = "待办提醒", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody WaitRemind waitRemind) {
+        return toAjax(waitRemindService.insertWaitRemind(waitRemind));
+    }
+
+    /**
+     * 修改待办提醒
+     */
+    @PreAuthorize("@ss.hasPermi('system:remind:edit')")
+    @Log(title = "待办提醒", businessType = BusinessType.UPDATE)
+    @PostMapping("/put")
+    public AjaxResult edit(@RequestBody WaitRemind waitRemind) {
+        return toAjax(waitRemindService.updateWaitRemind(waitRemind));
+    }
+
+    /**
+     * 删除待办提醒
+     */
+    @PreAuthorize("@ss.hasPermi('system:remind:remove')")
+    @Log(title = "待办提醒", businessType = BusinessType.DELETE)
+    @GetMapping("/delete/{remindIds}")
+    public AjaxResult remove(@PathVariable Integer[] remindIds) {
+        return toAjax(waitRemindService.deleteWaitRemindByRemindIds(remindIds));
+    }
+}

+ 95 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/controller/review/ReviewCommentsController.java

@@ -0,0 +1,95 @@
+package com.ruoyi.web.controller.review;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+
+import com.ruoyi.system.domain.review.ReviewComments;
+import com.ruoyi.system.service.review.IReviewCommentsService;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.common.core.page.TableDataInfo;
+
+/**
+ * 业务审核意见Controller
+ *
+ * @author boman
+ * @date 2024-04-24
+ */
+@RestController
+@RequestMapping("/comments")
+public class ReviewCommentsController extends BaseController {
+    @Autowired
+    private IReviewCommentsService reviewCommentsService;
+
+    /**
+     * 查询业务审核意见列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:comments:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(ReviewComments reviewComments) {
+        List<ReviewComments> list = reviewCommentsService.selectReviewCommentsList(reviewComments);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出业务审核意见列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:comments:export')")
+    @Log(title = "业务审核意见", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, ReviewComments reviewComments) {
+        List<ReviewComments> list = reviewCommentsService.selectReviewCommentsList(reviewComments);
+        ExcelUtil<ReviewComments> util = new ExcelUtil<ReviewComments>(ReviewComments.class);
+        util.exportExcel(response, list, "业务审核意见数据");
+    }
+
+    /**
+     * 获取业务审核意见详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('system:comments:query')")
+    @GetMapping(value = "/{reviewCommentsId}")
+    public AjaxResult getInfo(@PathVariable("reviewCommentsId") Long reviewCommentsId) {
+        return success(reviewCommentsService.selectReviewCommentsByReviewCommentsId(reviewCommentsId));
+    }
+
+    /**
+     * 新增业务审核意见
+     */
+    @PreAuthorize("@ss.hasPermi('system:comments:add')")
+    @Log(title = "业务审核意见", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody ReviewComments reviewComments) {
+        return toAjax(reviewCommentsService.insertReviewComments(reviewComments));
+    }
+
+    /**
+     * 修改业务审核意见
+     */
+    @PreAuthorize("@ss.hasPermi('system:comments:edit')")
+    @Log(title = "业务审核意见", businessType = BusinessType.UPDATE)
+    @PostMapping("/put")
+    public AjaxResult edit(@RequestBody ReviewComments reviewComments) {
+        return toAjax(reviewCommentsService.updateReviewComments(reviewComments));
+    }
+
+    /**
+     * 删除业务审核意见
+     */
+    @PreAuthorize("@ss.hasPermi('system:comments:remove')")
+    @Log(title = "业务审核意见", businessType = BusinessType.DELETE)
+    @GetMapping("/delete/{reviewCommentsIds}")
+    public AjaxResult remove(@PathVariable Long[] reviewCommentsIds) {
+        return toAjax(reviewCommentsService.deleteReviewCommentsByReviewCommentsIds(reviewCommentsIds));
+    }
+}

+ 56 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/controller/statistics/StatisticsController.java

@@ -0,0 +1,56 @@
+package com.ruoyi.web.controller.statistics;
+
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.system.domain.loan.LoanApplication;
+import com.ruoyi.system.domain.review.ReviewComments;
+import com.ruoyi.system.service.statistics.IStatisticsService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 首页统计
+ * @Author: tjf
+ * @Date: 2024/5/7 14:27
+ * @Describe:
+ */
+@RestController
+@RequestMapping("/statistics")
+public class StatisticsController extends BaseController {
+    @Autowired
+    private IStatisticsService statisticsService;
+
+    /**
+     * 后台首页统计
+     */
+    @PreAuthorize("@ss.hasPermi('system:statistics:loan')")
+    @PostMapping("/loan")
+    public AjaxResult loan(@RequestBody LoanApplication loanApplication) {
+        AjaxResult loan = statisticsService.loan(loanApplication);
+        return loan;
+    }
+
+    /**
+     * 后台首页统计本月数据
+     */
+    @PreAuthorize("@ss.hasPermi('system:statistics:loanMonth')")
+    @PostMapping("/loanMonth")
+    public AjaxResult loanMonth(@RequestBody LoanApplication loanApplication) {
+        AjaxResult loanMonth = statisticsService.loanMonth(loanApplication);
+        return loanMonth;
+    }
+
+    /**
+     * 后台首页统计季度数据
+     */
+    @PreAuthorize("@ss.hasPermi('system:statistics:loanQuarter')")
+    @PostMapping("/loanQuarter")
+    public AjaxResult loanQuarter(@RequestBody LoanApplication loanApplication) {
+        AjaxResult loanMonth = statisticsService.loanQuarter(loanApplication);
+        return loanMonth;
+    }
+}

+ 3 - 3
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysConfigController.java

@@ -96,7 +96,7 @@ public class SysConfigController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('system:config:edit')")
     @Log(title = "参数管理", businessType = BusinessType.UPDATE)
-    @PutMapping
+    @PostMapping("/put")
     public AjaxResult edit(@Validated @RequestBody SysConfig config)
     {
         if (!configService.checkConfigKeyUnique(config))
@@ -112,7 +112,7 @@ public class SysConfigController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('system:config:remove')")
     @Log(title = "参数管理", businessType = BusinessType.DELETE)
-    @DeleteMapping("/{configIds}")
+    @GetMapping("/delete/{configIds}")
     public AjaxResult remove(@PathVariable Long[] configIds)
     {
         configService.deleteConfigByIds(configIds);
@@ -124,7 +124,7 @@ public class SysConfigController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('system:config:remove')")
     @Log(title = "参数管理", businessType = BusinessType.CLEAN)
-    @DeleteMapping("/refreshCache")
+    @GetMapping("/delete/refreshCache")
     public AjaxResult refreshCache()
     {
         configService.resetConfigCache();

+ 2 - 2
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDeptController.java

@@ -89,7 +89,7 @@ public class SysDeptController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('system:dept:edit')")
     @Log(title = "部门管理", businessType = BusinessType.UPDATE)
-    @PutMapping
+    @PostMapping("/put")
     public AjaxResult edit(@Validated @RequestBody SysDept dept)
     {
         Long deptId = dept.getDeptId();
@@ -115,7 +115,7 @@ public class SysDeptController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('system:dept:remove')")
     @Log(title = "部门管理", businessType = BusinessType.DELETE)
-    @DeleteMapping("/{deptId}")
+    @GetMapping("/delete/{deptId}")
     public AjaxResult remove(@PathVariable Long deptId)
     {
         if (deptService.hasChildByDeptId(deptId))

+ 2 - 2
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictDataController.java

@@ -100,7 +100,7 @@ public class SysDictDataController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('system:dict:edit')")
     @Log(title = "字典数据", businessType = BusinessType.UPDATE)
-    @PutMapping
+    @PostMapping("/put")
     public AjaxResult edit(@Validated @RequestBody SysDictData dict)
     {
         dict.setUpdateBy(getUsername());
@@ -112,7 +112,7 @@ public class SysDictDataController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('system:dict:remove')")
     @Log(title = "字典类型", businessType = BusinessType.DELETE)
-    @DeleteMapping("/{dictCodes}")
+    @GetMapping("/delete/{dictCodes}")
     public AjaxResult remove(@PathVariable Long[] dictCodes)
     {
         dictDataService.deleteDictDataByIds(dictCodes);

+ 3 - 3
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictTypeController.java

@@ -84,7 +84,7 @@ public class SysDictTypeController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('system:dict:edit')")
     @Log(title = "字典类型", businessType = BusinessType.UPDATE)
-    @PutMapping
+    @PostMapping("/put")
     public AjaxResult edit(@Validated @RequestBody SysDictType dict)
     {
         if (!dictTypeService.checkDictTypeUnique(dict))
@@ -100,7 +100,7 @@ public class SysDictTypeController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('system:dict:remove')")
     @Log(title = "字典类型", businessType = BusinessType.DELETE)
-    @DeleteMapping("/{dictIds}")
+    @GetMapping("/delete/{dictIds}")
     public AjaxResult remove(@PathVariable Long[] dictIds)
     {
         dictTypeService.deleteDictTypeByIds(dictIds);
@@ -112,7 +112,7 @@ public class SysDictTypeController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('system:dict:remove')")
     @Log(title = "字典类型", businessType = BusinessType.CLEAN)
-    @DeleteMapping("/refreshCache")
+    @GetMapping("/refreshCache")
     public AjaxResult refreshCache()
     {
         dictTypeService.resetDictCache();

+ 1 - 1
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java

@@ -46,7 +46,7 @@ public class SysLoginController
         AjaxResult ajax = AjaxResult.success();
         // 生成令牌
         String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),
-                loginBody.getUuid());
+                loginBody.getUuid(),loginBody.getType());
         ajax.put(Constants.TOKEN, token);
         return ajax;
     }

+ 2 - 2
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysMenuController.java

@@ -102,7 +102,7 @@ public class SysMenuController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('system:menu:edit')")
     @Log(title = "菜单管理", businessType = BusinessType.UPDATE)
-    @PutMapping
+    @PostMapping("/put")
     public AjaxResult edit(@Validated @RequestBody SysMenu menu)
     {
         if (!menuService.checkMenuNameUnique(menu))
@@ -126,7 +126,7 @@ public class SysMenuController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('system:menu:remove')")
     @Log(title = "菜单管理", businessType = BusinessType.DELETE)
-    @DeleteMapping("/{menuId}")
+    @GetMapping("/delete/{menuId}")
     public AjaxResult remove(@PathVariable("menuId") Long menuId)
     {
         if (menuService.hasChildByMenuId(menuId))

+ 2 - 2
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysNoticeController.java

@@ -71,7 +71,7 @@ public class SysNoticeController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('system:notice:edit')")
     @Log(title = "通知公告", businessType = BusinessType.UPDATE)
-    @PutMapping
+    @PostMapping("/put")
     public AjaxResult edit(@Validated @RequestBody SysNotice notice)
     {
         notice.setUpdateBy(getUsername());
@@ -83,7 +83,7 @@ public class SysNoticeController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('system:notice:remove')")
     @Log(title = "通知公告", businessType = BusinessType.DELETE)
-    @DeleteMapping("/{noticeIds}")
+    @GetMapping("/delete/{noticeIds}")
     public AjaxResult remove(@PathVariable Long[] noticeIds)
     {
         return toAjax(noticeService.deleteNoticeByIds(noticeIds));

+ 2 - 2
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysPostController.java

@@ -91,7 +91,7 @@ public class SysPostController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('system:post:edit')")
     @Log(title = "岗位管理", businessType = BusinessType.UPDATE)
-    @PutMapping
+    @PostMapping("/put")
     public AjaxResult edit(@Validated @RequestBody SysPost post)
     {
         if (!postService.checkPostNameUnique(post))
@@ -111,7 +111,7 @@ public class SysPostController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('system:post:remove')")
     @Log(title = "岗位管理", businessType = BusinessType.DELETE)
-    @DeleteMapping("/{postIds}")
+    @GetMapping("/delete/{postIds}")
     public AjaxResult remove(@PathVariable Long[] postIds)
     {
         return toAjax(postService.deletePostByIds(postIds));

+ 22 - 26
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java

@@ -1,5 +1,7 @@
 package com.ruoyi.web.controller.system;
 
+
+import com.ruoyi.common.utils.AesUtil;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PostMapping;
@@ -23,17 +25,19 @@ import com.ruoyi.common.utils.file.MimeTypeUtils;
 import com.ruoyi.framework.web.service.TokenService;
 import com.ruoyi.system.service.ISysUserService;
 
+import java.util.Objects;
+
+import static com.ruoyi.common.constant.CommonConstants.LOGIN_PASSWORD_AES;
 import static com.ruoyi.common.constant.CommonConstants.ONE;
 
 /**
  * 个人信息 业务处理
- * 
+ *
  * @author ruoyi
  */
 @RestController
 @RequestMapping("/system/user/profile")
-public class SysProfileController extends BaseController
-{
+public class SysProfileController extends BaseController {
     @Autowired
     private ISysUserService userService;
 
@@ -44,8 +48,7 @@ public class SysProfileController extends BaseController
      * 个人信息
      */
     @GetMapping
-    public AjaxResult profile()
-    {
+    public AjaxResult profile() {
         LoginUser loginUser = getLoginUser();
         SysUser user = loginUser.getUser();
         AjaxResult ajax = AjaxResult.success(user);
@@ -58,25 +61,22 @@ public class SysProfileController extends BaseController
      * 修改用户
      */
     @Log(title = "个人信息", businessType = BusinessType.UPDATE)
-    @PutMapping
-    public AjaxResult updateProfile(@RequestBody SysUser user)
-    {
+    @PostMapping("/put")
+    public AjaxResult updateProfile(@RequestBody SysUser user) {
         LoginUser loginUser = getLoginUser();
         SysUser currentUser = loginUser.getUser();
         currentUser.setNickName(user.getNickName());
         currentUser.setEmail(user.getEmail());
         currentUser.setPhonenumber(user.getPhonenumber());
         currentUser.setSex(user.getSex());
-        if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(currentUser))
-        {
+        currentUser.setJgId(user.getJgId());
+        if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(currentUser)) {
             return error("修改用户'" + loginUser.getUsername() + "'失败,手机号码已存在");
         }
-        if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(currentUser))
-        {
+        if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(currentUser)) {
             return error("修改用户'" + loginUser.getUsername() + "'失败,邮箱账号已存在");
         }
-        if (userService.updateUserProfile(currentUser) > 0)
-        {
+        if (userService.updateUserProfile(currentUser) > 0) {
             // 更新缓存用户信息
             tokenService.setLoginUser(loginUser);
             return success();
@@ -88,17 +88,16 @@ public class SysProfileController extends BaseController
      * 重置密码
      */
     @Log(title = "个人信息", businessType = BusinessType.UPDATE)
-    @PutMapping("/updatePwd")
-    public AjaxResult updatePwd(String oldPassword, String newPassword)
-    {
+    @PostMapping("/updatePwd")
+    public AjaxResult updatePwd(String oldPassword, String newPassword) {
+        LoginUser loginUser = getLoginUser();
+        String userName = loginUser.getUsername();
+        String password = loginUser.getPassword();
         SysUser sysUser = new SysUser();
         sysUser.setPassword(newPassword);
         if (ONE.equals(userService.checkStrongPwd(sysUser))) {
             return AjaxResult.error("密码必须包含数字、大小写字母、特殊符号且大于8位");
         }
-        LoginUser loginUser = getLoginUser();
-        String userName = loginUser.getUsername();
-        String password = loginUser.getPassword();
         if (!SecurityUtils.matchesPassword(oldPassword, password))
         {
             return error("修改密码失败,旧密码错误");
@@ -123,14 +122,11 @@ public class SysProfileController extends BaseController
      */
     @Log(title = "用户头像", businessType = BusinessType.UPDATE)
     @PostMapping("/avatar")
-    public AjaxResult avatar(@RequestParam("avatarfile") MultipartFile file) throws Exception
-    {
-        if (!file.isEmpty())
-        {
+    public AjaxResult avatar(@RequestParam("avatarfile") MultipartFile file) throws Exception {
+        if (!file.isEmpty()) {
             LoginUser loginUser = getLoginUser();
             String avatar = FileUploadUtils.upload(RuoYiConfig.getAvatarPath(), file, MimeTypeUtils.IMAGE_EXTENSION);
-            if (userService.updateUserAvatar(loginUser.getUsername(), avatar))
-            {
+            if (userService.updateUserAvatar(loginUser.getUsername(), avatar)) {
                 AjaxResult ajax = AjaxResult.success();
                 ajax.put("imgUrl", avatar);
                 // 更新缓存用户头像

+ 7 - 7
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java

@@ -111,7 +111,7 @@ public class SysRoleController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('system:role:edit')")
     @Log(title = "角色管理", businessType = BusinessType.UPDATE)
-    @PutMapping
+    @PostMapping("/put")
     public AjaxResult edit(@Validated @RequestBody SysRole role)
     {
         roleService.checkRoleAllowed(role);
@@ -146,7 +146,7 @@ public class SysRoleController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('system:role:edit')")
     @Log(title = "角色管理", businessType = BusinessType.UPDATE)
-    @PutMapping("/dataScope")
+    @PostMapping("/dataScope/put")
     public AjaxResult dataScope(@RequestBody SysRole role)
     {
         roleService.checkRoleAllowed(role);
@@ -159,7 +159,7 @@ public class SysRoleController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('system:role:edit')")
     @Log(title = "角色管理", businessType = BusinessType.UPDATE)
-    @PutMapping("/changeStatus")
+    @PostMapping("/changeStatus/put")
     public AjaxResult changeStatus(@RequestBody SysRole role)
     {
         roleService.checkRoleAllowed(role);
@@ -173,7 +173,7 @@ public class SysRoleController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('system:role:remove')")
     @Log(title = "角色管理", businessType = BusinessType.DELETE)
-    @DeleteMapping("/{roleIds}")
+    @GetMapping("/delete/{roleIds}")
     public AjaxResult remove(@PathVariable Long[] roleIds)
     {
         return toAjax(roleService.deleteRoleByIds(roleIds));
@@ -218,7 +218,7 @@ public class SysRoleController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('system:role:edit')")
     @Log(title = "角色管理", businessType = BusinessType.GRANT)
-    @PutMapping("/authUser/cancel")
+    @PostMapping("/authUser/cancel/put")
     public AjaxResult cancelAuthUser(@RequestBody SysUserRole userRole)
     {
         return toAjax(roleService.deleteAuthUser(userRole));
@@ -229,7 +229,7 @@ public class SysRoleController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('system:role:edit')")
     @Log(title = "角色管理", businessType = BusinessType.GRANT)
-    @PutMapping("/authUser/cancelAll")
+    @PostMapping("/authUser/cancelAll/put")
     public AjaxResult cancelAuthUserAll(Long roleId, Long[] userIds)
     {
         return toAjax(roleService.deleteAuthUsers(roleId, userIds));
@@ -240,7 +240,7 @@ public class SysRoleController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('system:role:edit')")
     @Log(title = "角色管理", businessType = BusinessType.GRANT)
-    @PutMapping("/authUser/selectAll")
+    @PostMapping("/authUser/selectAll/put")
     public AjaxResult selectAuthUserAll(Long roleId, Long[] userIds)
     {
         roleService.checkRoleDataScope(roleId);

+ 44 - 9
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java

@@ -3,6 +3,10 @@ package com.ruoyi.web.controller.system;
 import java.util.List;
 import java.util.stream.Collectors;
 import javax.servlet.http.HttpServletResponse;
+
+import com.ruoyi.common.core.domain.model.LoginUser;
+import com.ruoyi.common.utils.AesUtil;
+import com.ruoyi.framework.web.service.TokenService;
 import org.apache.commons.lang3.ArrayUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
@@ -32,6 +36,7 @@ import com.ruoyi.system.service.ISysPostService;
 import com.ruoyi.system.service.ISysRoleService;
 import com.ruoyi.system.service.ISysUserService;
 
+import static com.ruoyi.common.constant.CommonConstants.LOGIN_PASSWORD_AES;
 import static com.ruoyi.common.constant.CommonConstants.ONE;
 
 /**
@@ -55,6 +60,9 @@ public class SysUserController extends BaseController
     @Autowired
     private ISysPostService postService;
 
+    @Autowired
+    private TokenService tokenService;
+
     /**
      * 获取用户列表
      */
@@ -67,6 +75,17 @@ public class SysUserController extends BaseController
         return getDataTable(list);
     }
 
+    /**
+     * 获取用户列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:user:noPageList')")
+    @GetMapping("/noPageList")
+    public TableDataInfo noPageList(SysUser user)
+    {
+        List<SysUser> list = userService.selectUserList(user);
+        return getDataTable(list);
+    }
+
     @Log(title = "用户管理", businessType = BusinessType.EXPORT)
     @PreAuthorize("@ss.hasPermi('system:user:export')")
     @PostMapping("/export")
@@ -134,10 +153,6 @@ public class SysUserController extends BaseController
         {
             return error("新增用户'" + user.getUserName() + "'失败,手机号码已存在");
         }
-        else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user))
-        {
-            return error("新增用户'" + user.getUserName() + "'失败,邮箱账号已存在");
-        }
         else if (ONE.equals(userService.checkStrongPwd(user))) {
             return AjaxResult.error("密码必须包含数字、大小写字母、特殊符号且大于8位");
         }
@@ -151,7 +166,7 @@ public class SysUserController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('system:user:edit')")
     @Log(title = "用户管理", businessType = BusinessType.UPDATE)
-    @PutMapping
+    @PostMapping("/put")
     public AjaxResult edit(@Validated @RequestBody SysUser user)
     {
         userService.checkUserAllowed(user);
@@ -177,7 +192,7 @@ public class SysUserController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('system:user:remove')")
     @Log(title = "用户管理", businessType = BusinessType.DELETE)
-    @DeleteMapping("/{userIds}")
+    @GetMapping("/delete/{userIds}")
     public AjaxResult remove(@PathVariable Long[] userIds)
     {
         if (ArrayUtils.contains(userIds, getUserId()))
@@ -192,7 +207,7 @@ public class SysUserController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('system:user:resetPwd')")
     @Log(title = "用户管理", businessType = BusinessType.UPDATE)
-    @PutMapping("/resetPwd")
+    @PostMapping("/resetPwd/put")
     public AjaxResult resetPwd(@RequestBody SysUser user)
     {
         if (ONE.equals(userService.checkStrongPwd(user))) {
@@ -210,7 +225,7 @@ public class SysUserController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('system:user:edit')")
     @Log(title = "用户管理", businessType = BusinessType.UPDATE)
-    @PutMapping("/changeStatus")
+    @PostMapping("/changeStatus/put")
     public AjaxResult changeStatus(@RequestBody SysUser user)
     {
         userService.checkUserAllowed(user);
@@ -219,6 +234,26 @@ public class SysUserController extends BaseController
         return toAjax(userService.updateUserStatus(user));
     }
 
+    /**
+     * 状态人脸识别认证状态
+     */
+    @PostMapping("/changeFace")
+    public AjaxResult changeFace(@RequestBody SysUser user)
+    {
+        LoginUser loginUser = getLoginUser();
+        SysUser currentUser = loginUser.getUser();
+        userService.checkUserAllowed(user);
+        userService.checkUserDataScope(user.getUserId());
+        user.setUpdateBy(getUsername());
+        if (userService.updateUserStatus(user) > 0) {
+            currentUser.setInitFace(user.getInitFace());
+            // 更新缓存用户信息
+            tokenService.setLoginUser(loginUser);
+            return success();
+        }
+        return  error("人脸认证更新失败");
+    }
+
     /**
      * 根据用户编号获取授权角色
      */
@@ -239,7 +274,7 @@ public class SysUserController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('system:user:edit')")
     @Log(title = "用户管理", businessType = BusinessType.GRANT)
-    @PutMapping("/authRole")
+    @PostMapping("/authRole/put")
     public AjaxResult insertAuthRole(Long userId, Long[] roleIds)
     {
         userService.checkUserDataScope(userId);

+ 100 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/UpdateAppController.java

@@ -0,0 +1,100 @@
+package com.ruoyi.web.controller.system;
+
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.system.domain.UpdateApp;
+import com.ruoyi.system.service.IUpdateAppService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletResponse;
+import java.util.List;
+
+/**
+ * 【请填写功能名称】Controller
+ * 
+ * @author ruoyi
+ * @date 2023-02-16
+ */
+@RestController
+@RequestMapping("/system/app")
+public class UpdateAppController extends BaseController
+{
+    @Autowired
+    private IUpdateAppService updateAppService;
+
+    /**
+     * 查询【请填写功能名称】列表
+     */
+    @GetMapping("/list")
+    public TableDataInfo list(UpdateApp updateApp)
+    {
+        startPage();
+        List<UpdateApp> list = updateAppService.selectUpdateAppList(updateApp);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出【请填写功能名称】列表
+     */
+    @Log(title = "【请填写功能名称】", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, UpdateApp updateApp)
+    {
+        List<UpdateApp> list = updateAppService.selectUpdateAppList(updateApp);
+        ExcelUtil<UpdateApp> util = new ExcelUtil<UpdateApp>(UpdateApp.class);
+        util.exportExcel(response, list, "【请填写功能名称】数据");
+    }
+
+    /**
+     * 获取【请填写功能名称】详细信息
+     */
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return success(updateAppService.selectUpdateAppById(id));
+    }
+
+    /**
+     * 新增【请填写功能名称】
+     */
+    @Log(title = "【请填写功能名称】", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody UpdateApp updateApp)
+    {
+        return toAjax(updateAppService.insertUpdateApp(updateApp));
+    }
+
+    /**
+     * 修改【请填写功能名称】
+     */
+    @Log(title = "【请填写功能名称】", businessType = BusinessType.UPDATE)
+    @PostMapping("/put")
+    public AjaxResult edit(@RequestBody UpdateApp updateApp)
+    {
+        return toAjax(updateAppService.updateUpdateApp(updateApp));
+    }
+
+    /**
+     * 删除【请填写功能名称】
+     */
+    @Log(title = "【请填写功能名称】", businessType = BusinessType.DELETE)
+	@GetMapping("/delete/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(updateAppService.deleteUpdateAppByIds(ids));
+    }
+
+    /**
+     * 获取当前最新版本数据
+     */
+    @GetMapping(value = "/new")
+    public AjaxResult getInfoNew(UpdateApp updateApp)
+    {
+        return success(updateAppService.getInfoNew(updateApp));
+    }
+}

+ 2 - 2
ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/TestController.java

@@ -80,7 +80,7 @@ public class TestController extends BaseController
     }
 
     @ApiOperation("更新用户")
-    @PutMapping("/update")
+    @PostMapping("/update/put")
     public R<String> update(@RequestBody UserEntity user)
     {
         if (StringUtils.isNull(user) || StringUtils.isNull(user.getUserId()))
@@ -98,7 +98,7 @@ public class TestController extends BaseController
 
     @ApiOperation("删除用户信息")
     @ApiImplicitParam(name = "userId", value = "用户ID", required = true, dataType = "int", paramType = "path", dataTypeClass = Integer.class)
-    @DeleteMapping("/{userId}")
+    @GetMapping("/delete/{userId}")
     public R<String> delete(@PathVariable Integer userId)
     {
         if (!users.isEmpty() && users.containsKey(userId))

+ 41 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/controller/webOffice/ConsoleController.java

@@ -0,0 +1,41 @@
+package com.ruoyi.web.controller.webOffice;
+
+
+import cn.ljserver.tool.weboffice.v3.exception.FileNotExist;
+import com.ruoyi.common.core.redis.RedisCache;
+import com.ruoyi.framework.web.domain.server.Sys;
+import com.ruoyi.system.service.ISysConfigService;
+import com.ruoyi.system.service.webService.IWebofficeFjService;
+import com.ruoyi.system.service.webService.QnFileService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletRequest;
+
+@RestController
+@RequestMapping("/console")
+public class ConsoleController {
+
+    @Autowired
+    private RedisCache redisCache;
+
+    @Autowired
+    private IWebofficeFjService webofficeFjService;
+
+    @PutMapping("/upload")
+    public String upload(MultipartFile file) {
+        return webofficeFjService.upload(file);
+    }
+
+    @PutMapping(value = "/upload/{file_id}")
+    public String upload(@PathVariable("file_id") String fileId, @RequestBody byte[] content, HttpServletRequest request) {
+        // ATTENTION a dirty version is written into storage
+        System.out.println(fileId+"ooooooooooooooooooooooooooo");
+        if (redisCache.getCacheObject(fileId)==null) throw new FileNotExist();
+        // 从缓存中获取当前需要上传文件的文件类型
+        String suffix = redisCache.getCacheObject(fileId);
+        return webofficeFjService.upload(fileId,content, suffix,request);
+    }
+
+}

+ 15 - 2
ruoyi-admin/src/main/resources/application-druid.yml

@@ -7,13 +7,15 @@ ruoyi:
     # 版权年份
     copyrightYear: 2023
     # 实例演示开关
-    demoEnabled: true
+    demoEnabled: false
     # 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath)
     profile: D:/ruoyi/uploadPath
     # 获取ip地址开关
     addressEnabled: false
     # 验证码类型 math 数组计算 char 字符验证
     captchaType: math
+    # 当前环境
+    isYml: druid
 # 开发环境配置
 server:
     # 服务器的HTTP端口,默认为8080
@@ -110,4 +112,15 @@ spring:
                     merge-sql: true
                 wall:
                     config:
-                        multi-statement-allow: true
+                        multi-statement-allow: true
+
+
+    thymeleaf:
+        prefix: classpath:/templates/
+        suffix: .html
+        cache: false
+
+web-office:
+    convert:
+        appid: AK20240724JZQZVF
+        secret: vkjGMdBUEQUpkhxcwEEjEOUyXxvowmWW

+ 12 - 5
ruoyi-admin/src/main/resources/application-prod.yml

@@ -9,11 +9,13 @@ ruoyi:
     # 实例演示开关
     demoEnabled: false
     # 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath)
-    profile: /home/ruoyi/uploadPath
+    profile: /home/ruoyi/uploadPath/rongzidanbao
     # 获取ip地址开关
     addressEnabled: false
     # 验证码类型 math 数组计算 char 字符验证
     captchaType: math
+    # 当前环境
+    isYml: prod
 
 # 开发环境配置
 server:
@@ -39,9 +41,9 @@ spring:
         # 端口,默认为6379
         port: 6379
         # 数据库索引
-        database: 7
+        database: 9
         # 密码
-        password: 3r263Tr$
+        password: D3fQYAsw
         # 连接超时时间
         timeout: 10s
         lettuce:
@@ -63,7 +65,7 @@ spring:
             master:
                 url: jdbc:mysql://127.0.0.1:3306/rongzidanbao?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true
                 username: root
-                password: UEB^RX$z
+                password: zhaoshang@2018
             # 从库数据源
             slave:
                 # 从数据源开关/默认关闭
@@ -113,4 +115,9 @@ spring:
                     merge-sql: true
                 wall:
                     config:
-                        multi-statement-allow: true
+                        multi-statement-allow: true
+
+web-office:
+    convert:
+        appid: AK20240724JZQZVF
+        secret: vkjGMdBUEQUpkhxcwEEjEOUyXxvowmWW

+ 3 - 1
ruoyi-admin/src/main/resources/application.yml

@@ -18,8 +18,10 @@ spring:
   messages:
     # 国际化资源文件路径
     basename: i18n/messages
+
   profiles:
     active: druid
+#    active: prod
   # 文件上传
   servlet:
     multipart:
@@ -40,7 +42,7 @@ token:
   # 令牌密钥
   secret: abcdefghijklmnopqrstuvwxyza
   # 令牌有效期(默认30分钟)
-  expireTime: 30
+  expireTime: 300
 
 # MyBatis配置
 mybatis:

+ 25 - 0
ruoyi-admin/src/main/resources/docx4j.properties

@@ -0,0 +1,25 @@
+# Page size: use a value from org.docx4j.model.structure.PageSizePaper enum
+# eg A4, LETTER
+docx4j.PageSize=LETTER
+# Page size: use a value from org.docx4j.model.structure.MarginsWellKnown enum
+docx4j.PageMargins=NORMAL
+docx4j.PageOrientationLandscape=false
+# Page size: use a value from org.pptx4j.model.SlideSizesWellKnown enum
+# eg A4, LETTER
+pptx4j.PageSize=LETTER
+pptx4j.PageOrientationLandscape=false
+# These will be injected into docProps/app.xml
+# if App.Write=true
+docx4j.App.write=true
+docx4j.Application=docx4j
+docx4j.AppVersion=6.1.2
+# of the form XX.YYYY where X and Y represent numerical values
+# These will be injected into docProps/core.xml
+docx4j.dc.write=true
+docx4j.dc.creator.value=docx4j
+docx4j.dc.lastModifiedBy.value=docx4j
+#
+#docx4j.McPreprocessor=true
+# If you haven't configured log4j yourself
+# docx4j will autoconfigure it. Set this to true to disable that
+docx4j.Log4j.Configurator.disabled=false

BIN
ruoyi-admin/src/main/resources/traineddata/chi_sim.traineddata


+ 124 - 8
ruoyi-common/pom.xml

@@ -15,13 +15,83 @@
         common通用工具
     </description>
 
+
     <dependencies>
+        <!--thumbnailator 压缩工具-->
+        <dependency>
+            <groupId>net.coobird</groupId>
+            <artifactId>thumbnailator</artifactId>
+            <version>0.4.8</version>
+        </dependency>
+        <dependency>
+            <groupId>commons-fileupload</groupId>
+            <artifactId>commons-fileupload</artifactId>
+            <version>1.3.1</version>
+        </dependency>
+        <!--图片识别文字-->
+        <dependency>
+            <groupId>net.sourceforge.tess4j</groupId>
+            <artifactId>tess4j</artifactId>
+            <version>5.3.0</version>
+        </dependency>
+        <!--imageio-jpeg CMYK模式读取支持-->
+        <dependency>
+            <groupId>com.twelvemonkeys.imageio</groupId>
+            <artifactId>imageio-jpeg</artifactId>
+            <version>3.6</version>
+        </dependency>
+        <!--   pdf文件处理包导入     -->
+        <dependency>
+            <groupId>org.apache.pdfbox</groupId>
+            <artifactId>pdfbox</artifactId>
+            <version>2.0.24</version>
+        </dependency>
 
+        <!--二维码-->
+        <dependency>
+            <groupId>com.google.zxing</groupId>
+            <artifactId>core</artifactId>
+            <version>3.5.1</version>
+        </dependency>
+        <dependency>
+            <groupId>com.google.zxing</groupId>
+            <artifactId>javase</artifactId>
+            <version>3.5.1</version>
+        </dependency>
+        <!--word签名-->
+        <dependency>
+            <groupId>org.docx4j</groupId>
+            <artifactId>docx4j</artifactId>
+            <version>6.1.2</version>
+        </dependency>
+        <!--阿里云人脸识别-->
+        <dependency>
+            <groupId>com.aliyun</groupId>
+            <artifactId>cloudauth20190307</artifactId>
+            <version>2.0.8</version>
+        </dependency>
+        <!--身份验证依赖-->
+        <dependency>
+            <groupId>com.aliyun</groupId>
+            <artifactId>credentials-java</artifactId>
+            <version>LATEST</version>
+        </dependency>
+        <!--压缩目录-->
+        <dependency>
+            <groupId>net.lingala.zip4j</groupId>
+            <artifactId>zip4j</artifactId>
+            <version>2.9.0</version>
+        </dependency>
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-all</artifactId>
+            <version>5.8.27</version>
+        </dependency>
         <!--阿里短信服务-->
         <dependency>
             <groupId>com.aliyun</groupId>
             <artifactId>dysmsapi20170525</artifactId>
-            <version>2.0.23</version>
+            <version>2.0.24</version>
         </dependency>
 
         <!-- Spring框架基本的核心工具 -->
@@ -59,19 +129,19 @@
             <groupId>org.apache.commons</groupId>
             <artifactId>commons-lang3</artifactId>
         </dependency>
-  
+
         <!-- JSON工具类 -->
         <dependency>
             <groupId>com.fasterxml.jackson.core</groupId>
             <artifactId>jackson-databind</artifactId>
         </dependency>
-        
+
         <!-- 动态数据源 -->
-		<dependency>
-			<groupId>com.baomidou</groupId>
-			<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
-			<version>3.5.2</version>
-		</dependency>
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
+            <version>3.5.2</version>
+        </dependency>
 
         <!-- 阿里JSON解析器 -->
         <dependency>
@@ -133,6 +203,52 @@
             <artifactId>javax.servlet-api</artifactId>
         </dependency>
 
+        <dependency>
+            <groupId>com.deepoove</groupId>
+            <artifactId>poi-tl</artifactId>
+            <version>1.12.2</version>
+        </dependency>
+        <dependency>
+            <groupId>com.squareup.okhttp3</groupId>
+            <artifactId>okhttp</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-compress</artifactId>
+            <version>1.19</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-mock</artifactId>
+            <version>2.0.8</version>
+            <scope>compile</scope>
+        </dependency>
+
+        <!---->
+        <dependency>
+            <groupId>cn.jpush.api</groupId>
+            <artifactId>jpush-client</artifactId>
+            <version>3.4.3</version>
+        </dependency>
+
+        <dependency>
+            <groupId>cn.jpush.api</groupId>
+            <artifactId>jiguang-common</artifactId>
+            <version>1.1.7</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.itextpdf</groupId>
+            <artifactId>itext-asian</artifactId>
+            <version>5.2.0</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.itextpdf</groupId>
+            <artifactId>itextpdf</artifactId>
+            <version>5.5.13</version>
+        </dependency>
+
     </dependencies>
 
 </project>

+ 11 - 0
ruoyi-common/src/main/java/com/ruoyi/common/config/RuoYiConfig.java

@@ -30,6 +30,9 @@ public class RuoYiConfig
     /** 验证码类型 */
     private static String captchaType;
 
+    /** 上传路径 */
+    private static String isYml;
+
     public String getName()
     {
         return name;
@@ -88,6 +91,14 @@ public class RuoYiConfig
         RuoYiConfig.captchaType = captchaType;
     }
 
+    public static String getIsYml() {
+        return isYml;
+    }
+
+    public void setIsYml(String isYml) {
+        RuoYiConfig.isYml = isYml;
+    }
+
     /**
      * 获取导入上传路径
      */

+ 18 - 0
ruoyi-common/src/main/java/com/ruoyi/common/constant/CommonConstants.java

@@ -21,6 +21,16 @@ public class CommonConstants {
     public static final String TWE = "12";
     public static final String YES = "是";
     public static final String NO = "否";
+    public static final String FRONT = "front";
+    public static final String BACK = "back";
+    public static final String RZDB = "RZDB";
+    public static final String A = "a";
+    public static final String B = "b";
+    public static final String C = "c";
+    public static final String D = "d";
+    public static final String E = "e";
+    public static final String F = "f";
+    public static final String Y = "Y";
 
     //角色权限
     //超级管理员
@@ -32,5 +42,13 @@ public class CommonConstants {
      * 短信登录验证码前缀
      */
     public static final String LOGIN_USER_SMS = "login_user_sms:";
+    /**
+     * 密码加密16位秘钥
+     */
+    public static final String LOGIN_PASSWORD_AES = "qwertyuiopasdfgh";
+    /**
+     * 百度ACCESS_TOKEN
+     */
+    public static final String BAI_DU_ACCESS_TOKEN = "BAI_DU_ACCESS_TOKEN:";
 
 }

+ 1 - 1
ruoyi-common/src/main/java/com/ruoyi/common/constant/UserConstants.java

@@ -73,6 +73,6 @@ public class UserConstants
     /**
      * 密码长度限制
      */
-    public static final int PASSWORD_MIN_LENGTH = 5;
+    public static final int PASSWORD_MIN_LENGTH = 8;
     public static final int PASSWORD_MAX_LENGTH = 20;
 }

+ 71 - 0
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/IdCardVo.java

@@ -0,0 +1,71 @@
+package com.ruoyi.common.core.domain;
+
+import java.io.Serializable;
+
+/**
+ * @Author: tjf
+ * @Date: 2024/4/23 14:58
+ * @Describe:
+ */
+public class IdCardVo implements Serializable {
+    private static final long serialVersionUID = 1L;
+    /**
+     * 身份证号码
+     */
+    private String idCard;
+    /**
+     * 姓名
+     */
+    private String name;
+    /**
+     * 图片
+     */
+    private String image;
+    /**
+     *-front:身份证含照片的一面
+     * -back:身份证带国徽的一面
+     */
+    private String idCardSide;
+
+    public String getIdCardSide() {
+        return idCardSide;
+    }
+
+    public void setIdCardSide(String idCardSide) {
+        this.idCardSide = idCardSide;
+    }
+
+    public String getIdCard() {
+        return idCard;
+    }
+
+    public void setIdCard(String idCard) {
+        this.idCard = idCard;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getImage() {
+        return image;
+    }
+
+    public void setImage(String image) {
+        this.image = image;
+    }
+
+    @Override
+    public String toString() {
+        return "IdCardVo{" +
+                "idCard='" + idCard + '\'' +
+                ", name='" + name + '\'' +
+                ", image='" + image + '\'' +
+                ", idCardSide='" + idCardSide + '\'' +
+                '}';
+    }
+}

+ 203 - 0
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/SysUserIdcardVo.java

@@ -0,0 +1,203 @@
+package com.ruoyi.common.core.domain;
+
+import com.ruoyi.common.annotation.Excel;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+/**
+ * 用户身份证信息对象 sys_user_idcard
+ * 
+ * @author boman
+ * @date 2024-04-22
+ */
+public class SysUserIdcardVo extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 用户ID */
+    private Long userId;
+
+    /** 身份证号码 */
+    private String idCard;
+
+    /** 真实姓名 */
+    @Excel(name = "真实姓名")
+    private String realName;
+
+    /** 失效日期 */
+    @Excel(name = "失效日期")
+    private String expirationDate;
+
+    /** 手机号码 */
+    @Excel(name = "手机号码")
+    private String phonenumber;
+
+    /** 居住地址 */
+    @Excel(name = "居住地址")
+    private String address;
+
+    /** 正面地址 */
+    @Excel(name = "正面地址")
+    private String front;
+
+    /** 反面地址 */
+    @Excel(name = "反面地址")
+    private String back;
+
+    /** 删除标志(0代表存在 2代表删除) */
+    private String delFlag;
+
+    /**
+     * 图片
+     */
+    private String image;
+    /**
+     * 认证结果
+     */
+    private String result;
+
+    /**
+     * MetaInfo环境参数,需要通过客户端SDK获取
+     *
+     * {"zimVer":"3.0.0","appVersion": "1","bioMetaInfo": "4.1.0:1150****,0","appName": "com.aliyun.antcloudauth","deviceType": "ios","osVersion": "iOS 10.3.2","apdidToken": "","deviceModel": "iPhone9,1"}
+     */
+    private String metaInfo;
+    /**
+     *     您的业务页面回跳的目标地址。
+     */
+    private String returnUrl;
+
+    public String getReturnUrl() {
+        return returnUrl;
+    }
+
+    public void setReturnUrl(String returnUrl) {
+        this.returnUrl = returnUrl;
+    }
+
+    public String getMetaInfo() {
+        return metaInfo;
+    }
+
+    public void setMetaInfo(String metaInfo) {
+        this.metaInfo = metaInfo;
+    }
+
+    public String getImage() {
+        return image;
+    }
+
+    public void setImage(String image) {
+        this.image = image;
+    }
+
+    public String getResult() {
+        return result;
+    }
+
+    public void setResult(String result) {
+        this.result = result;
+    }
+
+    public void setUserId(Long userId)
+    {
+        this.userId = userId;
+    }
+
+    public Long getUserId() 
+    {
+        return userId;
+    }
+    public void setIdCard(String idCard) 
+    {
+        this.idCard = idCard;
+    }
+
+    public String getIdCard() 
+    {
+        return idCard;
+    }
+    public void setRealName(String realName) 
+    {
+        this.realName = realName;
+    }
+
+    public String getRealName() 
+    {
+        return realName;
+    }
+    public void setExpirationDate(String expirationDate) 
+    {
+        this.expirationDate = expirationDate;
+    }
+
+    public String getExpirationDate() 
+    {
+        return expirationDate;
+    }
+    public void setPhonenumber(String phonenumber) 
+    {
+        this.phonenumber = phonenumber;
+    }
+
+    public String getPhonenumber() 
+    {
+        return phonenumber;
+    }
+    public void setAddress(String address) 
+    {
+        this.address = address;
+    }
+
+    public String getAddress() 
+    {
+        return address;
+    }
+    public void setFront(String front) 
+    {
+        this.front = front;
+    }
+
+    public String getFront() 
+    {
+        return front;
+    }
+    public void setBack(String back) 
+    {
+        this.back = back;
+    }
+
+    public String getBack() 
+    {
+        return back;
+    }
+    public void setDelFlag(String delFlag) 
+    {
+        this.delFlag = delFlag;
+    }
+
+    public String getDelFlag() 
+    {
+        return delFlag;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("userId", getUserId())
+            .append("idCard", getIdCard())
+            .append("realName", getRealName())
+            .append("expirationDate", getExpirationDate())
+            .append("phonenumber", getPhonenumber())
+            .append("address", getAddress())
+            .append("front", getFront())
+            .append("back", getBack())
+            .append("delFlag", getDelFlag())
+            .append("createBy", getCreateBy())
+            .append("createTime", getCreateTime())
+            .append("updateBy", getUpdateBy())
+            .append("updateTime", getUpdateTime())
+            .append("remark", getRemark())
+            .toString();
+    }
+}

+ 8 - 0
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeSelect.java

@@ -4,6 +4,7 @@ import java.io.Serializable;
 import java.util.List;
 import java.util.stream.Collectors;
 import com.fasterxml.jackson.annotation.JsonInclude;
+import com.ruoyi.common.core.domain.entity.IndustryCategory;
 import com.ruoyi.common.core.domain.entity.SysDept;
 import com.ruoyi.common.core.domain.entity.SysMenu;
 
@@ -38,6 +39,13 @@ public class TreeSelect implements Serializable
         this.children = dept.getChildren().stream().map(TreeSelect::new).collect(Collectors.toList());
     }
 
+    public TreeSelect(IndustryCategory category)
+    {
+        this.id = category.getCategoryId();
+        this.label = category.getCategoryName();
+        this.children = category.getChildren().stream().map(TreeSelect::new).collect(Collectors.toList());
+    }
+
     public TreeSelect(SysMenu menu)
     {
         this.id = menu.getMenuId();

+ 138 - 0
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/IndustryCategory.java

@@ -0,0 +1,138 @@
+package com.ruoyi.common.core.domain.entity;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.ruoyi.common.annotation.Excel;
+import com.ruoyi.common.core.domain.BaseEntity;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 行业类别对象 industry_category
+ * 
+ * @author ruoyi
+ * @date 2024-04-23
+ */
+public class IndustryCategory extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 行业类别id */
+    private Long categoryId;
+
+    /** 父类id */
+    @Excel(name = "父类id")
+    private Long parentId;
+
+    /** 祖级列表 */
+    @Excel(name = "祖级列表")
+    private String ancestors;
+
+    /** 行业类别名称 */
+    @Excel(name = "行业类别名称")
+    private String categoryName;
+
+    /** 显示顺序 */
+    @Excel(name = "显示顺序")
+    private Integer orderNum;
+
+    /** 状态(0正常 1停用) */
+    @Excel(name = "状态", readConverterExp = "0=正常,1=停用")
+    private String status;
+
+    /** 删除标志(0代表存在 2代表删除) */
+    private String delFlag;
+
+    /** 子部门 */
+    private List<IndustryCategory> children = new ArrayList<IndustryCategory>();
+
+    public List<IndustryCategory> getChildren() {
+        return children;
+    }
+
+    public void setChildren(List<IndustryCategory> children) {
+        this.children = children;
+    }
+
+    public void setCategoryId(Long categoryId)
+    {
+        this.categoryId = categoryId;
+    }
+
+    public Long getCategoryId() 
+    {
+        return categoryId;
+    }
+    public void setParentId(Long parentId) 
+    {
+        this.parentId = parentId;
+    }
+
+    public Long getParentId() 
+    {
+        return parentId;
+    }
+    public void setAncestors(String ancestors) 
+    {
+        this.ancestors = ancestors;
+    }
+
+    public String getAncestors() 
+    {
+        return ancestors;
+    }
+    public void setCategoryName(String categoryName) 
+    {
+        this.categoryName = categoryName;
+    }
+
+    public String getCategoryName() 
+    {
+        return categoryName;
+    }
+    public void setOrderNum(Integer orderNum) 
+    {
+        this.orderNum = orderNum;
+    }
+
+    public Integer getOrderNum() 
+    {
+        return orderNum;
+    }
+    public void setStatus(String status) 
+    {
+        this.status = status;
+    }
+
+    public String getStatus() 
+    {
+        return status;
+    }
+    public void setDelFlag(String delFlag) 
+    {
+        this.delFlag = delFlag;
+    }
+
+    public String getDelFlag() 
+    {
+        return delFlag;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("categoryId", getCategoryId())
+            .append("parentId", getParentId())
+            .append("ancestors", getAncestors())
+            .append("categoryName", getCategoryName())
+            .append("orderNum", getOrderNum())
+            .append("status", getStatus())
+            .append("delFlag", getDelFlag())
+            .append("createBy", getCreateBy())
+            .append("createTime", getCreateTime())
+            .append("updateBy", getUpdateBy())
+            .append("updateTime", getUpdateTime())
+            .toString();
+    }
+}

+ 35 - 0
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java

@@ -25,6 +25,9 @@ public class SysUser extends BaseEntity
     @Excel(name = "用户序号", cellType = ColumnType.NUMERIC, prompt = "用户编号")
     private Long userId;
 
+    /** 极光id */
+    private String jgId;
+
     /** 部门ID */
     @Excel(name = "部门编号", type = Type.IMPORT)
     private Long deptId;
@@ -37,6 +40,14 @@ public class SysUser extends BaseEntity
     @Excel(name = "用户名称")
     private String nickName;
 
+    /** 用户昵称 */
+    @Excel(name = "用户类型", readConverterExp = "00=系统用户,01=注册用户,02=管理用户")
+    private String userType;
+    /**
+     * 是否人脸认证 N:否 Y:是
+     */
+    private String initFace;
+
     /** 用户邮箱 */
     @Excel(name = "用户邮箱")
     private String email;
@@ -89,6 +100,22 @@ public class SysUser extends BaseEntity
     /** 角色ID */
     private Long roleId;
 
+    public String getInitFace() {
+        return initFace;
+    }
+
+    public void setInitFace(String initFace) {
+        this.initFace = initFace;
+    }
+
+    public String getUserType() {
+        return userType;
+    }
+
+    public void setUserType(String userType) {
+        this.userType = userType;
+    }
+
     public SysUser()
     {
 
@@ -297,6 +324,14 @@ public class SysUser extends BaseEntity
         this.roleId = roleId;
     }
 
+    public String getJgId() {
+        return jgId;
+    }
+
+    public void setJgId(String jgId) {
+        this.jgId = jgId;
+    }
+
     @Override
     public String toString() {
         return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)

+ 13 - 0
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginBody.java

@@ -27,6 +27,19 @@ public class LoginBody
      */
     private String uuid;
 
+    /**
+     * 登录模式:1:账号密码 2:短信验证码
+     */
+    private String type;
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
     public String getUsername()
     {
         return username;

+ 13 - 0
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/RegisterBody.java

@@ -7,5 +7,18 @@ package com.ruoyi.common.core.domain.model;
  */
 public class RegisterBody extends LoginBody
 {
+    /**
+     * code
+     */
+    private String code;
 
+    @Override
+    public String getCode() {
+        return code;
+    }
+
+    @Override
+    public void setCode(String code) {
+        this.code = code;
+    }
 }

+ 28 - 0
ruoyi-common/src/main/java/com/ruoyi/common/encoder/AesPasswordEncoder.java

@@ -0,0 +1,28 @@
+package com.ruoyi.common.encoder;
+
+import com.ruoyi.common.utils.AesUtil;
+import org.springframework.security.crypto.password.PasswordEncoder;
+
+import java.util.Objects;
+
+import static com.ruoyi.common.constant.CommonConstants.LOGIN_PASSWORD_AES;
+
+/**
+ * @Author: tjf
+ * @Date: 2024/4/16 11:05
+ * @Describe:
+ */
+public class AesPasswordEncoder implements PasswordEncoder {
+    @Override
+    public String encode(CharSequence rawPassword) {
+        if (rawPassword == null) {
+            throw new IllegalArgumentException("rawPassword cannot be null");
+        }
+        return AesUtil.encryptCBC(rawPassword.toString(),LOGIN_PASSWORD_AES);
+    }
+
+    @Override
+    public boolean matches(CharSequence rawPassword, String encodedPassword) {
+        return Objects.equals(AesUtil.encryptCBC(rawPassword.toString(), LOGIN_PASSWORD_AES), encodedPassword);
+    }
+}

+ 64 - 0
ruoyi-common/src/main/java/com/ruoyi/common/enums/FjType.java

@@ -0,0 +1,64 @@
+package com.ruoyi.common.enums;
+
+import org.omg.PortableInterceptor.INACTIVE;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 附件枚举
+ * @Author: tjf
+ * @Date: 2024/9/29 15:31
+ * @Describe:
+ */
+public enum FjType {
+    gdhyjy("gdhyjy",1),
+    rggzb("rggzb",2),
+    sdffpyn("sdffpyn",3),
+    frsfzrmx("frsfzrmx",4),
+    frsfzghm("frsfzghm",5),
+    frjhz("frjhz",6),
+    frhkbsy("frhkbsy",7),
+    frhkbbry("frhkbbry",8),
+    frhkbpoy("frhkbpoy",9),
+    sqqyzxbg("sqqyzxbg",10),
+    glqyzxbg("glqyzxbg",11),
+    qyfrzxbg("qyfrzxbg",12),
+    sjkgrzxbg("sjkgrzxbg",13),
+    nszm("nszm",14),
+    syndcwbb("syndcwbb",15),
+    dqcwbb("dqcwbb",16),
+    gxht("gxht",17),
+    jsyyhdzd("jsyyhdzd",18),
+    zyzhyhls("zyzhyhls",19),
+    jzdcbg("jzdcbg",20),
+    clhgb("clhgb",21),
+    psyjqpb("psyjqpb",22),
+    wtdbht("wtdbht",23);
+
+
+    private final String type;
+    private final Integer sort;
+
+    FjType(String type, Integer sort) {
+        this.type = type;
+        this.sort = sort;
+    }
+    public Integer getSort() {
+        return sort;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+
+    public static Integer getDriverType(String name) {
+        for (FjType type : FjType.values()) {
+            if (name.equals(type.getType())) {
+                return type.sort;
+            }
+        }
+        return 100;
+    }
+}

+ 206 - 0
ruoyi-common/src/main/java/com/ruoyi/common/utils/AesUtil.java

@@ -0,0 +1,206 @@
+package com.ruoyi.common.utils;
+
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.util.Base64Utils;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+import static com.ruoyi.common.constant.CommonConstants.LOGIN_PASSWORD_AES;
+
+/**
+ * @Author: tjf AES加密工具类
+ * @Date: 2024/4/16 10:09
+ * @Describe:
+ */
+public class AesUtil {
+    /**
+     * 日志相关
+     */
+    private static final Logger LOGGER = LoggerFactory.getLogger(AesUtil.class);
+    /**
+     * 编码
+     */
+    private static final String ENCODING = "UTF-8";
+    /**
+     * 算法定义
+     */
+    private static final String AES_ALGORITHM = "AES";
+    /**
+     * 指定填充方式
+     */
+    private static final String CIPHER_PADDING = "AES/ECB/PKCS5Padding";
+    private static final String CIPHER_CBC_PADDING = "AES/CBC/PKCS5Padding";
+    /**
+     * 偏移量(CBC中使用,增强加密算法强度)
+     */
+    private static final String IV_SEED = "1234567812345678";
+
+    /**
+     * AES加密
+     *
+     * @param content 待加密内容
+     * @param aesKey  密码
+     * @return
+     */
+    public static String encrypt(String content, String aesKey) {
+        if (StringUtils.isBlank(content)) {
+            LOGGER.info("AES encrypt: the content is null!");
+            return null;
+        }
+        //判断秘钥是否为16位
+        if (StringUtils.isNotBlank(aesKey) && aesKey.length() == 16) {
+            try {
+                //对密码进行编码
+                byte[] bytes = aesKey.getBytes(ENCODING);
+                //设置加密算法,生成秘钥
+                SecretKeySpec skeySpec = new SecretKeySpec(bytes, AES_ALGORITHM);
+                // "算法/模式/补码方式"
+                Cipher cipher = Cipher.getInstance(CIPHER_PADDING);
+                //选择加密
+                cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
+                //根据待加密内容生成字节数组
+                byte[] encrypted = cipher.doFinal(content.getBytes(ENCODING));
+                //返回base64字符串
+                return Base64Utils.encodeToString(encrypted);
+            } catch (Exception e) {
+                LOGGER.info("AES encrypt exception:" + e.getMessage());
+                throw new RuntimeException(e);
+            }
+
+        } else {
+            LOGGER.info("AES encrypt: the aesKey is null or error!");
+            return null;
+        }
+    }
+
+    /**
+     * 解密
+     *
+     * @param content 待解密内容
+     * @param aesKey  密码
+     * @return
+     */
+    public static String decrypt(String content, String aesKey) {
+        if (StringUtils.isBlank(content)) {
+            LOGGER.info("AES decrypt: the content is null!");
+            return null;
+        }
+        //判断秘钥是否为16位
+        if (StringUtils.isNotBlank(aesKey) && aesKey.length() == 16) {
+            try {
+                //对密码进行编码
+                byte[] bytes = aesKey.getBytes(ENCODING);
+                //设置解密算法,生成秘钥
+                SecretKeySpec skeySpec = new SecretKeySpec(bytes, AES_ALGORITHM);
+                // "算法/模式/补码方式"
+                Cipher cipher = Cipher.getInstance(CIPHER_PADDING);
+                //选择解密
+                cipher.init(Cipher.DECRYPT_MODE, skeySpec);
+
+                //先进行Base64解码
+                byte[] decodeBase64 = Base64Utils.decodeFromString(content);
+
+                //根据待解密内容进行解密
+                byte[] decrypted = cipher.doFinal(decodeBase64);
+                //将字节数组转成字符串
+                return new String(decrypted, ENCODING);
+            } catch (Exception e) {
+                LOGGER.info("AES decrypt exception:" + e.getMessage());
+                throw new RuntimeException(e);
+            }
+
+        } else {
+            LOGGER.info("AES decrypt: the aesKey is null or error!");
+            return null;
+        }
+    }
+
+    /**
+     * AES_CBC加密
+     *
+     * @param content 待加密内容
+     * @param aesKey  密码
+     * @return
+     */
+    public static String encryptCBC(String content, String aesKey) {
+        if (StringUtils.isBlank(content)) {
+            LOGGER.info("AES_CBC encrypt: the content is null!");
+            return null;
+        }
+        //判断秘钥是否为16位
+        if (StringUtils.isNotBlank(aesKey) && aesKey.length() == 16) {
+            try {
+                //对密码进行编码
+                byte[] bytes = aesKey.getBytes(ENCODING);
+                //设置加密算法,生成秘钥
+                SecretKeySpec skeySpec = new SecretKeySpec(bytes, AES_ALGORITHM);
+                // "算法/模式/补码方式"
+                Cipher cipher = Cipher.getInstance(CIPHER_CBC_PADDING);
+                //偏移
+                IvParameterSpec iv = new IvParameterSpec(IV_SEED.getBytes(ENCODING));
+                //选择加密
+                cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
+                //根据待加密内容生成字节数组
+                byte[] encrypted = cipher.doFinal(content.getBytes(ENCODING));
+                //返回base64字符串
+                return Base64Utils.encodeToString(encrypted);
+            } catch (Exception e) {
+                LOGGER.info("AES_CBC encrypt exception:" + e.getMessage());
+                throw new RuntimeException(e);
+            }
+
+        } else {
+            LOGGER.info("AES_CBC encrypt: the aesKey is null or error!");
+            return null;
+        }
+    }
+
+    /**
+     * AES_CBC解密
+     *
+     * @param content 待解密内容
+     * @param aesKey  密码
+     * @return
+     */
+    public static String decryptCBC(String content, String aesKey) {
+        if (StringUtils.isBlank(content)) {
+            LOGGER.info("AES_CBC decrypt: the content is null!");
+            return null;
+        }
+        //判断秘钥是否为16位
+        if (StringUtils.isNotBlank(aesKey) && aesKey.length() == 16) {
+            try {
+                //对密码进行编码
+                byte[] bytes = aesKey.getBytes(ENCODING);
+                //设置解密算法,生成秘钥
+                SecretKeySpec skeySpec = new SecretKeySpec(bytes, AES_ALGORITHM);
+                //偏移
+                IvParameterSpec iv = new IvParameterSpec(IV_SEED.getBytes(ENCODING));
+                // "算法/模式/补码方式"
+                Cipher cipher = Cipher.getInstance(CIPHER_CBC_PADDING);
+                //选择解密
+                cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
+
+                //先进行Base64解码
+                byte[] decodeBase64 = Base64Utils.decodeFromString(content);
+
+                //根据待解密内容进行解密
+                byte[] decrypted = cipher.doFinal(decodeBase64);
+                //将字节数组转成字符串
+                return new String(decrypted, ENCODING);
+            } catch (Exception e) {
+                LOGGER.info("AES_CBC decrypt exception:" + e.getMessage());
+                throw new RuntimeException(e);
+            }
+        } else {
+            LOGGER.info("AES_CBC decrypt: the aesKey is null or error!");
+            return null;
+        }
+    }
+}
+

+ 65 - 0
ruoyi-common/src/main/java/com/ruoyi/common/utils/Base64Util.java

@@ -0,0 +1,65 @@
+package com.ruoyi.common.utils;
+
+/**
+ * Base64 工具类
+ */
+public class Base64Util {
+    private static final char last2byte = (char) Integer.parseInt("00000011", 2);
+    private static final char last4byte = (char) Integer.parseInt("00001111", 2);
+    private static final char last6byte = (char) Integer.parseInt("00111111", 2);
+    private static final char lead6byte = (char) Integer.parseInt("11111100", 2);
+    private static final char lead4byte = (char) Integer.parseInt("11110000", 2);
+    private static final char lead2byte = (char) Integer.parseInt("11000000", 2);
+    private static final char[] encodeTable = new char[]{'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};
+
+    public Base64Util() {
+    }
+
+    public static String encode(byte[] from) {
+        StringBuilder to = new StringBuilder((int) ((double) from.length * 1.34D) + 3);
+        int num = 0;
+        char currentByte = 0;
+
+        int i;
+        for (i = 0; i < from.length; ++i) {
+            for (num %= 8; num < 8; num += 6) {
+                switch (num) {
+                    case 0:
+                        currentByte = (char) (from[i] & lead6byte);
+                        currentByte = (char) (currentByte >>> 2);
+                    case 1:
+                    case 3:
+                    case 5:
+                    default:
+                        break;
+                    case 2:
+                        currentByte = (char) (from[i] & last6byte);
+                        break;
+                    case 4:
+                        currentByte = (char) (from[i] & last4byte);
+                        currentByte = (char) (currentByte << 2);
+                        if (i + 1 < from.length) {
+                            currentByte = (char) (currentByte | (from[i + 1] & lead2byte) >>> 6);
+                        }
+                        break;
+                    case 6:
+                        currentByte = (char) (from[i] & last2byte);
+                        currentByte = (char) (currentByte << 4);
+                        if (i + 1 < from.length) {
+                            currentByte = (char) (currentByte | (from[i + 1] & lead4byte) >>> 4);
+                        }
+                }
+
+                to.append(encodeTable[currentByte]);
+            }
+        }
+
+        if (to.length() % 4 != 0) {
+            for (i = 4 - to.length() % 4; i > 0; --i) {
+                to.append("=");
+            }
+        }
+
+        return to.toString();
+    }
+}

+ 114 - 5
ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java

@@ -3,11 +3,8 @@ package com.ruoyi.common.utils;
 import java.lang.management.ManagementFactory;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
-import java.time.LocalDate;
-import java.time.LocalDateTime;
-import java.time.LocalTime;
-import java.time.ZoneId;
-import java.time.ZonedDateTime;
+import java.time.*;
+import java.util.Calendar;
 import java.util.Date;
 import org.apache.commons.lang3.time.DateFormatUtils;
 
@@ -53,6 +50,11 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils
         return dateTimeNow(YYYY_MM_DD);
     }
 
+    public static String getYear()
+    {
+        return dateTimeNow(YYYY);
+    }
+
     public static final String getTime()
     {
         return dateTimeNow(YYYY_MM_DD_HH_MM_SS);
@@ -188,4 +190,111 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils
         ZonedDateTime zdt = localDateTime.atZone(ZoneId.systemDefault());
         return Date.from(zdt.toInstant());
     }
+
+    /**
+     * 增加 Date ==> LocalDate
+     */
+    public static LocalDate toLocalDate(Date date)
+    {
+        // 转换为java.time.LocalDate
+        LocalDate localDate = date.toInstant()
+                .atZone(ZoneId.systemDefault())
+                .toLocalDate();
+        return localDate;
+    }
+
+    public static int getWeekOfMonth(Date date)
+    {
+        Calendar calendar = Calendar.getInstance();
+        // 设置每周的第一天是周一(Calendar.MONDAY = 2)
+        calendar.setFirstDayOfWeek(Calendar.MONDAY);
+        // 设置一周的最小天数为1天(不足一周则补至下周)
+        calendar.setMinimalDaysInFirstWeek(1);
+        calendar.setTime(date);
+        int weekOfMonth = calendar.get(Calendar.WEEK_OF_MONTH);
+        return weekOfMonth;
+    }
+    /**
+     * 获取时间戳
+     *
+     * @return
+     */
+    public static String getUnix() {
+        return Long.toString(System.currentTimeMillis() / 1000L);
+    }
+
+    /**
+     * 返回 年月日小时分秒 毫秒
+     *
+     * @return yyyyMMddHHmmssS
+     */
+    public static String getTodayChar() {
+        String dateString = DateFormatUtils.format(new Date(), "yyyyMMddHHmmssS");
+        int length = dateString.length();
+
+        if (length < 17) {
+            StringBuilder endStr = new StringBuilder(dateString.substring(14, length));
+            int len = endStr.length();
+            for (int i = 0; i < 3 - len; i++) {
+                endStr.insert(0, "0");
+            }
+            dateString = dateString.substring(0, 14) + endStr;
+        }
+        return dateString;
+    }
+
+    /**
+     * 判断一个字字符串能不能转成LONG
+     *
+     * @return yyyyMMddHHmmssS
+     */
+    public static boolean isNumeric(String strNum) {
+        try {
+            // 尝试将字符串转换为数字
+            Long num = Long.parseLong(strNum);
+            // 是数字,返回true
+            return true;
+        } catch (NumberFormatException e) {
+            // 不是数字,捕获异常并返回false
+            return false;
+        }
+    }
+
+    /**
+     * 获取当前月
+     *
+     * @return
+     */
+    public static String getMonth()
+    {
+        LocalDate currentDate = LocalDate.now();
+        int currentMonth = currentDate.getMonthValue();
+        return String.valueOf(currentMonth);
+    }
+
+    /**
+     * 获取当前日
+     *
+     * @return
+     */
+    public static String getDay()
+    {
+        LocalDate now = LocalDate.now();
+        int day = now.getDayOfMonth();
+        return String.valueOf(day);
+    }
+
+    /**
+     * 两个日期之间相差的月数
+     * @param date1 开始时间
+     * @param date2 结束时间
+     * @return
+     */
+    public static int calculateMonths(String date1, String date2) {
+        LocalDate localDate1 = LocalDate.parse(date1);
+        LocalDate localDate2 = LocalDate.parse(date2);
+        Period period = Period.between(localDate1, localDate2);
+        return period.getMonths();
+    }
+
 }

+ 72 - 0
ruoyi-common/src/main/java/com/ruoyi/common/utils/FileUtil.java

@@ -0,0 +1,72 @@
+package com.ruoyi.common.utils;
+
+import java.io.*;
+
+/**
+ * 文件读取工具类
+ */
+public class FileUtil {
+
+    /**
+     * 读取文件内容,作为字符串返回
+     */
+    public static String readFileAsString(String filePath) throws IOException {
+        File file = new File(filePath);
+        if (!file.exists()) {
+            throw new FileNotFoundException(filePath);
+        } 
+
+        if (file.length() > 1024 * 1024 * 1024) {
+            throw new IOException("File is too large");
+        } 
+
+        StringBuilder sb = new StringBuilder((int) (file.length()));
+        // 创建字节输入流  
+        FileInputStream fis = new FileInputStream(filePath);  
+        // 创建一个长度为10240的Buffer
+        byte[] bbuf = new byte[10240];  
+        // 用于保存实际读取的字节数  
+        int hasRead = 0;  
+        while ( (hasRead = fis.read(bbuf)) > 0 ) {  
+            sb.append(new String(bbuf, 0, hasRead));  
+        }  
+        fis.close();  
+        return sb.toString();
+    }
+
+    /**
+     * 根据文件路径读取byte[] 数组
+     */
+    public static byte[] readFileByBytes(String filePath) throws IOException {
+        File file = new File(filePath);
+        if (!file.exists()) {
+            throw new FileNotFoundException(filePath);
+        } else {
+            ByteArrayOutputStream bos = new ByteArrayOutputStream((int) file.length());
+            BufferedInputStream in = null;
+
+            try {
+                in = new BufferedInputStream(new FileInputStream(file));
+                short bufSize = 1024;
+                byte[] buffer = new byte[bufSize];
+                int len1;
+                while (-1 != (len1 = in.read(buffer, 0, bufSize))) {
+                    bos.write(buffer, 0, len1);
+                }
+
+                byte[] var7 = bos.toByteArray();
+                return var7;
+            } finally {
+                try {
+                    if (in != null) {
+                        in.close();
+                    }
+                } catch (IOException var14) {
+                    var14.printStackTrace();
+                }
+
+                bos.close();
+            }
+        }
+    }
+}

+ 77 - 0
ruoyi-common/src/main/java/com/ruoyi/common/utils/HttpUtil.java

@@ -0,0 +1,77 @@
+package com.ruoyi.common.utils;
+
+import java.io.BufferedReader;
+import java.io.DataOutputStream;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * http 工具类
+ */
+public class HttpUtil {
+
+    public static String post(String requestUrl, String accessToken, String params)
+            throws Exception {
+        String contentType = "application/x-www-form-urlencoded";
+        return HttpUtil.post(requestUrl, accessToken, contentType, params);
+    }
+
+    public static String post(String requestUrl, String accessToken, String contentType, String params)
+            throws Exception {
+        String encoding = "UTF-8";
+        if (requestUrl.contains("nlp")) {
+            encoding = "GBK";
+        }
+        return HttpUtil.post(requestUrl, accessToken, contentType, params, encoding);
+    }
+
+    public static String post(String requestUrl, String accessToken, String contentType, String params, String encoding)
+            throws Exception {
+        String url = requestUrl + "?access_token=" + accessToken;
+        return HttpUtil.postGeneralUrl(url, contentType, params, encoding);
+    }
+
+    public static String postGeneralUrl(String generalUrl, String contentType, String params, String encoding)
+            throws Exception {
+        URL url = new URL(generalUrl);
+        // 打开和URL之间的连接
+        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+        connection.setRequestMethod("POST");
+        // 设置通用的请求属性
+        connection.setRequestProperty("Content-Type", contentType);
+        connection.setRequestProperty("Connection", "Keep-Alive");
+        connection.setUseCaches(false);
+        connection.setDoOutput(true);
+        connection.setDoInput(true);
+
+        // 得到请求的输出流对象
+        DataOutputStream out = new DataOutputStream(connection.getOutputStream());
+        out.write(params.getBytes(encoding));
+        out.flush();
+        out.close();
+
+        // 建立实际的连接
+        connection.connect();
+        // 获取所有响应头字段
+        Map<String, List<String>> headers = connection.getHeaderFields();
+        // 遍历所有的响应头字段
+        for (String key : headers.keySet()) {
+            System.err.println(key + "--->" + headers.get(key));
+        }
+        // 定义 BufferedReader输入流来读取URL的响应
+        BufferedReader in = null;
+        in = new BufferedReader(
+                new InputStreamReader(connection.getInputStream(), encoding));
+        String result = "";
+        String getLine;
+        while ((getLine = in.readLine()) != null) {
+            result += getLine;
+        }
+        in.close();
+        System.err.println("result:" + result);
+        return result;
+    }
+}

+ 77 - 0
ruoyi-common/src/main/java/com/ruoyi/common/utils/HttpUtils.java

@@ -0,0 +1,77 @@
+package com.ruoyi.common.utils;
+
+import java.io.BufferedReader;
+import java.io.DataOutputStream;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * http 工具类
+ */
+public class HttpUtils {
+
+    public static String post(String requestUrl, String accessToken, String params)
+            throws Exception {
+        String contentType = "application/x-www-form-urlencoded";
+        return HttpUtils.post(requestUrl, accessToken, contentType, params);
+    }
+
+    public static String post(String requestUrl, String accessToken, String contentType, String params)
+            throws Exception {
+        String encoding = "UTF-8";
+        if (requestUrl.contains("nlp")) {
+            encoding = "GBK";
+        }
+        return HttpUtils.post(requestUrl, accessToken, contentType, params, encoding);
+    }
+
+    public static String post(String requestUrl, String accessToken, String contentType, String params, String encoding)
+            throws Exception {
+        String url = requestUrl + "?access_token=" + accessToken;
+        return HttpUtils.postGeneralUrl(url, contentType, params, encoding);
+    }
+
+    public static String postGeneralUrl(String generalUrl, String contentType, String params, String encoding)
+            throws Exception {
+        URL url = new URL(generalUrl);
+        // 打开和URL之间的连接
+        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+        connection.setRequestMethod("POST");
+        // 设置通用的请求属性
+        connection.setRequestProperty("Content-Type", contentType);
+        connection.setRequestProperty("Connection", "Keep-Alive");
+        connection.setUseCaches(false);
+        connection.setDoOutput(true);
+        connection.setDoInput(true);
+
+        // 得到请求的输出流对象
+        DataOutputStream out = new DataOutputStream(connection.getOutputStream());
+        out.write(params.getBytes(encoding));
+        out.flush();
+        out.close();
+
+        // 建立实际的连接
+        connection.connect();
+        // 获取所有响应头字段
+        Map<String, List<String>> headers = connection.getHeaderFields();
+        // 遍历所有的响应头字段
+        for (String key : headers.keySet()) {
+            System.err.println(key + "--->" + headers.get(key));
+        }
+        // 定义 BufferedReader输入流来读取URL的响应
+        BufferedReader in = null;
+        in = new BufferedReader(
+                new InputStreamReader(connection.getInputStream(), encoding));
+        String result = "";
+        String getLine;
+        while ((getLine = in.readLine()) != null) {
+            result += getLine;
+        }
+        in.close();
+        System.err.println("result:" + result);
+        return result;
+    }
+}

+ 1478 - 0
ruoyi-common/src/main/java/com/ruoyi/common/utils/IdCardUtil.java

@@ -0,0 +1,1478 @@
+package com.ruoyi.common.utils;
+
+/**
+ * @Author: tjf
+ * @Date: 2024/4/17 9:35
+ * @Describe:
+ */
+
+import com.alibaba.fastjson2.JSONArray;
+import com.aliyun.cloudauth20190307.Client;
+import com.aliyun.cloudauth20190307.models.*;
+import com.aliyun.teaopenapi.models.Config;
+import com.aliyun.teautil.models.RuntimeOptions;
+
+import java.util.Arrays;
+import java.util.List;
+
+import cn.hutool.http.HttpUtil;
+
+import java.util.Arrays;
+import java.util.List;
+
+import com.aliyun.cloudauth20190307.Client;
+import com.aliyun.cloudauth20190307.models.*;
+import com.aliyun.teaopenapi.models.Config;
+import com.aliyun.teautil.models.RuntimeOptions;
+import com.ruoyi.common.core.domain.SysUserIdcardVo;
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONObject;
+import com.ruoyi.common.core.domain.AjaxResult;
+import okhttp3.*;
+import org.apache.poi.util.IOUtils;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.SecretKeySpec;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.*;
+
+import static com.ruoyi.common.constant.CommonConstants.*;
+
+public class IdCardUtil {
+    /**
+     * 重要提示代码中所需工具类
+     * FileUtil,HttpUtil请从
+     * https://ai.baidu.com/file/658A35ABAB2D404FBF903F64D47C1F72
+     * https://ai.baidu.com/file/544D677F5D4E4F17B4122FBD60DB82B3
+     * 下载
+     * <p>
+     * https://cloud.baidu.com/doc/OCR/s/rk3h7xzck 文档地址
+     */
+
+    // aes key 从console控制台获取 身份证识别使用
+    static String aesKey = "ce539dc069ad0908";
+
+    static byte[] originAesKey = null;
+
+    /**
+     * 身份证识别
+     * {
+     * "log_id": "1559208562721579319",
+     * "direction": 0,
+     * "image_status": "normal",
+     * "photo": "/9j/4AAQSkZJRgABA......",
+     * "photo_location": {
+     * "width": 1189,
+     * "top": 638,
+     * "left": 2248,
+     * "height": 1483
+     * },
+     * "card_image": "/9j/4AAQSkZJRgABA......",
+     * "card_location": {
+     * "top": 328,
+     * "left": 275,
+     * "width": 1329,
+     * "height": 571
+     * },
+     * "words_result": {
+     * "住址": {
+     * "location": {
+     * "left": 267,
+     * "top": 453,
+     * "width": 459,
+     * "height": 99
+     * },
+     * "words": "南京市江宁区弘景大道3889号"
+     * },
+     * "公民身份号码": {
+     * "location": {
+     * "left": 443,
+     * "top": 681,
+     * "width": 589,
+     * "height": 45
+     * },
+     * "words": "330881199904173914"
+     * },
+     * "出生": {
+     * "location": {
+     * "left": 270,
+     * "top": 355,
+     * "width": 357,
+     * "height": 45
+     * },
+     * "words": "19990417"
+     * },
+     * "姓名": {
+     * "location": {
+     * "left": 267,
+     * "top": 176,
+     * "width": 152,
+     * "height": 50
+     * },
+     * "words": "伍云龙"
+     * },
+     * "性别": {
+     * "location": {
+     * "left": 269,
+     * "top": 262,
+     * "width": 33,
+     * "height": 52
+     * },
+     * "words": "男"
+     * },
+     * "民族": {
+     * "location": {
+     * "left": 492,
+     * "top": 279,
+     * "width": 30,
+     * "height": 37
+     * },
+     * "words": "汉"
+     * }
+     * },
+     * "words_result_num": 6
+     * }
+     * <p>
+     * <p>
+     * {
+     * "words_result": {
+     * "失效日期": {
+     * "words": "20390711",
+     * "location": {
+     * "top": 445,
+     * "left": 523,
+     * "width": 153,
+     * "height": 38
+     * }
+     * },
+     * "签发机关": {
+     * "words": "陆丰市公安局",
+     * "location": {
+     * "top": 377,
+     * "left": 339,
+     * "width": 195,
+     * "height": 38
+     * }
+     * },
+     * "签发日期": {
+     * "words": "20190606",
+     * "location": {
+     * "top": 445,
+     * "left": 343,
+     * "width": 152,
+     * "height": 38
+     * }
+     * }
+     * },
+     * "log_id": "1559208562721579328",
+     * "words_result_num": 3,
+     * "error_code": 0,
+     * "image_status": "normal"
+     * }
+     *
+     * @return
+     */
+    public static AjaxResult idCard(String image, String idCardSide) {
+        try {
+            // 文件路径
+            byte[] imgData = FileUtil.readFileByBytes(image);
+
+            String imgStr = encryptImg(aesKey, imgData);
+
+            String imgParam = URLEncoder.encode(imgStr, "UTF-8");
+            String url = "https://aip.baidubce.com/rest/2.0/ocr/v1/idcard";
+            //-front:身份证含照片的一面
+            //-back:身份证带国徽的一面
+            //自动检测身份证正反面,如果传参指定方向与图片相反,支持正常识别,返回参数image_status字段为"reversed_side"
+            String param = "id_card_side=" + idCardSide +
+                    "&image=" + imgParam +
+                    "&AESEncry=" + true;
+            String accessToken = getAccessToken("TvvuZOOh7MgnlDFnw11ln67n", "CY47OI0eKAzYBD2LO55SM3OITzsyq6DK");
+            String encryptResult = HttpUtils.post(url, accessToken, param);
+            String decryptResult = parseResult(encryptResult);
+            JSONObject jsonObject = JSON.parseObject(decryptResult);
+            String wordsResult = jsonObject.getString("words_result");
+            Map<String, Object> map = new HashMap<>(3);
+            if (StringUtils.isNotEmpty(wordsResult)) {
+                JSONObject jsonObjectWordsResult = JSON.parseObject(wordsResult);
+                if (FRONT.equals(idCardSide)) {
+                    String name = JSON.parseObject(jsonObjectWordsResult.getString("姓名")).getString("words");
+                    String address = JSON.parseObject(jsonObjectWordsResult.getString("住址")).getString("words");
+                    String idCard = JSON.parseObject(jsonObjectWordsResult.getString("公民身份号码")).getString("words");
+                    map.put("realName", name);
+                    map.put("address", address);
+                    map.put("idCard", idCard);
+                } else if (BACK.equals(idCardSide)) {
+                    String date = JSON.parseObject(jsonObjectWordsResult.getString("失效日期")).getString("words");
+                    map.put("expirationDate", date);
+                }
+            }
+            return AjaxResult.success(map);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return AjaxResult.error();
+    }
+
+    /**
+     * 加密图片
+     *
+     * @param aesKey
+     * @param imgData
+     * @return
+     * @throws Exception
+     */
+    private static String encryptImg(String aesKey, byte[] imgData) throws Exception {
+        originAesKey = AesKeyUtil.parseAesKey(aesKey);
+        byte[] encImgBytes = AesUtil.encrypt(imgData, originAesKey);
+        String imgStr = Base64Util.encodeBase64(encImgBytes);
+        return imgStr;
+    }
+
+    /**
+     * 解密结果
+     *
+     * @param encryptResult
+     * @return
+     * @throws Exception
+     */
+    private static String parseResult(String encryptResult) throws Exception {
+        JSONObject obj = JSONObject.parseObject(encryptResult);
+        String result = obj.getString("result");
+        byte[] arr = Base64Util.decodeBase64(result);
+        String decryptResult = new String(AesUtil.decrypt(arr, originAesKey));
+        return decryptResult;
+    }
+
+
+    static class AesKeyUtil {
+        private static final String HEX = "0123456789abcdef";
+
+        /**
+         * 获得原生的128位的aeskey
+         * 因为一个byte位8位最后生成的byte数组长度为16
+         * <p>
+         * 16 * 8 = 128
+         *
+         * @param hex
+         * @return
+         */
+        public static byte[] parseAesKey(String hex) throws Exception {
+            char[] data = hex.toCharArray();
+            if (data.length != 16) {
+                throw new Exception(" ase key illegal ");
+            }
+            return decode(hex.toCharArray());
+        }
+
+        private static byte[] decode(char[] data) throws IllegalArgumentException {
+            int len = data.length;
+
+            byte[] out = new byte[len];
+
+            for (int i = 0; i < len; i++) {
+                int f = toDigit(data[i]);
+                out[i] = (byte) (f);
+            }
+            return out;
+        }
+
+        private static int toDigit(char ch) {
+            return HEX.indexOf(ch);
+        }
+    }
+
+    static class AesUtil {
+
+        private static final String ALGORITHM = "AES";
+
+        private static final String ALGORITHM_STR = "AES/ECB/PKCS5Padding";
+
+        /**
+         * aes 加密
+         */
+        private static byte[] encrypt(byte[] src, byte[] aesKey) throws Exception {
+            Cipher cipher = getCipher(aesKey, Cipher.ENCRYPT_MODE);
+            byte[] ret = cipher.doFinal(src);
+            return ret;
+        }
+
+        /**
+         * aes 解密
+         */
+        public static byte[] decrypt(byte[] src, byte[] aesKey) throws Exception {
+            Cipher cipher = getCipher(aesKey, Cipher.DECRYPT_MODE);
+            byte[] original = cipher.doFinal(src);
+            return original;
+        }
+
+        private static Cipher getCipher(byte[] aesKey, int mode) throws Exception {
+            SecretKeySpec secretKeySpec = new SecretKeySpec(aesKey, ALGORITHM);
+            Cipher cipher = Cipher.getInstance(ALGORITHM_STR);
+            cipher.init(mode, secretKeySpec);
+            return cipher;
+        }
+    }
+
+    static class Base64Util {
+
+        private static Base64.Encoder ENCODER = Base64.getEncoder();
+
+        // base64 加密
+        private static Base64.Decoder DECODER = Base64.getDecoder();
+
+        /**
+         * base64加密
+         *
+         * @param arr
+         * @return
+         */
+        private static String encodeBase64(byte[] arr) {
+            String base64 = null;
+            try {
+                base64 = ENCODER.encodeToString(arr);
+            } catch (Exception e) {
+            }
+            return base64;
+        }
+
+        /**
+         * base64解密
+         *
+         * @param str
+         * @return
+         */
+        public static byte[] decodeBase64(String str) {
+            byte[] encodeBase64 = new byte[0];
+            try {
+                encodeBase64 = DECODER.decode(str);
+            } catch (Exception e) {
+            }
+            return encodeBase64;
+        }
+    }
+
+    /**
+     * 营业执照识别
+     * 重要提示代码中所需工具类
+     * FileUtil,Base64Util,HttpUtil,GsonUtils请从
+     * https://ai.baidu.com/file/658A35ABAB2D404FBF903F64D47C1F72
+     * https://ai.baidu.com/file/C8D81F3301E24D2892968F09AE1AD6E2
+     * https://ai.baidu.com/file/544D677F5D4E4F17B4122FBD60DB82B3
+     * https://ai.baidu.com/file/470B3ACCA3FE43788B5A963BF0B625F3
+     * 下载
+     */
+    public static AjaxResult businessLicense(String image) {
+        // 请求url
+        String url = "https://aip.baidubce.com/rest/2.0/ocr/v1/business_license";
+        try {
+            // 本地文件路径
+            byte[] imgData = FileUtil.readFileByBytes(image);
+            String imgStr = com.ruoyi.common.utils.Base64Util.encode(imgData);
+            String imgParam = URLEncoder.encode(imgStr, "UTF-8");
+            String param = "image=" + imgParam;
+            String accessToken = getAccessToken("TvvuZOOh7MgnlDFnw11ln67n", "CY47OI0eKAzYBD2LO55SM3OITzsyq6DK");
+            String result = HttpUtils.post(url, accessToken, param);
+            /**
+             *
+             {
+             "words_result": {
+             "经营范围": {
+             "location": {
+             "top": 589,
+             "left": 381,
+             "width": 90,
+             "height": 19
+             },
+             "words": "商务服务业"
+             },
+             "组成形式": {
+             "location": {
+             "top": -1,
+             "left": -1,
+             "width": 0,
+             "height": 0
+             },
+             "words": "无"
+             },
+             "法人": {
+             "location": {
+             "top": 537,
+             "left": 381,
+             "width": 36,
+             "height": 19
+             },
+             "words": "方平"
+             },
+             "证件编号": {
+             "location": {
+             "top": 218,
+             "left": 302,
+             "width": 140,
+             "height": 15
+             },
+             "words": "921MA190538210301"
+             },
+             "注册资本": {
+             "location": {
+             "top": 431,
+             "left": 1044,
+             "width": 152,
+             "height": 21
+             },
+             "words": "200万元"
+             },
+             "单位名称": {
+             "location": {
+             "top": 431,
+             "left": 384,
+             "width": 71,
+             "height": 20
+             },
+             "words": "有限公司"
+             },
+             "有效期": {
+             "location": {
+             "top": 536,
+             "left": 1044,
+             "width": 198,
+             "height": 20
+             },
+             "words": "长期"
+             },
+             "社会信用代码": {
+             "location": {
+             "top": 300,
+             "left": 241,
+             "width": 156,
+             "height": 16
+             },
+             "words": "10440119MA06M85"
+             },
+             "实收资本": {
+             "location": {
+             "top": -1,
+             "left": -1,
+             "width": 0,
+             "height": 0
+             },
+             "words": "无"
+             },
+             "有效期起始日期": {
+             "location": {
+             "top": 536,
+             "left": 1044,
+             "width": 198,
+             "height": 20
+             },
+             "words": "2019年01月01日"
+             },
+             "核准日期": {
+             "location": {
+             "top": 884,
+             "left": 1188,
+             "width": 199,
+             "height": 22
+             },
+             "words": "2019年01月01日"
+             },
+             "成立日期": {
+             "location": {
+             "top": 484,
+             "left": 1043,
+             "width": 126,
+             "height": 19
+             },
+             "words": "2019年01月01日"
+             },
+             "税务登记号": {
+             "location": {
+             "top": -1,
+             "left": -1,
+             "width": 0,
+             "height": 0
+             },
+             "words": "无"
+             },
+             "地址": {
+             "location": {
+             "top": 588,
+             "left": 1043,
+             "width": 55,
+             "height": 22
+             },
+             "words": "广州市"
+             },
+             "登记机关": {
+             "location": {
+             "top": 0,
+             "left": 0,
+             "width": 0,
+             "height": 0
+             },
+             "words": "无"
+             },
+             "类型": {
+             "location": {
+             "top": 484,
+             "left": 382,
+             "width": 258,
+             "height": 20
+             },
+             "words": "有限责任公司(自然人投资或控股)"
+             }
+             },
+             "direction": 0,
+             "words_result_num": 16,
+             "log_id": "3166723741167575145"
+             }
+             */
+            JSONObject jsonObject = JSONObject.parseObject(result);
+            String wordsResult = jsonObject.getString("words_result");
+            Map<String, Object> map = new HashMap<>(9);
+            if (StringUtils.isNotEmpty(wordsResult)) {
+                JSONObject jsonObjectWordsResult = JSON.parseObject(wordsResult);
+                String creditCode = JSON.parseObject(jsonObjectWordsResult.getString("社会信用代码")).getString("words");
+                String enterpriseName = JSON.parseObject(jsonObjectWordsResult.getString("单位名称")).getString("words");
+                String enterpriseType = JSON.parseObject(jsonObjectWordsResult.getString("类型")).getString("words");
+                String enterpriseAddress = JSON.parseObject(jsonObjectWordsResult.getString("地址")).getString("words");
+                String legalName = JSON.parseObject(jsonObjectWordsResult.getString("法人")).getString("words");
+                String registeredCapital = JSON.parseObject(jsonObjectWordsResult.getString("注册资本")).getString("words");
+                String establishData = JSON.parseObject(jsonObjectWordsResult.getString("成立日期")).getString("words");
+                String businessTerm = JSON.parseObject(jsonObjectWordsResult.getString("有效期")).getString("words");
+                String businessScope = JSON.parseObject(jsonObjectWordsResult.getString("经营范围")).getString("words");
+                map.put("creditCode", creditCode);
+                map.put("enterpriseName", enterpriseName);
+                map.put("enterpriseType", enterpriseType);
+                map.put("enterpriseAddress", enterpriseAddress);
+                map.put("legalName", legalName);
+                map.put("registeredCapital", registeredCapital);
+                map.put("establishData", establishData);
+                map.put("businessTerm", businessTerm);
+                map.put("businessScope", businessScope);
+            } else {
+                return AjaxResult.error("营业执照识别失败,请检查。");
+            }
+            return AjaxResult.success(map);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return AjaxResult.error();
+    }
+
+    /**
+     * 人脸识别
+     *
+     * @throws IOException
+     */
+    public static AjaxResult sample(SysUserIdcardVo sysUserIdcardVo) {
+        String image = sysUserIdcardVo.getImage();
+        String idCardNumber = sysUserIdcardVo.getIdCard();
+        String name = sysUserIdcardVo.getRealName();
+        if (StringUtils.isEmpty(image) || StringUtils.isEmpty(idCardNumber) || StringUtils.isEmpty(name)) {
+            return AjaxResult.error("参数不完整");
+        }
+        // image 可以通过 getFileContentAsBase64("C:\fakepath\1675840208844.png") 方法获取,如果Content-Type是application/x-www-form-urlencoded时,第二个参数传true
+        HashMap<String, Object> paramMap = new HashMap<>();
+        paramMap.put("access_token", getAccessToken("OmTDmo9hv4wll1ReYiRNJEfz", "vqnio9p7C17nbrkVar0MrHU4KOz2OXOr"));
+        paramMap.put("image", getFileContentAsBase64(image, false));
+        paramMap.put("image_type", "BASE64");
+        paramMap.put("id_card_number", idCardNumber);
+        paramMap.put("name", name);
+        paramMap.put("spoofing_control", "NORMAL");
+        paramMap.put("quality_control", "NORMAL");
+        //返回值
+        String post = HttpUtil.post("https://aip.baidubce.com/rest/2.0/face/v4/mingjing/verify", paramMap);
+        /**
+         * {
+         *     "log_id": 1370579072568000512,
+         *     "result": {
+         *         "score": 40.884,
+         *         "verify_status": 0
+         *     },
+         *     "dec_image": "/9j/4AAQSkZJRgABAgAAAQABAAD",
+         *     "risk_level": "3",
+         *     "risk_tag": [
+         *         "若判断为有风险,则会有风险标签json 数组告知风险类型,如:general_inject"
+         *     ]
+         * }
+         */
+        JSONObject jsonObject = JSONObject.parseObject(post);
+        Map<String, Object> map = new HashMap<>();
+        return AjaxResult.success(map);
+    }
+
+    /**
+     * 获取文件base64编码
+     *
+     * @param path      文件路径
+     * @param urlEncode 如果Content-Type是application/x-www-form-urlencoded时,传true
+     * @return base64编码信息,不带文件头
+     * @throws IOException IO异常
+     */
+    static String getFileContentAsBase64(String path, boolean urlEncode) {
+        byte[] b = new byte[0];
+        try {
+            b = Files.readAllBytes(Paths.get(path));
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        String base64 = Base64.getEncoder().encodeToString(b);
+        if (urlEncode) {
+            try {
+                base64 = URLEncoder.encode(base64, "utf-8");
+            } catch (UnsupportedEncodingException e) {
+                e.printStackTrace();
+            }
+        }
+        return base64;
+    }
+
+    /**
+     * 获取百度开放平台的AccessToken
+     * client_id: 必须参数,应用的API Key;
+     * client_secret: 必须参数,应用的Secret Key;不同的功能不同
+     *
+     * @return
+     */
+    public static String getAccessToken(String apiKey, String secretKey) {
+        String url = "https://aip.baidubce.com/oauth/2.0/token";
+        /**
+         *grant_type: 必须参数,固定为client_credentials;
+         *client_id: 必须参数,应用的API Key;
+         *client_secret: 必须参数,应用的Secret Key;
+         */
+        HashMap<String, Object> paramMap = new HashMap<>(3);
+        paramMap.put("grant_type", "client_credentials");
+        paramMap.put("client_id", apiKey);
+        paramMap.put("client_secret", secretKey);
+        String post = cn.hutool.http.HttpUtil.post(url, paramMap);
+        JSONObject jsonObject = JSONObject.parseObject(post);
+        String accessToken = jsonObject.getString("access_token");
+        return accessToken;
+    }
+
+
+    /**
+     * 人脸识别阿里云金融级实人认证
+     *
+     * @throws IOException
+     */
+    public static AjaxResult ocrSampleAliYun(SysUserIdcardVo sysUserIdcardVo) {
+
+        return AjaxResult.success(initFaceVerify(sysUserIdcardVo));
+    }
+
+    /**
+     * 阿里云调用人脸识别
+     * 每次开始认证前通过本接口获取CertifyId,用来串联认证请求中的各个接口。
+     */
+    public static Object initFaceVerify(SysUserIdcardVo sysUserIdcardVo) {
+        InitFaceVerifyRequest request = new InitFaceVerifyRequest();
+        // 请输入场景ID+L。1000009979场景id固定值
+        request.setSceneId(1000009979L);
+        // 设置商户请求的唯一标识。
+        request.setOuterOrderNo(UUID.randomUUID().toString().replaceAll("-", ""));
+        // 认证方案。
+        request.setProductCode("ID_PRO");
+        // 模式。要进行活体检测的类型。取值:
+        //LIVENESS(默认):眨眼动作活体检测。
+        //
+        //PHOTINUS_LIVENESS:眨眼动作活体+炫彩活体双重检测。
+        //
+        //MULTI_ACTION:多动作活体检测。当前为眨眼+任意摇头检测。
+        request.setModel("PHOTINUS_LIVENESS");
+        //不同证件类型,取值均为IDENTITY_CARD
+        request.setCertType("IDENTITY_CARD");
+        //您的终端用户的真实姓名
+        request.setCertName(sysUserIdcardVo.getRealName());
+        //您的终端用户的证件号码。
+        request.setCertNo(sysUserIdcardVo.getIdCard());
+        // MetaInfo环境参数。
+        request.setMetaInfo(sysUserIdcardVo.getMetaInfo());
+        //业务页面回跳的目标地址。
+        String returnUrl = sysUserIdcardVo.getReturnUrl();
+        if (StringUtils.isNotEmpty(returnUrl)) {
+            //H5的model不一样
+            request.setModel("MULTI_ACTION");
+            request.setReturnUrl(returnUrl);
+        }
+        //request.setMobile("130xxxxxxxx");
+        //request.setIp("114.xxx.xxx.xxx");
+        //request.setUserId("12345xxxx");
+        //request.setCallbackUrl("https://www.aliyundoc.com");
+        //request.setCallbackToken("xxxxx");
+        // 如需开启个人信息加密传输。
+        //request.setEncryptType("SM2");
+        //request.setCertName("BCRD/7ZkNy7Q*****M1BMBezZe8GaYHrLwyJv558w==");
+        //request.setCertNo("BMjsstxK3S4b1YH*****Pet8ECObfxmLN92SLsNg==");
+
+        // 推荐,支持服务路由。
+        InitFaceVerifyResponse response = initFaceVerifyAutoRoute(request);
+
+        // 不支持服务自动路由。
+        //InitFaceVerifyResponse response = initFaceVerify("cloudauth.cn-shanghai.aliyuncs.com", request);
+
+        response.getBody().getRequestId();
+        String certifyId = response.getBody().getResultObject().getCertifyId();
+
+        InitFaceVerifyResponseBody.InitFaceVerifyResponseBodyResultObject resultObject = response.getBody().getResultObject();
+
+        System.out.println(response.getBody().getRequestId());
+        System.out.println(response.getBody().getCode());
+        System.out.println(response.getBody().getMessage());
+        System.out.println(response.getBody().getResultObject() == null ? null
+                : response.getBody().getResultObject().getCertifyId());
+        return resultObject;
+    }
+
+    private static InitFaceVerifyResponse initFaceVerifyAutoRoute(InitFaceVerifyRequest request) {
+        // 第一个为主区域Endpoint,第二个为备区域Endpoint。
+        List<String> endpoints = Arrays.asList("cloudauth.cn-shanghai.aliyuncs.com", "cloudauth.cn-beijing.aliyuncs.com");
+        InitFaceVerifyResponse lastResponse = null;
+        for (int i = 0; i < endpoints.size(); i++) {
+            try {
+                InitFaceVerifyResponse response = initFaceVerify(endpoints.get(i), request);
+                lastResponse = response;
+
+                // 服务端错误,切换到下个区域调用。
+                if (response != null) {
+                    if (500 == response.getStatusCode()) {
+                        continue;
+                    }
+                    if (response.getBody() != null) {
+                        if ("500".equals(response.getBody().getCode())) {
+                            continue;
+                        }
+                    }
+                }
+
+                // 正常返回
+                return lastResponse;
+            } catch (Exception e) {
+                e.printStackTrace();
+                if (i == endpoints.size() - 1) {
+                    throw new RuntimeException(e);
+                }
+            }
+        }
+
+        return lastResponse;
+    }
+
+    private static InitFaceVerifyResponse initFaceVerify(String endpoint, InitFaceVerifyRequest request)
+            throws Exception {
+        // 阿里云账号AccessKey拥有所有API的访问权限,建议您使用RAM用户进行API访问或日常运维。
+        // 强烈建议不要把AccessKey ID和AccessKey Secret保存到工程代码里,否则可能导致AccessKey泄露,威胁您账号下所有资源的安全。
+        // 本示例通过阿里云Credentials工具从环境变量中读取AccessKey,来实现API访问的身份验证。如何配置环境变量,请参见https://help.aliyun.com/document_detail/378657.html。
+        Config credentialConfig = new Config();
+        credentialConfig.setType("access_key");
+        //使用阿里云RAM用户的AK。最小的权限
+        credentialConfig.setAccessKeyId("LTAI5tCwkQRjuJYzbohaveEz");
+        credentialConfig.setAccessKeySecret("8VW0H8GL7hmm5td8cYxO49FcVLPzOj");
+        credentialConfig.setEndpoint(endpoint);
+        Client client = new Client(credentialConfig);
+        // 设置http代理。
+        //config.setHttpProxy("http://xx.xx.xx.xx:xxxx");
+        // 设置https代理。
+        //config.setHttpsProxy("https://xx.xx.xx.xx:xxxx");
+
+
+        // 创建RuntimeObject实例并设置运行参数。
+        RuntimeOptions runtime = new RuntimeOptions();
+        runtime.readTimeout = 10000;
+        runtime.connectTimeout = 10000;
+
+        return client.initFaceVerifyWithOptions(request, runtime);
+    }
+
+
+    /**
+     * 图片文字识别
+     *
+     * @param filePath 本地文件路径
+     * @return
+     */
+    public static Map<String, Object> accurateBasic(String filePath) {
+        String imgParam = getFileContentAsBase64(filePath, true);
+        String param = "image=" + imgParam + "&detect_direction=true";
+        MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded");
+        // image 可以通过 getFileContentAsBase64("C:\fakepath\zhizhao.jpg") 方法获取,如果Content-Type是application/x-www-form-urlencoded时,第二个参数传true
+        RequestBody body = RequestBody.create(mediaType, param);
+        Request request = new Request.Builder()
+                .url("https://aip.baidubce.com/rest/2.0/ocr/v1/accurate_basic?access_token=" + getAccessToken("TvvuZOOh7MgnlDFnw11ln67n", "CY47OI0eKAzYBD2LO55SM3OITzsyq6DK"))
+                .method("POST", body)
+                .addHeader("Content-Type", "application/x-www-form-urlencoded")
+                .addHeader("Accept", "application/json")
+                .build();
+        try {
+/*            {
+                "words_result": [
+                    {
+                        "words": "http:/10.0.175.74/ahlm/loan/Sv-2024.07.04/jbview.afx.html.print.printer.html?window页码,2024(w9"
+                    },
+                    {
+                        "words": "安徽农金"
+                    },
+                    {
+                        "words": "借据"
+                    },
+                    {
+                        "words": "ARCU"
+                    },
+                    {
+                        "words": "贷款单位:安徽潜山农村商业银行股份有限公司塔畈支行"
+                    },
+                    {
+                        "words": "借款人:潜山和沐物流有限公司"
+                    },
+                    {
+                        "words": "客户编号:200101281091"
+                    },
+                    {
+                        "words": "证件号码:913408243487083682"
+                    },
+                    {
+                        "words": "借据编号:860066291011"
+                    },
+                    {
+                        "words": "借款合同编号:2397591220240003"
+                    },
+                    {
+                        "words": "借款日期:2024年08月09日"
+                    },
+                    {
+                        "words": "借款到期日:2025年08月09日"
+                    },
+                    {
+                        "words": "借款金额(大写):人民币贰佰万元整"
+                    },
+                    {
+                        "words": "(小写):¥2,000,000.00"
+                    },
+                    {
+                        "words": "担保方式:保证"
+                    },
+                    {
+                        "words": "借款用途说明:进货"
+                    },
+                    {
+                        "words": "利率种类:年利率"
+                    },
+                    {
+                        "words": "贷款利率:6.09000000%"
+                    },
+                    {
+                        "words": "第一联银行贷款债权凭证"
+                    },
+                    {
+                        "words": "还款方式:按月结息、到期一次性还本法"
+                    },
+                    {
+                        "words": "还款账号:20010128109166600000032"
+                    },
+                    {
+                        "words": "以上款项已转入借款人指定账户"
+                    },
+                    {
+                        "words": "贷款单位(签章"
+                    },
+                    {
+                        "words": "分书·00010X022"
+                    },
+                    {
+                        "words": "借款人(签章或按指印):"
+                    },
+                    {
+                        "words": "负责人:"
+                    },
+                    {
+                        "words": "法定代表人(负责人)"
+                    },
+                    {
+                        "words": "孙慧"
+                    },
+                    {
+                        "words": "客户经理"
+                    },
+                    {
+                        "words": "或授权代理人(签章)"
+                    },
+                    {
+                        "words": ".证件号码:"
+                    },
+                    {
+                        "words": "经办人:"
+                    },
+                    {
+                        "words": "网址:www.ahrcu.com"
+                    },
+                    {
+                        "words": "客服电话:96669"
+                    }
+                ],
+                "words_result_num": 34,
+                "direction": 0,
+                "log_id": 1824253359437875000
+            }*/
+            Response response = HTTP_CLIENT.newCall(request).execute();
+            String result = response.body().string();
+            if (StringUtils.isNotBlank(result)) {
+                JSONObject jsonObject = JSONObject.parseObject(result);
+                JSONArray wordsResult = jsonObject.getJSONArray("words_result");
+                Map<String, Object> bankMap = bank(wordsResult);
+                return bankMap;
+
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    /**
+     * 从图片识别中提取数据
+     *
+     * @param wordsResult
+     * @return
+     */
+    public static Map<String, Object> bank(JSONArray wordsResult) {
+        Map<String, Object> map = new HashMap<>(2);
+        for (int i = 0; i < wordsResult.size(); i++) {
+            String o = wordsResult.get(i).toString();
+            if (o.contains("\"words\":\"中国银行\"")) {
+                for (int p = 0; p < wordsResult.size(); p++) {
+                    String b = wordsResult.get(p).toString();
+                    if (b.contains("合同金额")) {
+                        String[] split = b.split(":");
+                        String cny = split[1].replace("CNY", "").replace("\"}", "").replace(",", "");
+                        double actuallyAmount = Double.parseDouble(cny) / 10000;
+                        map.put("actuallyAmount", actuallyAmount);
+                    }
+                    if (b.contains("起息日")) {
+                        String[] split = b.split(":");
+                        String actuallyTime = split[1].replace("\"}", "").replace("/", "-");
+                        map.put("actuallyTime", actuallyTime);
+                    }
+                }
+                break;
+            } else if (o.contains("\"words\":\"安徽农金\"")) {
+                for (int p = 0; p < wordsResult.size(); p++) {
+                    String b = wordsResult.get(p).toString();
+                    if (b.contains("(小写)")) {
+                        String[] split = b.split(":");
+                        String cny = split[1].replace("¥", "").replace("\"}", "").replace(",", "");
+                        double actuallyAmount = Double.parseDouble(cny) / 10000;
+                        map.put("actuallyAmount", actuallyAmount);
+                    }
+                    if (b.contains("借款日期")) {
+                        String[] split = b.split(":");
+                        String actuallyTime = split[1].replace("\"}", "").replace("年", "-").replace("月", "-").replace("日", "");
+                        map.put("actuallyTime", actuallyTime);
+                    }
+                }
+                break;
+            } else if (o.contains("\"words\":\"中国建设银行\"")) {
+                //[{"words":"中国建设银行"},{"words":"China Construction Bank"},{"words":"贷款开户放款复核单"},{"words":"交易日期:"},{"words":"20240808"},{"words":"交易流水号:"},{"words":"102015LN21723106881097611"},{"words":"客户编号:"},{"words":"033811000008657356"},{"words":"产品编码:"},{"words":"00000082"},{"words":"客户名称:"},{"words":"潜山县华达实业有限公司"},{"words":"产品名称:"},{"words":"流动资金贷款"},{"words":"币种名称:人民币"},{"words":"币种代码:156"},{"words":"贷款账号:"},{"words":"34050368430800000726"},{"words":"放款金额:"},{"words":"1000000.00"},{"words":"内部账号:"},{"words":"贷转存账号:"},{"words":"中建设银行股份有限公司"},{"words":"34050168480800000976"},{"words":"利率(%):3.750000"},{"words":"贷款放款日期:20240808"},{"words":"到期日期:"},{"words":"潜山支行"},{"words":"20250807"},{"words":"业务专用章"},{"words":"授权:"},{"words":"复核:"},{"words":"经办:"},{"words":"53596089vM"}]
+                for (int p = 0; p < wordsResult.size(); p++) {
+                    String b = wordsResult.get(p).toString();
+                    if (b.contains("交易日期")) {
+                        String result = wordsResult.get(p + 1).toString();
+                        String[] split = result.split(":");
+                        String actuallyTime = split[1].replace("}", "").replace("\"", "");
+                        map.put("actuallyTime", actuallyTime);
+                    }
+                    if (b.contains("放款金额")) {
+                        String result = wordsResult.get(p + 1).toString();
+                        String[] split = result.split(":");
+                        //"20240808"}
+                        String cny = split[1].replace("}", "").replace("\"", "");
+                        double actuallyAmount = Double.parseDouble(cny) / 10000;
+                        map.put("actuallyAmount", actuallyAmount);
+                    }
+                }
+                break;
+            }
+        }
+        return map;
+    }
+
+/*    public static void main(String[] args) {
+        String imgParam = getFileContentAsBase64("D:\\jianhang.jpg", true);
+        String param = "image=" + imgParam + "&detect_direction=true";
+        MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded");
+        // image 可以通过 getFileContentAsBase64("C:\fakepath\zhizhao.jpg") 方法获取,如果Content-Type是application/x-www-form-urlencoded时,第二个参数传true
+        RequestBody body = RequestBody.create(mediaType, param);
+        Request request = new Request.Builder()
+                .url("https://aip.baidubce.com/rest/2.0/ocr/v1/accurate_basic?access_token=" + getAccessToken("TvvuZOOh7MgnlDFnw11ln67n", "CY47OI0eKAzYBD2LO55SM3OITzsyq6DK"))
+                .method("POST", body)
+                .addHeader("Content-Type", "application/x-www-form-urlencoded")
+                .addHeader("Accept", "application/json")
+                .build();
+        try {
+            Response response = HTTP_CLIENT.newCall(request).execute();
+            String result = response.body().string();
+            if (StringUtils.isNotBlank(result)) {
+                JSONObject jsonObject = JSONObject.parseObject(result);
+                JSONArray wordsResult = jsonObject.getJSONArray("words_result");
+                Map<String, Object> bankMap = bank(wordsResult);
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
+    }*/
+
+    /**
+     * 图片文字识别
+     *
+     * @param filePath 本地文件路径
+     * @return
+     */
+    public static Map<String, Object> accurateBasicCj(String filePath) {
+        String imgParam = getFileContentAsBase64(filePath, true);
+        String param = "image=" + imgParam + "&detect_direction=true";
+        MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded");
+        // image 可以通过 getFileContentAsBase64("C:\fakepath\zhizhao.jpg") 方法获取,如果Content-Type是application/x-www-form-urlencoded时,第二个参数传true
+        RequestBody body = RequestBody.create(mediaType, param);
+        Request request = new Request.Builder()
+                .url("https://aip.baidubce.com/rest/2.0/ocr/v1/accurate_basic?access_token=" + getAccessToken("TvvuZOOh7MgnlDFnw11ln67n", "CY47OI0eKAzYBD2LO55SM3OITzsyq6DK"))
+                .method("POST", body)
+                .addHeader("Content-Type", "application/x-www-form-urlencoded")
+                .addHeader("Accept", "application/json")
+                .build();
+        try {
+/*            {
+                "words_result": [
+                    {
+                        "words": "http:/10.0.175.74/ahlm/loan/Sv-2024.07.04/jbview.afx.html.print.printer.html?window页码,2024(w9"
+                    },
+                    {
+                        "words": "安徽农金"
+                    },
+                    {
+                        "words": "借据"
+                    },
+                    {
+                        "words": "ARCU"
+                    },
+                    {
+                        "words": "贷款单位:安徽潜山农村商业银行股份有限公司塔畈支行"
+                    },
+                    {
+                        "words": "借款人:潜山和沐物流有限公司"
+                    },
+                    {
+                        "words": "客户编号:200101281091"
+                    },
+                    {
+                        "words": "证件号码:913408243487083682"
+                    },
+                    {
+                        "words": "借据编号:860066291011"
+                    },
+                    {
+                        "words": "借款合同编号:2397591220240003"
+                    },
+                    {
+                        "words": "借款日期:2024年08月09日"
+                    },
+                    {
+                        "words": "借款到期日:2025年08月09日"
+                    },
+                    {
+                        "words": "借款金额(大写):人民币贰佰万元整"
+                    },
+                    {
+                        "words": "(小写):¥2,000,000.00"
+                    },
+                    {
+                        "words": "担保方式:保证"
+                    },
+                    {
+                        "words": "借款用途说明:进货"
+                    },
+                    {
+                        "words": "利率种类:年利率"
+                    },
+                    {
+                        "words": "贷款利率:6.09000000%"
+                    },
+                    {
+                        "words": "第一联银行贷款债权凭证"
+                    },
+                    {
+                        "words": "还款方式:按月结息、到期一次性还本法"
+                    },
+                    {
+                        "words": "还款账号:20010128109166600000032"
+                    },
+                    {
+                        "words": "以上款项已转入借款人指定账户"
+                    },
+                    {
+                        "words": "贷款单位(签章"
+                    },
+                    {
+                        "words": "分书·00010X022"
+                    },
+                    {
+                        "words": "借款人(签章或按指印):"
+                    },
+                    {
+                        "words": "负责人:"
+                    },
+                    {
+                        "words": "法定代表人(负责人)"
+                    },
+                    {
+                        "words": "孙慧"
+                    },
+                    {
+                        "words": "客户经理"
+                    },
+                    {
+                        "words": "或授权代理人(签章)"
+                    },
+                    {
+                        "words": ".证件号码:"
+                    },
+                    {
+                        "words": "经办人:"
+                    },
+                    {
+                        "words": "网址:www.ahrcu.com"
+                    },
+                    {
+                        "words": "客服电话:96669"
+                    }
+                ],
+                "words_result_num": 34,
+                "direction": 0,
+                "log_id": 1824253359437875000
+            }*/
+            Response response = HTTP_CLIENT.newCall(request).execute();
+            String result = response.body().string();
+            if (StringUtils.isNotBlank(result)) {
+                JSONObject jsonObject = JSONObject.parseObject(result);
+                JSONArray wordsResult = jsonObject.getJSONArray("words_result");
+                Map<String, Object> bankMap = bankCj(wordsResult);
+                return bankMap;
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+    /**
+     * {
+     *     "words_result": [
+     *         {
+     *             "words": "-20230822-287806450001.pdf-Adobe Reader"
+     *         },
+     *         {
+     *             "words": "文档(D)"
+     *         },
+     *         {
+     *             "words": "工具①"
+     *         },
+     *         {
+     *             "words": "窗口(W)"
+     *         },
+     *         {
+     *             "words": "帮助H)"
+     *         },
+     *         {
+     *             "words": "/1"
+     *         },
+     *         {
+     *             "words": "125%"
+     *         },
+     *         {
+     *             "words": "查找"
+     *         },
+     *         {
+     *             "words": "中国银行"
+     *         },
+     *         {
+     *             "words": "贷款放款回单"
+     *         },
+     *         {
+     *             "words": "BANK OF CHINA"
+     *         },
+     *         {
+     *             "words": "客户号:572904279"
+     *         },
+     *         {
+     *             "words": "日期:2023年08月22日"
+     *         },
+     *         {
+     *             "words": "收款人账号:178257778412"
+     *         },
+     *         {
+     *             "words": "贷款账号:181273443198"
+     *         },
+     *         {
+     *             "words": "收款人名称:潜山县永杰竹业有限公司"
+     *         },
+     *         {
+     *             "words": "收款人开户行:中国银行潜山支行"
+     *         },
+     *         {
+     *             "words": "金额:CNY1,000,000.00"
+     *         },
+     *         {
+     *             "words": "人民币壹佰万元整"
+     *         },
+     *         {
+     *             "words": "合同金额:CNY1,000,000.00"
+     *         },
+     *         {
+     *             "words": "合同编号:15003616890"
+     *         },
+     *         {
+     *             "words": "起息日:2023/08/22"
+     *         },
+     *         {
+     *             "words": "到期日:2024/08/22"
+     *         },
+     *         {
+     *             "words": "借款人名称:潜山县永杰竹业有限公司"
+     *         },
+     *         {
+     *             "words": "收款人卡号:"
+     *         },
+     *         {
+     *             "words": "附言:"
+     *         },
+     *         {
+     *             "words": "中国银行股份有限公司"
+     *         },
+     *         {
+     *             "words": "电子回单专用章"
+     *         },
+     *         {
+     *             "words": "如您已通过银行网点取得相应纸质回单,请注意核对,勿重复记账!"
+     *         },
+     *         {
+     *             "words": "交易机构:08731"
+     *         },
+     *         {
+     *             "words": "交易渠道:柜台"
+     *         },
+     *         {
+     *             "words": "交易流水号:80114160-996"
+     *         },
+     *         {
+     *             "words": "经办:"
+     *         },
+     *         {
+     *             "words": "回单编号:2308220801141608"
+     *         },
+     *         {
+     *             "words": "回单验证码:24BN8WT36FM2"
+     *         },
+     *         {
+     *             "words": "打印时间:"
+     *         },
+     *         {
+     *             "words": "打印次数:"
+     *         },
+     *         {
+     *             "words": "次"
+     *         }
+     *     ],
+     *     "words_result_num": 38,
+     *     "direction": 0,
+     *     "log_id": 1825789540967617800
+     * }
+     */
+
+    /**
+     * 从图片识别中提取数据
+     *
+     * @param wordsResult
+     * @return
+     */
+    public static Map<String, Object> bankCj(JSONArray wordsResult) {
+        Map<String, Object> map = new HashMap<>(2);
+        map.put("dkdw", "");
+        map.put("jkr", "");
+        map.put("jkje", "");
+        map.put("jkytsm", "");
+        map.put("hksj", "");
+        int hksj = 0;
+        String strTime = null;
+        String endTime = null;
+        for (int i = 0; i < wordsResult.size(); i++) {
+            String o = wordsResult.get(i).toString();
+            if (o.contains("\"words\":\"中国银行\"")) {
+                map.put("zh", "中国银行");
+                for (int p = 0; p < wordsResult.size(); p++) {
+                    String b = wordsResult.get(p).toString();
+                    if (b.contains("收款人开户行")) {
+                        String[] split = b.split(":");
+                        String cny = split[1];
+                        map.put("dkdw", cny);
+                    }
+                    if (b.contains("借款人名称")) {
+                        String[] split = b.split(":");
+                        String cny = split[1];
+                        map.put("jkr", cny);
+                    }
+                    if (b.contains("合同金额")) {
+                        String[] split = b.split(":");
+                        String cny = split[1].replace("CNY", "").replace("\"}", "").replace(",", "");
+                        double actuallyAmount = Double.parseDouble(cny) / 10000;
+                        map.put("jkje", actuallyAmount);
+                    }
+                    if (b.contains("起息日")) {
+                        String[] split = b.split(":");
+                        strTime = split[1].replace("\"}", "").replace("/", "-");
+                        map.put("qxr", strTime);
+                    }
+                    if (b.contains("到期日")) {
+                        String[] split = b.split(":");
+                        endTime = split[1].replace("\"}", "").replace("/", "-");
+                        map.put("dqr", endTime);
+                    }
+                }
+                break;
+            } else if (o.contains("\"words\":\"安徽农金\"")) {
+                map.put("zh", "安徽农金");
+                for (int p = 0; p < wordsResult.size(); p++) {
+                    String b = wordsResult.get(p).toString();
+                    if (b.contains("贷款单位")) {
+                        String[] split = b.split(":");
+                        String cny = split[1];
+                        map.put("dkdw", cny);
+                    }
+                    if (b.contains("借款人")) {
+                        String[] split = b.split(":");
+                        String cny = split[1];
+                        map.put("jkr", cny);
+                    }
+                    if (b.contains("(小写)")) {
+                        String[] split = b.split(":");
+                        String cny = split[1].replace("¥", "").replace("\"}", "").replace(",", "");
+                        double actuallyAmount = Double.parseDouble(cny) / 10000;
+                        map.put("jkje", actuallyAmount);
+                    }
+                    if (b.contains("借款用途说明")) {
+                        String[] split = b.split(":");
+                        String cny = split[1];
+                        map.put("jkytsm", cny);
+                    }
+                    //计算还款时间
+                    if (b.contains("借款日期")) {
+                        String[] split = b.split(":");
+                        strTime = split[1].replace("\"}", "").replace("年", "-").replace("月", "-").replace("日", "");
+                        map.put("qxr", strTime);
+                    }
+                    if (b.contains("借款到日期")) {
+                        String[] split = b.split(":");
+                        endTime = split[1].replace("\"}", "").replace("年", "-").replace("月", "-").replace("日", "");
+                        map.put("dqr", endTime);
+                    }
+                }
+
+                break;
+            } else if (o.contains("\"words\":\"中国建设银行\"")) {
+                //[{"words":"中国建设银行"},{"words":"China Construction Bank"},{"words":"贷款开户放款复核单"},{"words":"交易日期:"},{"words":"20240808"},{"words":"交易流水号:"},{"words":"102015LN21723106881097611"},{"words":"客户编号:"},{"words":"033811000008657356"},{"words":"产品编码:"},{"words":"00000082"},{"words":"客户名称:"},{"words":"潜山县华达实业有限公司"},{"words":"产品名称:"},{"words":"流动资金贷款"},{"words":"币种名称:人民币"},{"words":"币种代码:156"},{"words":"贷款账号:"},{"words":"34050368430800000726"},{"words":"放款金额:"},{"words":"1000000.00"},{"words":"内部账号:"},{"words":"贷转存账号:"},{"words":"中建设银行股份有限公司"},{"words":"34050168480800000976"},{"words":"利率(%):3.750000"},{"words":"贷款放款日期:20240808"},{"words":"到期日期:"},{"words":"潜山支行"},{"words":"20250807"},{"words":"业务专用章"},{"words":"授权:"},{"words":"复核:"},{"words":"经办:"},{"words":"53596089vM"}]
+                map.put("zh", "中国建设银行");
+                map.put("dkdw", "中国建设银行");
+                for (int p = 0; p < wordsResult.size(); p++) {
+                    String b = wordsResult.get(p).toString();
+                    if (b.contains("客户名称")) {
+                        String result = wordsResult.get(p + 1).toString();
+                        String[] split = result.split(":");
+                        String cny = split[1];
+                        map.put("jkr", cny);
+                    }
+                    if (b.contains("放款金额")) {
+                        String result = wordsResult.get(p + 1).toString();
+                        String[] split = result.split(":");
+                        //"20240808"}
+                        String cny = split[1].replace("}", "").replace("\"", "");
+                        double actuallyAmount = Double.parseDouble(cny) / 10000;
+                        map.put("jkje", actuallyAmount);
+                    }
+                    if (b.contains("产品名称")) {
+                        String result = wordsResult.get(p + 1).toString();
+                        String[] split = result.split(":");
+                        String cny = split[1];
+                        map.put("jkytsm", cny);
+                    }
+                }
+                break;
+            }
+        }
+        if (StringUtils.isNotEmpty(strTime) && StringUtils.isNotEmpty(endTime)) {
+            hksj = DateUtils.calculateMonths(strTime, endTime);
+        }
+        if (hksj != 0) {
+            map.put("hksj", hksj);
+        }
+        return map;
+    }
+
+    /**
+     * 手写文字识别
+     */
+    /**
+     * 重要提示代码中所需工具类
+     * FileUtil,Base64Util,HttpUtil,GsonUtils请从
+     * https://ai.baidu.com/file/658A35ABAB2D404FBF903F64D47C1F72
+     * https://ai.baidu.com/file/C8D81F3301E24D2892968F09AE1AD6E2
+     * https://ai.baidu.com/file/544D677F5D4E4F17B4122FBD60DB82B3
+     * https://ai.baidu.com/file/470B3ACCA3FE43788B5A963BF0B625F3
+     * 下载
+     */
+    public static AjaxResult ocrHandWriting(String filePath) {
+        // 请求url
+        String url = "https://aip.baidubce.com/rest/2.0/ocr/v1/handwriting";
+        try {
+            // 本地文件路径
+            byte[] imgData = FileUtil.readFileByBytes(filePath);
+            String imgStr = Base64Util.encodeBase64(imgData);
+            String imgParam = URLEncoder.encode(imgStr, "UTF-8");
+
+            String param = "image=" + imgParam;
+
+            // 注意这里仅为了简化编码每一次请求都去获取access_token,线上环境access_token有过期时间, 客户端可自行缓存,过期后重新获取。
+            String accessToken = getAccessToken("TvvuZOOh7MgnlDFnw11ln67n", "CY47OI0eKAzYBD2LO55SM3OITzsyq6DK");
+
+            String result = HttpUtils.post(url, accessToken, param);
+            /**
+             * {
+             *     "log_id": 620759800,
+             *     "words_result": [
+             *         {
+             *             "location": {
+             *                 "left": 56,
+             *                 "top": 0,
+             *                 "width": 21,
+             *                 "height": 210
+             *             },
+             *             "words": "今天"
+             *         }
+             *     ],
+             *     "words_result_num": 1
+             * }
+             */
+            System.out.println(result);
+            return AjaxResult.success();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return null;
+
+    }
+
+
+    static final OkHttpClient HTTP_CLIENT = new OkHttpClient().newBuilder().build();
+}

+ 100 - 0
ruoyi-common/src/main/java/com/ruoyi/common/utils/ImageSizeUtil.java

@@ -0,0 +1,100 @@
+package com.ruoyi.common.utils;
+
+import net.coobird.thumbnailator.Thumbnails;
+import org.apache.commons.fileupload.FileItem;
+import org.apache.commons.fileupload.FileItemFactory;
+import org.apache.commons.fileupload.disk.DiskFileItemFactory;
+import org.springframework.web.multipart.MultipartFile;
+import org.springframework.web.multipart.commons.CommonsMultipartFile;
+import sun.misc.BASE64Decoder;
+import sun.misc.BASE64Encoder;
+
+import java.io.*;
+
+/**
+ * 获取图片尺寸和截图 工具类
+ *
+ * @author zhangxiaoyan
+ */
+public class ImageSizeUtil {
+    /**
+     * 压缩图片 并返回MultipartFile
+     * @param multiFile
+     * @return
+     * @throws Exception
+     */
+    public static MultipartFile compressImg(MultipartFile multiFile) {
+        long size = multiFile.getSize();
+        if (size> 0){
+            double fileSizeMb = size / (1024.0 * 1024.0);
+            if (fileSizeMb < 5){
+                return multiFile;
+            }
+        }
+        // 压缩图片
+        InputStream inputStream = null;
+        ByteArrayOutputStream bos = null;
+        MultipartFile multipartFile = null;
+        InputStream fileInput= null;
+        try {
+            inputStream = multiFile.getInputStream();
+            bos = new ByteArrayOutputStream();
+            // 压缩图片核心代码 scale设置压缩比例 越小压缩图片越小
+            Thumbnails.of(inputStream).scale(0.5f).outputQuality(1f).toOutputStream(bos);
+            fileInput = new ByteArrayInputStream(bos.toByteArray());
+            // 转换 MultipartFile
+            String fieldName = multiFile.getName();
+            String fileName = multiFile.getOriginalFilename();
+            String contentType = multiFile.getContentType();
+            multipartFile = getMulFileByFile(fileInput, fieldName, contentType, fileName);
+        } catch (IOException e) {
+            e.printStackTrace();
+        } finally {
+            try {
+                if (inputStream != null){
+                    inputStream.close();
+                }
+                if (bos != null){
+                    bos.close();
+                }
+                if (fileInput != null){
+                    fileInput.close();
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+
+            }
+        }
+        return multipartFile;
+    }
+
+    public static MultipartFile getMulFileByFile(InputStream fis,String fieldName,String contentType,String fileName) {
+        FileItem fileItem = createFileItem(fis,fieldName,contentType,fileName);
+        MultipartFile mfile = new CommonsMultipartFile(fileItem);
+        return mfile;
+    }
+
+    public static FileItem createFileItem(InputStream fis,String fieldName,String contentType,String fileName){
+        FileItemFactory factory = new DiskFileItemFactory(16, null);
+        FileItem item = factory.createItem(fieldName, contentType, false,fileName);
+        int bytesRead = 0;
+        byte[] buffer = new byte[8192];
+        try
+        {
+            OutputStream os = item.getOutputStream();
+            while ((bytesRead = fis.read(buffer, 0, 8192))!= -1)
+            {
+                os.write(buffer, 0, bytesRead);
+            }
+            os.close();
+            fis.close();
+        }
+        catch (IOException e)
+        {
+            e.printStackTrace();
+        }
+        return item;
+    }
+}
+
+

+ 260 - 0
ruoyi-common/src/main/java/com/ruoyi/common/utils/QRCodeUtils.java

@@ -0,0 +1,260 @@
+package com.ruoyi.common.utils;
+
+import com.google.zxing.*;
+import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
+import com.google.zxing.common.BitMatrix;
+import com.google.zxing.common.HybridBinarizer;
+import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
+import com.ruoyi.common.utils.uuid.UUID;
+
+import javax.imageio.ImageIO;
+import java.awt.*;
+import java.awt.geom.RoundRectangle2D;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.OutputStream;
+import java.util.Hashtable;
+
+/**
+ * @author tjf
+ * @Date: 2021/12/29/15:09
+ */
+public class QRCodeUtils {
+    private static final String CHARSET = "utf-8";
+    private static final String FORMAT_NAME = "JPG";
+    // 二维码尺寸
+    private static final int QRCODE_SIZE = 300;
+    // LOGO宽度
+    private static final int WIDTH = 60;
+    // LOGO高度
+    private static final int HEIGHT = 60;
+
+    private static BufferedImage createImage(String content, String imgPath,
+                                             boolean needCompress) throws Exception {
+        Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
+        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
+        hints.put(EncodeHintType.CHARACTER_SET, CHARSET);
+        hints.put(EncodeHintType.MARGIN, 1);
+        BitMatrix bitMatrix = new MultiFormatWriter().encode(content,
+                BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE, hints);
+        int width = bitMatrix.getWidth();
+        int height = bitMatrix.getHeight();
+        BufferedImage image = new BufferedImage(width, height,
+                BufferedImage.TYPE_INT_RGB);
+        for (int x = 0; x < width; x++) {
+            for (int y = 0; y < height; y++) {
+                image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000
+                        : 0xFFFFFFFF);
+            }
+        }
+        if (imgPath == null || "".equals(imgPath)) {
+            return image;
+        }
+        // 插入图片
+        QRCodeUtils.insertImage(image, imgPath, needCompress);
+        return image;
+    }
+
+    /**
+     * 插入LOGO
+     *
+     * @param source       二维码图片
+     * @param imgPath      LOGO图片地址
+     * @param needCompress 是否压缩
+     * @throws Exception
+     */
+    private static void insertImage(BufferedImage source, String imgPath,
+                                    boolean needCompress) throws Exception {
+        File file = new File(imgPath);
+        if (!file.exists()) {
+            System.err.println("" + imgPath + "   该文件不存在!");
+            return;
+        }
+        Image src = ImageIO.read(new File(imgPath));
+        int width = src.getWidth(null);
+        int height = src.getHeight(null);
+        if (needCompress) { // 压缩LOGO
+            if (width > WIDTH) {
+                width = WIDTH;
+            }
+            if (height > HEIGHT) {
+                height = HEIGHT;
+            }
+            Image image = src.getScaledInstance(width, height,
+                    Image.SCALE_SMOOTH);
+            BufferedImage tag = new BufferedImage(width, height,
+                    BufferedImage.TYPE_INT_RGB);
+            Graphics g = tag.getGraphics();
+            g.drawImage(image, 0, 0, null); // 绘制缩小后的图
+            g.dispose();
+            src = image;
+        }
+        // 插入LOGO
+        Graphics2D graph = source.createGraphics();
+        int x = (QRCODE_SIZE - width) / 2;
+        int y = (QRCODE_SIZE - height) / 2;
+        graph.drawImage(src, x, y, width, height, null);
+        Shape shape = new RoundRectangle2D.Float(x, y, width, width, 6, 6);
+        graph.setStroke(new BasicStroke(3f));
+        graph.draw(shape);
+        graph.dispose();
+    }
+
+    /**
+     * 生成二维码(内嵌LOGO)
+     *
+     * @param content      内容
+     * @param imgPath      LOGO地址
+     * @param destPath     存放目录
+     * @param needCompress 是否压缩LOGO
+     * @throws Exception
+     */
+    public static String encode(String content, String imgPath, String destPath,
+                                boolean needCompress) throws Exception {
+        BufferedImage image = QRCodeUtils.createImage(content, imgPath,
+                needCompress);
+        String date = DateUtils.datePath();
+        destPath = destPath+"/" + date;
+        mkdirs(destPath);
+        String file = UUID.randomUUID() + ".jpg";
+        File fileQR = new File(destPath + "/" + file);
+        ImageIO.write(image, FORMAT_NAME, fileQR);
+        return "/profile/qrUpload/"+date+"/"+file;
+    }
+
+
+    /**
+     * 生成二维码(内嵌LOGO) 返回传入的地址
+     *
+     * @param content      内容
+     * @param imgPath      LOGO地址
+     * @param destPath     存放目录
+     * @param needCompress 是否压缩LOGO
+     * @throws Exception
+     */
+    public static String encodeNodate(String content, String imgPath, String destPath,
+                                boolean needCompress) throws Exception {
+        BufferedImage image = QRCodeUtils.createImage(content, imgPath,
+                needCompress);
+        mkdirs(destPath);
+        String file = UUID.randomUUID() + ".jpg";
+        File fileQR = new File(destPath + "/" + file);
+        ImageIO.write(image, FORMAT_NAME, fileQR);
+        return destPath+"/"+file;
+    }
+
+
+    /**
+     * 当文件夹不存在时,mkdirs会自动创建多层目录,区别于mkdir.(mkdir如果父目录不存在则会抛出异常)
+     *
+     * @param destPath 存放目录
+     * @date 2013-12-11 上午10:16:36
+     */
+    public static void mkdirs(String destPath) {
+        File file = new File(destPath);
+        //当文件夹不存在时,mkdirs会自动创建多层目录,区别于mkdir.(mkdir如果父目录不存在则会抛出异常)
+        if (!file.exists() && !file.isDirectory()) {
+            file.mkdirs();
+        }
+    }
+
+    /**
+     * 生成二维码(内嵌LOGO)
+     *
+     * @param content  内容
+     * @param imgPath  LOGO地址
+     * @param destPath 存储地址
+     * @throws Exception
+     */
+    public static void encode(String content, String imgPath, String destPath)
+            throws Exception {
+        QRCodeUtils.encode(content, imgPath, destPath, false);
+    }
+
+    /**
+     * 生成二维码
+     *
+     * @param content      内容
+     * @param destPath     存储地址
+     * @param needCompress 是否压缩LOGO
+     * @throws Exception
+     */
+    public static void encode(String content, String destPath,
+                              boolean needCompress) throws Exception {
+        QRCodeUtils.encode(content, null, destPath, needCompress);
+    }
+
+    /**
+     * 生成二维码
+     *
+     * @param content  内容
+     * @param destPath 存储地址
+     * @throws Exception
+     */
+    public static void encode(String content, String destPath) throws Exception {
+        QRCodeUtils.encode(content, null, destPath, false);
+    }
+
+    /**
+     * 生成二维码(内嵌LOGO)
+     *
+     * @param content      内容
+     * @param imgPath      LOGO地址
+     * @param output       输出流
+     * @param needCompress 是否压缩LOGO
+     * @throws Exception
+     */
+    public static void encode(String content, String imgPath,
+                              OutputStream output, boolean needCompress) throws Exception {
+        BufferedImage image = QRCodeUtils.createImage(content, imgPath,
+                needCompress);
+        ImageIO.write(image, FORMAT_NAME, output);
+    }
+
+    /**
+     * 生成二维码
+     *
+     * @param content 内容
+     * @param output  输出流
+     * @throws Exception
+     */
+    public static void encode(String content, OutputStream output)
+            throws Exception {
+        QRCodeUtils.encode(content, null, output, false);
+    }
+
+    /**
+     * 解析二维码
+     *
+     * @param file 二维码图片
+     * @return
+     * @throws Exception
+     */
+    public static String decode(File file) throws Exception {
+        BufferedImage image;
+        image = ImageIO.read(file);
+        if (image == null) {
+            return null;
+        }
+        BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(
+                image);
+        BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
+        Result result;
+        Hashtable<DecodeHintType, Object> hints = new Hashtable<DecodeHintType, Object>();
+        hints.put(DecodeHintType.CHARACTER_SET, CHARSET);
+        result = new MultiFormatReader().decode(bitmap, hints);
+        String resultStr = result.getText();
+        return resultStr;
+    }
+
+    /**
+     * 解析二维码
+     *
+     * @param path 二维码图片地址
+     * @return
+     * @throws Exception
+     */
+    public static String decode(String path) throws Exception {
+        return QRCodeUtils.decode(new File(path));
+    }
+}

+ 11 - 4
ruoyi-common/src/main/java/com/ruoyi/common/utils/SecurityUtils.java

@@ -3,6 +3,8 @@ package com.ruoyi.common.utils;
 import java.util.Collection;
 import java.util.List;
 import java.util.stream.Collectors;
+
+import com.ruoyi.common.encoder.AesPasswordEncoder;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.context.SecurityContextHolder;
 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
@@ -13,6 +15,8 @@ import com.ruoyi.common.core.domain.entity.SysRole;
 import com.ruoyi.common.core.domain.model.LoginUser;
 import com.ruoyi.common.exception.ServiceException;
 
+import static com.ruoyi.common.constant.CommonConstants.LOGIN_PASSWORD_AES;
+
 /**
  * 安全服务工具类
  * 
@@ -97,8 +101,9 @@ public class SecurityUtils
      */
     public static String encryptPassword(String password)
     {
-        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
-        return passwordEncoder.encode(password);
+        //BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
+        //return passwordEncoder.encode(password);
+        return AesUtil.encryptCBC(password,LOGIN_PASSWORD_AES);
     }
 
     /**
@@ -110,8 +115,10 @@ public class SecurityUtils
      */
     public static boolean matchesPassword(String rawPassword, String encodedPassword)
     {
-        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
-        return passwordEncoder.matches(rawPassword, encodedPassword);
+/*        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
+        return passwordEncoder.matches(rawPassword, encodedPassword);*/
+        AesPasswordEncoder aesPasswordEncoder = new AesPasswordEncoder();
+        return aesPasswordEncoder.matches(rawPassword,encodedPassword);
     }
 
     /**

+ 133 - 0
ruoyi-common/src/main/java/com/ruoyi/common/utils/SendSmsUtils.java

@@ -0,0 +1,133 @@
+package com.ruoyi.common.utils;
+
+
+import com.aliyun.dysmsapi20170525.models.SendBatchSmsRequest;
+import com.aliyun.dysmsapi20170525.models.SendBatchSmsResponse;
+import com.aliyun.dysmsapi20170525.models.SendSmsResponse;
+import com.aliyun.tea.TeaException;
+
+/**阿里云
+ * @author tjf
+ * @Date: 2021/07/15/10:21
+ */
+public class SendSmsUtils {
+    //阿里云ACCESS_KEY短信参数
+    static final String ACCESS_KEY_ID = "LTAI5tNA2fcBJH6EWRH6Pxr6";
+    static final String ACCESS_KEY_SECRET = "5WdaPEOvC3u9LC7pwy2DQ9pgmJvgUr";
+
+
+    //生成X位验证码
+    public static String getCode(Integer num) {
+        String[] codes = {"1", "2", "3", "4", "5", "6", "7", "8", "9"};
+        StringBuilder code = new StringBuilder();
+        for (int i = 0; i < num; i++) {
+            int j = (int) (Math.random() * 10);
+            if (j <= 0) {
+                j = 1;
+            }
+            code.append(codes[j - 1]);
+
+        }
+        return code.toString();
+    }
+
+    /**
+     * 使用AK&SK初始化账号Client
+     *
+     * @return Client
+     * @throws Exception
+     */
+    public static com.aliyun.dysmsapi20170525.Client createClient() throws Exception {
+        // 工程代码泄露可能会导致 AccessKey 泄露,并威胁账号下所有资源的安全性。以下代码示例仅供参考。
+        // 建议使用更安全的 STS 方式,更多鉴权访问方式请参见:https://help.aliyun.com/document_detail/378657.html。
+        com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()
+                // 必填,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_ID。
+                .setAccessKeyId(ACCESS_KEY_ID)
+                // 必填,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_SECRET。
+                .setAccessKeySecret(ACCESS_KEY_SECRET);
+        // Endpoint 请参考 https://api.aliyun.com/product/Dysmsapi
+        config.endpoint = "dysmsapi.aliyuncs.com";
+        return new com.aliyun.dysmsapi20170525.Client(config);
+    }
+
+
+    /**
+     * 发送短信消息
+     *
+     * @return
+     */
+    public static String sendSms(String phone, String templateCode, String smsCode) {
+        String code = "";
+        try {
+            // 工程代码泄露可能会导致AccessKey泄露,并威胁账号下所有资源的安全性。以下代码示例仅供参考,建议使用更安全的 STS 方式,更多鉴权访问方式请参见:https://help.aliyun.com/document_detail/378657.html
+            com.aliyun.dysmsapi20170525.Client client = SendSmsUtils.createClient();
+
+            com.aliyun.dysmsapi20170525.models.SendSmsRequest sendSmsRequest = new com.aliyun.dysmsapi20170525.models.SendSmsRequest()
+                    //手机号码
+                    .setPhoneNumbers(phone)
+                    //短信签名名称。潜山市皖源融资担保
+                    .setSignName("潜山市皖源融资担保")
+                    //短信模板变量对应的实际值{"name": code}
+                    .setTemplateParam(smsCode)
+                    //短信模板CODE
+                    .setTemplateCode(templateCode);
+            // 复制代码运行请自行打印 API 的返回值
+            SendSmsResponse sendSmsResponse = client.sendSmsWithOptions(sendSmsRequest, new com.aliyun.teautil.models.RuntimeOptions());
+            code = sendSmsResponse.getBody().code;
+        } catch (Exception _error) {
+        }
+        return code;
+    }
+
+    /**
+     * 阿里云批量发送 短信接口,一次最多100个手机号码
+     *
+     * @return
+     * @throws
+     */
+    public static SendBatchSmsResponse sendBatchSms(SendBatchSmsRequest sendBatchSmsRequest) {
+        try {
+            com.aliyun.dysmsapi20170525.Client client = SendSmsUtils.createClient();
+            com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
+            SendBatchSmsResponse sendBatchSmsResponse = client.sendBatchSmsWithOptions(sendBatchSmsRequest, runtime);
+            return sendBatchSmsResponse;
+            // 复制代码运行请自行打印 API 的返回值
+        } catch (TeaException error) {
+            // 如有需要,请打印 error
+            com.aliyun.teautil.Common.assertAsString(error.message);
+        } catch (Exception _error) {
+            TeaException error = new TeaException(_error.getMessage(), _error);
+            // 如有需要,请打印 error
+            com.aliyun.teautil.Common.assertAsString(error.message);
+        }
+        return null;
+    }
+
+    /**
+     * 发送注册的随机密码
+     *
+     * @return
+     */
+    public static String sendPassword(String code, String phone) {
+        try {
+            // 工程代码泄露可能会导致AccessKey泄露,并威胁账号下所有资源的安全性。以下代码示例仅供参考,建议使用更安全的 STS 方式,更多鉴权访问方式请参见:https://help.aliyun.com/document_detail/378657.html
+            com.aliyun.dysmsapi20170525.Client client = SendSmsUtils.createClient();
+            String smsCode = "{\"code\":\"" + code + "\"}";
+            com.aliyun.dysmsapi20170525.models.SendSmsRequest sendSmsRequest = new com.aliyun.dysmsapi20170525.models.SendSmsRequest()
+                    //手机号码
+                    .setPhoneNumbers(phone)
+                    //短信签名名称。潜山市皖源融资担保
+                    .setSignName("潜山市皖源融资担保")
+                    //短信模板CODE
+                    .setTemplateCode("SMS_219525380")
+                    //短信模板变量对应的实际值{"name": code}
+                    .setTemplateParam(smsCode);
+            // 复制代码运行请自行打印 API 的返回值
+            SendSmsResponse sendSmsResponse = client.sendSmsWithOptions(sendSmsRequest, new com.aliyun.teautil.models.RuntimeOptions());
+            code = sendSmsResponse.getBody().code;
+        } catch (Exception _error) {
+        }
+        return code;
+    }
+}
+

+ 53 - 6
ruoyi-common/src/main/java/com/ruoyi/common/utils/StringUtils.java

@@ -1,11 +1,9 @@
 package com.ruoyi.common.utils;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.text.NumberFormat;
+import java.time.LocalDate;
+import java.util.*;
+
 import org.springframework.util.AntPathMatcher;
 import com.ruoyi.common.constant.Constants;
 import com.ruoyi.common.core.text.StrFormatter;
@@ -26,6 +24,9 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
     /** 星号 */
     private static final char ASTERISK = '*';
 
+    private static final char[] CN_NUMBERS = {'零', '一', '二', '三', '四', '五', '六', '七', '八', '九'};
+    private static final char[] CN_UNITS = { ' ','十', '百', '千', '万'};
+
     /**
      * 获取参数不为空值
      * 
@@ -681,4 +682,50 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
         }
         return sb.toString();
     }
+
+
+    public static String convert(int number) {
+
+        if(number>99999){
+            return "";
+        }
+
+        String[] units = {"", "十", "百", "千","万"};
+        String[] digits = {"零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"};
+
+        StringBuilder result = new StringBuilder();
+        int unit = 0;
+
+        while (number > 0) {
+            int digit = number % 10;
+            if (digit != 0) {
+                result.insert(0, units[unit]);
+                result.insert(0, digits[digit]);
+            } else {
+                if (result.length() > 0 && result.charAt(0) != '零') {
+                    result.insert(0, digits[digit]);
+                }
+            }
+
+            number /= 10;
+            unit++;
+        }
+
+        if (result.length() == 0) {
+            result.append("零");
+        }
+
+        return result.toString();
+    }
+
+    //判断正整数
+    public static boolean isNumeric(String str){
+        for (int i = str.length();--i>=0;){
+            if (!Character.isDigit(str.charAt(i))){
+                return false;
+            }
+        }
+        return true;
+    }
+
 }

+ 86 - 0
ruoyi-common/src/main/java/com/ruoyi/common/utils/Text2PdfUtil.java

@@ -0,0 +1,86 @@
+package com.ruoyi.common.utils;
+
+import com.itextpdf.text.Document;
+import com.itextpdf.text.DocumentException;
+import com.itextpdf.text.Font;
+import com.itextpdf.text.Paragraph;
+import com.itextpdf.text.pdf.BaseFont;
+import com.itextpdf.text.pdf.PdfReader;
+import com.itextpdf.text.pdf.PdfWriter;
+import com.itextpdf.text.pdf.parser.PdfTextExtractor;
+
+import java.io.*;
+import java.nio.charset.Charset;
+
+/**
+ * 需要引入的依赖
+ *
+ * <dependency>
+ *             <groupId>com.itextpdf</groupId>
+ *             <artifactId>itext-asian</artifactId>
+ *             <version>5.2.0</version>
+ *         </dependency>
+ *
+ *         <dependency>
+ *             <groupId>com.itextpdf</groupId>
+ *             <artifactId>itextpdf</artifactId>
+ *             <version>5.5.13</version>
+ *         </dependency>
+ *
+ */
+public class Text2PdfUtil {
+
+    /**
+     * txt文本文件  转pdf文件
+     * @param text   F:/data/te616.txt
+     * @param pdf  F:/data/aet618.pdf
+     * @throws DocumentException
+     * @throws IOException
+     */
+    public static void text2pdf(String text,String pdf) throws DocumentException, IOException {
+        Document doc = new Document();
+        OutputStream os = new FileOutputStream(new File(pdf));
+        PdfWriter.getInstance(doc, os);
+        doc.open();
+        //指定 使用内置的中文字体
+        BaseFont baseFont =
+                BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);
+        Font font = new Font(baseFont,12,Font.NORMAL);
+        //指定输出编码为UTF-8
+        InputStreamReader isr = new InputStreamReader(
+                new FileInputStream(new File(text)), Charset.forName("UTF-8"));
+        BufferedReader br = new BufferedReader(isr);
+        String str = "";
+        while((str = br.readLine()) != null){
+            doc.add(new Paragraph(str,font));
+        }
+        isr.close();
+        br.close();
+        doc.close();
+    }
+
+
+    /**
+     * 读取pdf文件的内容
+     * @param filename  F:/data/aet618.pdf
+     * @return  String
+     */
+    public static String readPDF(String filename){
+        StringBuilder result = new StringBuilder();
+        try {
+            PdfReader reader = new PdfReader(filename);
+            int countPage = reader.getNumberOfPages();
+            for(int i=1;i<=countPage;i++){
+                result.append(PdfTextExtractor.getTextFromPage(reader, i));
+            }
+            reader.close();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return result.toString();
+    }
+
+}
+
+
+

+ 553 - 0
ruoyi-common/src/main/java/com/ruoyi/common/utils/ThumbnailUtil.java

@@ -0,0 +1,553 @@
+package com.ruoyi.common.utils;
+
+/**
+ * @Author: tjf
+ * @Date: 2024/7/29 17:57
+ * @Describe:
+ */
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.mock.web.MockMultipartFile;
+import org.springframework.web.multipart.MultipartFile;
+import javax.activation.MimetypesFileTypeMap;
+import javax.imageio.*;
+import javax.imageio.stream.ImageOutputStream;
+import java.awt.*;
+import java.awt.image.BufferedImage;
+import java.io.*;
+import java.util.*;
+import java.util.stream.StreamSupport;
+
+
+/**
+ * @author
+ * @description 多线程图片压缩
+ * @date 2022/12/13 18:56
+ */
+public class ThumbnailUtil {
+
+    // 压缩比率, 低(原质量*0.85),中(原质量*0.7),高(原质量*0.6)
+    public static String[] ratios = new String[]{"low", "medium", "high"};
+    // 原始格式
+    public static String orgForm = "orgForm";
+    // 支持输出的图片格式
+    public static String[] imageFormats = new String[]{"bmp","jpeg","jpg","png"};
+
+    /**
+     * 多文件输入
+     * @param files
+     * @return
+     */
+    public static Builder<File> of(File... files) {
+        Iterable<File> iter = Arrays.asList(files);
+        return new Builder<>(iter);
+    }
+
+    /**
+     * 多文件Buffered流输入
+     * @param images
+     * @return
+     */
+    public static Builder<BufferedImage> of(BufferedImage... images) {
+        return new Builder<>(Arrays.asList(images));
+    }
+
+    /**
+     * 多文件输入流输入
+     * @param inputStreams
+     * @return
+     */
+    public static Builder<InputStream> of(InputStream... inputStreams) {
+        return new Builder<>(Arrays.asList(inputStreams));
+    }
+
+    /**
+     * 多文件MultipartFile流输入
+     * @param multipartFiles
+     * @return
+     */
+    public static Builder<MultipartFile> of(MultipartFile... multipartFiles) {
+        return new Builder<>(Arrays.asList(multipartFiles));
+    }
+
+    /**
+     * 识别是否是图片过滤器
+     * @return
+     */
+    public static FilenameFilter readFilter() {
+        String readFormats[] = ImageIO.getReaderFormatNames();
+        Set<String> readFormatSet = new HashSet<>(Arrays.asList(readFormats));
+        String writeFormats[] = ImageIO.getWriterFormatNames();
+        return new FilenameFilter() {
+            @Override
+            public boolean accept(File dir, String name) {
+                String seprator = ".";
+                if (name == null || !name.contains(seprator)) {
+                    return false;
+                }
+                String format = name.substring(name.lastIndexOf(seprator) + 1);
+                return readFormatSet.contains(format);
+            }
+        };
+    }
+
+    public static class Builder<T> {
+        // 待转换源数据
+        private final Iterable<T> sources;
+        // 输出格式
+        private String outputFormat = null;
+        // 压缩比率
+        private String compressionRatio = null;
+
+        // 缩放后宽
+        private double scaleWidth = Double.NaN;
+        // 缩放后高
+        private double scaleHeight = Double.NaN;
+        // 压缩质量系数 0-1之间
+        private double outputQuality = Double.NaN;
+
+        private Builder() {
+            sources = null;
+        }
+
+        private Builder(Iterable<T> sources) {
+            this.sources = sources;
+        }
+
+        /**
+         * 自动通过压缩比率自匹配压缩宽高比率和压缩质量系数
+         * @param compressionRatio 压缩比率, 低(原质量*0.85),中(原质量*0.7),高(原质量*0.6)
+         * @return
+         */
+        public Builder<T> identifyCompress(String compressionRatio) {
+            if (!Objects.equals(Double.NaN, scaleWidth)
+                    || !Objects.equals(Double.NaN, scaleHeight)
+                    || !Objects.equals(Double.NaN, outputQuality)
+            ) {
+                // 有设置scale和outputQuality则不使用自动压缩选项
+                return this;
+            } else if (null == compressionRatio) {
+                this.compressionRatio = ratios[1];
+                return this;
+            }
+            if (!Arrays.toString(ratios).contains(compressionRatio)) {
+                throw new IllegalArgumentException("Unsupported compressionRatio Type.");
+            }
+            this.compressionRatio = compressionRatio;
+            return this;
+        }
+
+        /**
+         * 自动根据原图尺寸以及构造器中提供的参数计算压缩长宽和压缩质量
+         * @param compressionRatio 压缩比率
+         * @param width 原图宽
+         * @param height 原图高
+         * @return 新计算的压缩宽高和压缩质量系数
+         */
+        private Builder<T> identifyCompress(String compressionRatio, int width, int height) {
+            if (width <= 0 || height <= 0) {
+                throw new IllegalArgumentException("Width (" + width + ") and height (" + height + ") cannot be <= 0");
+            }
+            // 为了支持多线程压缩, 需要将可变变量直接传入方法中,不能使用共享变量返回scaleWidth和outputQuality
+            if (!Objects.equals(Double.NaN, scaleWidth)
+                    || !Objects.equals(Double.NaN, scaleHeight)
+                    || !Objects.equals(Double.NaN, outputQuality)
+            ) {
+                // 有设置scale和outputQuality则不使用自动压缩选项
+                return this;
+            } else if (null == compressionRatio) {
+                compressionRatio = ratios[1];
+            }
+            if (!Arrays.toString(ratios).contains(compressionRatio)) {
+                throw new IllegalArgumentException("Unsupported compressionRatio Type.");
+            }
+            int min = width < height ? width : height;
+            double offset;
+            Builder builder = new Builder();
+            if (Objects.equals(ratios[0], compressionRatio)) {
+                // 最低压缩,图片保持原来尺寸,质量为原图的0.8
+                builder.scaleWidth = builder.scaleHeight = 1.0D;
+                builder.outputQuality = 0.8D;
+                return builder;
+            } else if (Objects.equals(ratios[1], compressionRatio)) {
+                offset = 0.4D;
+            } else {
+                offset = 0.3D;
+            }
+            if (min <= 1024) {
+                // 最小像素小于1024,长和宽不压缩
+                builder.scaleWidth = builder.scaleHeight = 1.0D;
+                builder.outputQuality = (builder.outputQuality = 0.3D + offset) <= 1 ? builder.outputQuality : 1;
+            } else if (min > 1024 && min <= 3 * 1024) {
+                builder.scaleHeight = (builder.scaleHeight = 0.4D + offset) <= 1 ? builder.scaleHeight : 1;
+                builder.scaleWidth = builder.scaleHeight;
+                builder.outputQuality = (builder.outputQuality = 0.3D + offset) <= 1 ? builder.outputQuality : 1;
+            } else {
+                builder.scaleHeight = (builder.scaleHeight = 2048D / min + offset) <= 1 ? builder.scaleHeight : 1;
+                builder.scaleWidth = builder.scaleHeight;
+                builder.outputQuality = builder.scaleHeight;
+            }
+            return builder;
+        }
+
+        /**
+         * 自定义设置压缩宽高比率
+         * @param scaleWidth 宽压缩比率
+         * @param scaleHeight 高压缩比率
+         * @return
+         */
+        public Builder<T> scale(double scaleWidth, double scaleHeight) {
+            if (scaleWidth <= 0.0 || scaleHeight <= 0.0) {
+                throw new IllegalArgumentException(
+                        "The scaling factor is equal to or less than 0."
+                );
+            }
+            if (Double.isNaN(scaleWidth) || Double.isNaN(scaleHeight)) {
+                throw new IllegalArgumentException(
+                        "The scaling factor is not a number."
+                );
+            }
+            if (Double.isInfinite(scaleWidth) || Double.isInfinite(scaleHeight)) {
+                throw new IllegalArgumentException(
+                        "The scaling factor cannot be infinity."
+                );
+            }
+            this.scaleWidth = scaleWidth;
+            this.scaleHeight = scaleHeight;
+            return this;
+        }
+
+        /**
+         * 自定义等比例设置压缩宽高比率
+         * @param scale 等比例宽高压缩比率
+         * @return
+         */
+        public Builder<T> scale(double scale) {
+            return scale(scale, scale);
+        }
+
+        /**
+         * 自定义设置压缩质量系数 0-1之间
+         * @param quality 压缩质量系数 0-1之间
+         *                越大,压缩越少,质量越好,一般0.8的质量和原图肉眼识别不到差异
+         * @return
+         */
+        public Builder<T> outputQuality(double quality) {
+            if (quality < 0.0f || quality > 1.0f) {
+                throw new IllegalArgumentException(
+                        "The quality setting must be in the range 0.0f and " +
+                                "1.0f, inclusive."
+                );
+            }
+            outputQuality = quality;
+            return this;
+        }
+
+        /**
+         * 自定义设置输出格式,输出格式提前使用图片工具校验
+         * @param formatName jpg jpeg png 等常用格式 见枚举imageFormats
+         * @return
+         */
+        public Builder<T> outputFormat(String formatName) {
+            if (StringUtils.isEmpty(formatName)) {
+                this.outputFormat = orgForm;
+                return this;
+            } else if (Objects.equals(orgForm, formatName)) {
+                this.outputFormat = formatName;
+                return this;
+            }
+            Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName(formatName);
+            if (!writers.hasNext()) {
+                throw new UnsupportedOperationException(
+                        "No suitable ImageWriter found for " + formatName + "."
+                );
+            }
+            this.outputFormat = formatName;
+            return this;
+        }
+
+        /**
+         * 校验输出格式是否正确
+         * @param source 待压缩数据
+         * @param formatName 输出格式
+         * @return
+         * @throws IOException
+         */
+        private String outputFormat(T source, String formatName) throws IOException {
+            if (source == null) {
+                throw new IllegalArgumentException("The resource being processed is null.");
+            }
+            if (StringUtils.isEmpty(formatName)) {
+                formatName = orgForm;
+            } else if (!Objects.equals(orgForm, formatName)) {
+                return formatName;
+            }
+            Iterator<ImageReader> iterReader = ImageIO.getImageReaders(ImageIO.createImageInputStream(source));
+            if (null == iterReader || !iterReader.hasNext()) {
+                throw new UnsupportedOperationException("The resource being processed is not a picture.");
+            }
+            formatName = iterReader.next().getFormatName();
+            Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName(formatName);
+            if (!writers.hasNext()) {
+                throw new UnsupportedOperationException(
+                        "No suitable ImageWriter found for " + formatName + "."
+                );
+            }
+            return formatName;
+        }
+
+        /**
+         * 压缩实现关键方法
+         * @param source 待压缩数据
+         * @param outputStream 图片输出流
+         * @throws IOException
+         */
+        private void write(T source, final ImageOutputStream outputStream) throws IOException {
+            if (StringUtils.isEmpty(outputFormat)) {
+                throw new IllegalStateException("Output format has not been set.");
+            }
+            Objects.requireNonNull(outputStream, "Could not open OutputStream.");
+            BufferedImage srcImage;
+            if (source instanceof BufferedImage) {
+                srcImage = (BufferedImage) source;
+            } else if (source instanceof File) {
+                srcImage = ImageIO.read((File) source);
+            } else if (source instanceof MultipartFile) {
+                srcImage = ImageIO.read(((MultipartFile) source).getInputStream());
+                // 将MultipartFile装换为InputStream
+                source = (T) ((MultipartFile) source).getInputStream();
+            } else if (source instanceof InputStream) {
+                srcImage = ImageIO.read((InputStream) source);
+            } else {
+                throw new IllegalArgumentException("Unsupported ImageIO Type.");
+            }
+            // 校验输出格式是否正确
+            String outputFormatName = this.outputFormat(source, outputFormat);
+            System.out.println("outputFormatName : " + outputFormatName);
+            // 原图宽
+            int width = srcImage.getWidth();
+            // 原图高
+            int height = srcImage.getHeight();
+            // 自动根据原图尺寸以及构造器中提供的参数计算压缩长宽和压缩质量
+            Builder builder = this.identifyCompress(compressionRatio, width, height);
+            double scaleWidth = builder.scaleWidth;
+            double scaleHeight = builder.scaleHeight;
+            double outputQuality = builder.outputQuality;
+            System.out.println("scaleWidth ; " + scaleWidth + " scaleHeight : " + scaleHeight + " outputQuality : " + outputQuality);
+            if (Objects.equals(outputQuality, Double.NaN)) {
+                throw new IllegalArgumentException("outputQuality is null.");
+            }
+            // 缩放后宽
+            int sclWidth = Objects.equals(Double.NaN, scaleWidth) ? width : (int) (width * scaleWidth);
+            // 缩放后高
+            int sclHeight = Objects.equals(Double.NaN, scaleHeight) ? height : (int) (height * scaleHeight);
+            System.out.println("sclWidth : " + sclWidth + " sclHeight : " + sclHeight);
+            // 输出BufferedImage流
+            long startTime = System.currentTimeMillis();
+            BufferedImage destImage =
+                    new BufferedImage(sclWidth, sclHeight, BufferedImage.TYPE_INT_RGB);
+            Graphics2D g = destImage.createGraphics();
+            // 消除锯齿
+            g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+//            g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,RenderingHints.VALUE_STROKE_DEFAULT);
+            g.addRenderingHints(new HashMap<>());
+            g.drawImage(srcImage, 0, 0, sclWidth, sclHeight, null);
+            System.out.println("image scale cost time : " + (System.currentTimeMillis() - startTime));
+            // 压缩后增加一点点锐化,如不需要的,以下4行代码可以干掉
+            g.dispose();
+            ImageWriter writer = null;
+            ImageTypeSpecifier type =
+                    ImageTypeSpecifier.createFromRenderedImage(destImage);
+            // formatName不生效, 所以统一使用jpg
+//            Iterator iterIO = ImageIO.getImageWriters(type, outputFormatName);
+            Iterator iterIO = ImageIO.getImageWriters(type, "jpg");
+            if (iterIO.hasNext()) {
+                writer = (ImageWriter) iterIO.next();
+            }
+            if (writer == null) {
+                throw new IllegalArgumentException("ImageWriter is null.");
+            }
+
+            IIOImage iioImage = new IIOImage(destImage, null, null);
+            ImageWriteParam param = writer.getDefaultWriteParam();
+            if (param.canWriteCompressed() && !outputFormatName.equalsIgnoreCase("bmp")) {
+                param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
+                param.setCompressionQuality((float) outputQuality);    //这里可以指定压缩的程度 0-1.0
+            } else {
+//                param.setCompressionQuality(0.0f);
+                System.out.println("The outputFormat (" + outputFormatName + ") cannot be compressed");
+            }
+            writer.setOutput(outputStream);
+            writer.write(null, iioImage, param);
+            writer.dispose();
+            outputStream.close();
+        }
+
+        /**
+         * 输出单个文件到Byte流
+         * @return
+         * @throws IOException
+         */
+        public ByteArrayInputStream asByteArray() throws IOException {
+            Iterator<T> iter = sources.iterator();
+            T source = iter.next();
+            if (iter.hasNext()) {
+                throw new IllegalArgumentException("Cannot create one thumbnail from multiple original images.");
+            }
+            // 将缓存中的图片按照指定的配置输出到字节数组中
+            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+            write(source, ImageIO.createImageOutputStream(byteArrayOutputStream));
+            // 从字节数组中读取图片
+            ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
+//            InputStream inputStream = new ByteArrayInputStream(byteArrayInputStream);
+//            MultipartFile file = new MockMultipartFile(ContentType.APPLICATION_OCTET_STREAM.toString(), byteArrayInputStream);
+            return byteArrayInputStream;
+        }
+
+        /**
+         * 多文件输出MultipartFile[]流文件
+         * @return
+         */
+        public MultipartFile[] asMultipartFiles() {
+            long startTime = System.currentTimeMillis();
+            MultipartFile[] multipartFiles = StreamSupport.stream(sources.spliterator(), true).map(source -> {
+                if (!(source instanceof File)
+                        && (!(source instanceof MultipartFile))
+                ) {
+                    throw new IllegalStateException("Cannot create thumbnails to files if original images are not from files or multipartFile.");
+                }
+                String filename = "";
+                String mimeType = "";
+                if (source instanceof File) {
+                    filename = ((File) source).getName();
+                    MimetypesFileTypeMap fileTypeMap = new MimetypesFileTypeMap();
+                    mimeType = fileTypeMap.getContentType(filename);
+                } else if (source instanceof MultipartFile) {
+                    filename = ((MultipartFile) source).getOriginalFilename();
+                    mimeType = ((MultipartFile) source).getContentType();
+                }
+                // 将缓存中的图片按照指定的配置输出到字节数组中
+                ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+                try {
+                    System.out.println("Process the image " + filename + " start.");
+                    write(source, ImageIO.createImageOutputStream(byteArrayOutputStream));
+                } catch (IOException e) {
+                    String desc = "Failed to process the image " + filename + " .";
+                    System.out.println(desc);
+                    throw new IllegalArgumentException(desc, e);
+                }
+                // 从字节数组中读取图片
+                ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
+                String octetStream = "application/octet-stream";
+                MultipartFile multipartFile = null;
+                try {
+                    multipartFile =  new MockMultipartFile(octetStream, filename, mimeType, byteArrayInputStream);
+                } catch (IOException e) {
+                    String desc = "Failed to mockMultipartFile the image " + filename + " .";
+                    System.out.println(desc);
+                    throw new IllegalArgumentException(desc, e);
+                }
+                return multipartFile;
+            }).toArray(MultipartFile[]::new);
+            System.out.println("cost : " + (System.currentTimeMillis() - startTime));
+            return multipartFiles;
+        }
+
+
+        /**
+         * 单文件输出提供的文件目录中
+         * @param outFile 文件目录
+         * @throws IOException
+         */
+        public void toFile(final File outFile) throws IOException {
+            Iterator<T> iter = sources.iterator();
+            T source = iter.next();
+            if (iter.hasNext()) {
+                throw new IllegalArgumentException("Cannot create one thumbnail from multiple original images.");
+            }
+            write(source, ImageIO.createImageOutputStream(outFile));
+        }
+
+        private void toFiles(Iterable<File> iterable) throws IOException {
+            Iterator<File> filenameIter = iterable.iterator();
+            for (T source : sources) {
+                if (!filenameIter.hasNext()) {
+                    throw new IndexOutOfBoundsException(
+                            "Not enough file names provided by iterator."
+                    );
+                }
+                write(source, ImageIO.createImageOutputStream(filenameIter.next()));
+            }
+        }
+
+        /**
+         * 多文件输出提供的文件目录中
+         * @param destinationDir 文件目录
+         * @param namePrefix 文件重命名前缀
+         * @throws IOException
+         */
+        public void toFiles(File destinationDir, String namePrefix) throws IOException {
+            if (destinationDir == null && namePrefix == null) {
+                throw new NullPointerException("destinationDir and rename is null.");
+            }
+            if (destinationDir != null && !destinationDir.isDirectory()) {
+                destinationDir.mkdir();
+//                throw new IllegalArgumentException("Given destination is not a directory.");
+            }
+
+            if (destinationDir != null && !destinationDir.isDirectory()) {
+                throw new IllegalArgumentException("Given destination is not a directory.");
+            }
+            long startTime = System.currentTimeMillis();
+            Builder<T> builder = outputFormat(outputFormat);
+            StreamSupport.stream(sources.spliterator(), true).forEach(source -> {
+                if (!(source instanceof File)) {
+                    throw new IllegalStateException("Cannot create thumbnails to files if original images are not from files.");
+                }
+                File f = (File) source;
+                File actualDestDir = destinationDir == null ? f.getParentFile() : destinationDir;
+                String name = StringUtils.isEmpty(namePrefix) ? f.getName() : namePrefix + f.getName();
+                if (!Objects.equals(orgForm, builder.outputFormat)) {
+                    name = name.substring(0, name.lastIndexOf(".")) + "." + outputFormat;
+                }
+                File destinationFile = new File(actualDestDir, name);
+                try {
+                    System.out.println("Process the image " + f.getName() + " start.");
+                    write((T) source, ImageIO.createImageOutputStream(destinationFile));
+                } catch (Exception e) {
+                    System.out.println("Failed to process the image " + f.getName() + " .");
+                    e.printStackTrace();
+                }
+            });
+            System.out.println("cost : " + (System.currentTimeMillis() - startTime));
+        }
+
+        /**
+         * 单文件输出提供的输出流中
+         * @throws IOException
+         */
+        public void toOutputStream(final OutputStream outputStream) throws IOException {
+            Iterator<T> iter = sources.iterator();
+            T source = iter.next();
+            if (iter.hasNext()) {
+                throw new IllegalArgumentException("Cannot create one thumbnail from multiple original images.");
+            }
+            write(source, ImageIO.createImageOutputStream(outputStream));
+        }
+
+        /**
+         * 多文件输出提供的多个输出流中
+         * @throws IOException
+         */
+        public void toOutputStreams(Iterable<? extends OutputStream> iterable) throws IOException {
+            Iterator<? extends OutputStream> filenameIter = iterable.iterator();
+            for (T source : sources) {
+                if (!filenameIter.hasNext()) {
+                    throw new IndexOutOfBoundsException(
+                            "Not enough file names provided by iterator."
+                    );
+                }
+                write(source, ImageIO.createImageOutputStream(filenameIter.next()));
+            }
+        }
+    }
+}

+ 224 - 0
ruoyi-common/src/main/java/com/ruoyi/common/utils/WordUtil.java

@@ -0,0 +1,224 @@
+package com.ruoyi.common.utils;
+
+import com.ruoyi.common.config.RuoYiConfig;
+import com.ruoyi.common.core.domain.AjaxResult;
+import org.docx4j.TraversalUtil;
+import org.docx4j.XmlUtils;
+import org.docx4j.dml.CTPositiveSize2D;
+import org.docx4j.dml.Graphic;
+import org.docx4j.dml.GraphicData;
+import org.docx4j.dml.picture.Pic;
+import org.docx4j.dml.wordprocessingDrawing.Inline;
+import org.docx4j.finders.RangeFinder;
+import org.docx4j.jaxb.Context;
+import org.docx4j.openpackaging.exceptions.Docx4JException;
+import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
+import org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage;
+import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart;
+import org.docx4j.wml.*;
+
+import javax.xml.bind.JAXBElement;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.util.*;
+
+/**
+ * 给word模板,在需要插入图片(签字)的地方,word中设则书签
+ * wordFilePath word 文档路径
+ * image 签名BASE64
+ * @Author: tjf
+ * @Date: 2024/5/15 10:25
+ * @Describe:
+ */
+public class WordUtil {
+    public static AjaxResult wordFilePath(String wordFilePath,String image) {
+        try {
+            // 上传文件路径
+            String filePath = RuoYiConfig.getUploadPath();
+            if (StringUtils.isNotEmpty(wordFilePath)){
+                wordFilePath = wordFilePath.replace("/profile/upload",filePath);
+            }
+            WordprocessingMLPackage wordMLPackage = load(wordFilePath);
+
+            // 提取正文
+            MainDocumentPart main = wordMLPackage.getMainDocumentPart();
+            Document doc = null;
+            doc = main.getContents();
+            Body body = doc.getBody();
+
+            // 获取段落
+            List<Object> paragraphs = body.getContent();
+
+            // 提取书签并获取书签的游标
+            RangeFinder rt = new RangeFinder("CTBookmark", "CTMarkupRange");
+            new TraversalUtil(paragraphs, rt);
+
+            // 遍历书签
+            for (CTBookmark bm : rt.getStarts()) {
+                System.out.println("name:" + bm.getName());
+                // 替换image sign是书签名字
+                if ("sign".equals(bm.getName())) {
+                    addImage(wordMLPackage, bm, image);
+                    break;
+                }
+            }
+            save(wordMLPackage, wordFilePath);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        return AjaxResult.success();
+    }
+
+    /**
+     * @param wPackage 文档
+     * @param bm       书签
+     * @param base64String    签名图片base64
+     * @throws Exception
+     */
+    public static void addImage(WordprocessingMLPackage wPackage, CTBookmark bm, String base64String) throws Exception {
+        P p = (P) (bm.getParent());
+        ObjectFactory factory = Context.getWmlObjectFactory();
+        R run = factory.createR();
+
+        // 读入图片并转化为字节数组,因为docx4j只能字节数组的方式插入图片
+        // byte[] bytes = IOUtils.toByteArray(new FileInputStream("图片文件路径"));
+        //byte[] bytes = getFileBytes(image);
+        if (base64String.contains("data:")) {
+            int start = base64String.indexOf(",");
+            base64String = base64String.substring(start + 1);
+        }
+        base64String = base64String.replaceAll("\r|\n", "");
+        base64String = base64String.trim();
+        byte[] bytes = Base64.getDecoder().decode(base64String);
+        // 开始创建一个行内图片
+        BinaryPartAbstractImage imagePart = BinaryPartAbstractImage.createImagePart(wPackage, bytes);
+        // 最后一个是限制图片的宽度,缩放的依据
+        Inline newInline = imagePart.createImageInline(null, null, 0, 1, false, 0);
+        // 构建绘图
+        Drawing drawing = factory.createDrawing();
+        // 加入图片段落
+        drawing.getAnchorOrInline().add(newInline);
+        run.getContent().add(drawing);
+        // 清理书签所在数据
+        // p.getContent().clear();
+        // 加入图片信息
+        p.getContent().add(run);
+    }
+
+
+    /**
+     * 处理图片适应大小
+     * @param cx
+     * @param cy
+     * @param newCx
+     * @param newCy
+     */
+    public static Map<String, Long> dealCxy(Long cx, Long cy, Long newCx, Long newCy){
+        Map<String, Long> map = new HashMap<>();
+        Long setCx;
+        Long setCy;
+
+        if (newCx > cx){
+            if (newCy <= cy){
+                setCx = cx;
+                setCy = newCy/(newCx/cx);
+            } else {
+                if ((newCx/cx) > (newCy/cy)){
+                    setCx = cx;
+                    setCy = newCy/(newCx/cx);
+                } else {
+                    setCy = cy;
+                    setCx = newCx/(newCy/cy);
+                }
+            }
+        } else {   // newCx < cx
+            if (newCy > cy) {
+                setCx = cx;
+                setCy = newCy * (cx/newCx);
+            } else {
+                if ((cx/newCx) > (cy/newCy)) {
+                    setCx = cx;
+                    setCy = newCy *(cx/newCx);
+                } else {
+                    setCy = cy;
+                    setCx = newCy * (cy/newCy);
+                }
+            }
+        }
+        map.put("setCx",setCx);
+        map.put("setCy",setCy);
+        return map;
+    }
+
+    /**
+     * 得到指定类型的元素
+     * @param obj
+     * @param toSearch
+     * @return
+     */
+    public static List<Object> getAllElementFromObject(Object obj, Class<?> toSearch) {
+        List<Object> result = new ArrayList<>();
+        if (obj instanceof JAXBElement)
+            obj = ((JAXBElement<?>) obj).getValue();
+        if (obj.getClass().equals(toSearch))
+            result.add(obj);
+        else if (obj instanceof ContentAccessor) {
+            List<?> children = ((ContentAccessor) obj).getContent();
+            for (Object child : children) {
+                result.addAll(getAllElementFromObject(child, toSearch));
+            }
+        }
+        return result;
+    }
+    /**
+     * 构建文件
+     */
+    public static WordprocessingMLPackage build() throws Exception {
+        return WordprocessingMLPackage.createPackage();
+    }
+
+    /**
+     * 读取存在的word文件
+     *
+     * @param wordFilePath word文件路径
+     */
+    public static WordprocessingMLPackage load(String wordFilePath) throws Exception {
+        return WordprocessingMLPackage.load(new File(wordFilePath));
+    }
+
+    /**
+     * 保存
+     *
+     * @param wordMLPackage word
+     */
+    public static void save(WordprocessingMLPackage wordMLPackage, String wordFilePath) throws Exception {
+        wordMLPackage.save(new File(wordFilePath));
+    }
+
+    /**
+     * 将图片转为Base64数组
+     *
+     * @param filePath
+     * @return
+     * @throws Exception
+     */
+    public static byte[] getFileBytes(String filePath) throws Exception {
+        File file = new File(filePath);
+        if (!file.exists()) {
+            throw new Exception("文件不存在!");
+        }
+
+        byte[] data = null;
+        try (FileInputStream fis = new FileInputStream(file); ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
+            int len;
+            byte[] buffer = new byte[1024];
+            while ((len = fis.read(buffer)) != -1) {
+                baos.write(buffer, 0, len);
+            }
+            data = baos.toByteArray();
+        }
+        return data;
+    }
+}

+ 243 - 71
ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java

@@ -2,9 +2,32 @@ package com.ruoyi.common.utils.file;
 
 import java.io.File;
 import java.io.IOException;
+import java.io.InputStream;
+import java.net.URLEncoder;
 import java.nio.file.Paths;
-import java.util.Objects;
+import java.util.*;
+
+import cn.hutool.http.HttpRequest;
+import cn.hutool.http.HttpResponse;
+import cn.hutool.json.JSONString;
+import cn.hutool.json.JSONUtil;
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONArray;
+import com.alibaba.fastjson2.JSONObject;
+import com.beust.jcommander.internal.Maps;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.utils.Base64Util;
+import com.ruoyi.common.utils.HttpUtils;
+import okhttp3.*;
 import org.apache.commons.io.FilenameUtils;
+import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.pdmodel.PDPage;
+import org.apache.pdfbox.pdmodel.PDPageContentStream;
+import org.apache.pdfbox.pdmodel.common.PDRectangle;
+import org.apache.pdfbox.pdmodel.graphics.image.JPEGFactory;
+import org.apache.pdfbox.pdmodel.graphics.image.LosslessFactory;
+import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
+import org.springframework.mock.web.MockMultipartFile;
 import org.springframework.web.multipart.MultipartFile;
 import com.ruoyi.common.config.RuoYiConfig;
 import com.ruoyi.common.constant.Constants;
@@ -15,17 +38,18 @@ import com.ruoyi.common.utils.DateUtils;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.uuid.Seq;
 
+import javax.imageio.ImageIO;
+
 /**
  * 文件上传工具类
  *
  * @author ruoyi
  */
-public class FileUploadUtils
-{
+public class FileUploadUtils {
     /**
      * 默认大小 50M
      */
-    public static final long DEFAULT_MAX_SIZE = 50 * 1024 * 1024;
+    public static final long DEFAULT_MAX_SIZE = 500 * 1024 * 1024;
 
     /**
      * 默认的文件名最大长度 100
@@ -37,13 +61,11 @@ public class FileUploadUtils
      */
     private static String defaultBaseDir = RuoYiConfig.getProfile();
 
-    public static void setDefaultBaseDir(String defaultBaseDir)
-    {
+    public static void setDefaultBaseDir(String defaultBaseDir) {
         FileUploadUtils.defaultBaseDir = defaultBaseDir;
     }
 
-    public static String getDefaultBaseDir()
-    {
+    public static String getDefaultBaseDir() {
         return defaultBaseDir;
     }
 
@@ -54,14 +76,10 @@ public class FileUploadUtils
      * @return 文件名称
      * @throws Exception
      */
-    public static final String upload(MultipartFile file) throws IOException
-    {
-        try
-        {
+    public static final String upload(MultipartFile file) throws IOException {
+        try {
             return upload(getDefaultBaseDir(), file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
-        }
-        catch (Exception e)
-        {
+        } catch (Exception e) {
             throw new IOException(e.getMessage(), e);
         }
     }
@@ -70,18 +88,31 @@ public class FileUploadUtils
      * 根据文件路径上传
      *
      * @param baseDir 相对应用的基目录
-     * @param file 上传的文件
+     * @param file    上传的文件
      * @return 文件名称
      * @throws IOException
      */
-    public static final String upload(String baseDir, MultipartFile file) throws IOException
-    {
-        try
-        {
+    public static final String upload(String baseDir, MultipartFile file) throws IOException {
+        try {
             return upload(baseDir, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
+        } catch (Exception e) {
+            throw new IOException(e.getMessage(), e);
         }
-        catch (Exception e)
-        {
+    }
+
+    /**
+     * 根据文件路径上传 合同编码
+     *
+     * @param baseDir               相对应用的基目录
+     * @param file                  上传的文件
+     * @param loanApplicationNumber 合同编码
+     * @return 文件名称
+     * @throws IOException
+     */
+    public static final String uploadLoanApplicationNumber(String baseDir, MultipartFile file, String loanApplicationNumber, String originalFilename) throws IOException {
+        try {
+            return uploadLoanApplicationNumber(baseDir, file, loanApplicationNumber, originalFilename, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
+        } catch (Exception e) {
             throw new IOException(e.getMessage(), e);
         }
     }
@@ -89,22 +120,20 @@ public class FileUploadUtils
     /**
      * 文件上传
      *
-     * @param baseDir 相对应用的基目录
-     * @param file 上传的文件
+     * @param baseDir          相对应用的基目录
+     * @param file             上传的文件
      * @param allowedExtension 上传文件类型
      * @return 返回上传成功的文件名
-     * @throws FileSizeLimitExceededException 如果超出最大大小
+     * @throws FileSizeLimitExceededException       如果超出最大大小
      * @throws FileNameLengthLimitExceededException 文件名太长
-     * @throws IOException 比如读写文件出错时
-     * @throws InvalidExtensionException 文件校验异常
+     * @throws IOException                          比如读写文件出错时
+     * @throws InvalidExtensionException            文件校验异常
      */
     public static final String upload(String baseDir, MultipartFile file, String[] allowedExtension)
             throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException,
-            InvalidExtensionException
-    {
+            InvalidExtensionException {
         int fileNamelength = Objects.requireNonNull(file.getOriginalFilename()).length();
-        if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH)
-        {
+        if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH) {
             throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH);
         }
 
@@ -117,31 +146,72 @@ public class FileUploadUtils
         return getPathFileName(baseDir, fileName);
     }
 
+    /**
+     * 文件上传合同编号
+     *
+     * @param baseDir               相对应用的基目录
+     * @param file                  上传的文件
+     * @param allowedExtension      上传文件类型
+     * @param loanApplicationNumber 合同编码
+     * @return 返回上传成功的文件名
+     * @throws FileSizeLimitExceededException       如果超出最大大小
+     * @throws FileNameLengthLimitExceededException 文件名太长
+     * @throws IOException                          比如读写文件出错时
+     * @throws InvalidExtensionException            文件校验异常
+     */
+    public static final String uploadLoanApplicationNumber(String baseDir, MultipartFile file, String loanApplicationNumber, String originalFilename, String[] allowedExtension)
+            throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException,
+            InvalidExtensionException {
+        int fileNamelength = Objects.requireNonNull(originalFilename).length();
+        if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH) {
+            throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH);
+        }
+
+        assertAllowed(file, allowedExtension);
+
+        String fileName = extractFilenameLoanApplicationNumber(file, loanApplicationNumber, originalFilename);
+
+        String absPath = getAbsoluteFile(baseDir, fileName).getAbsolutePath();
+        file.transferTo(Paths.get(absPath));
+        return getPathFileName(baseDir, fileName);
+    }
+
     /**
      * 编码文件名
      */
-    public static final String extractFilename(MultipartFile file)
-    {
+    public static final String extractFilename(MultipartFile file) {
         return StringUtils.format("{}/{}_{}.{}", DateUtils.datePath(),
                 FilenameUtils.getBaseName(file.getOriginalFilename()), Seq.getId(Seq.uploadSeqType), getExtension(file));
     }
 
-    public static final File getAbsoluteFile(String uploadDir, String fileName) throws IOException
-    {
+    /**
+     * 编码文件名根据合同编号
+     */
+    public static final String extractFilenameLoanApplicationNumber(MultipartFile file, String loanApplicationNumber, String originalFilename) {
+        return StringUtils.format("{}/{}_{}.{}", loanApplicationNumber,
+                FilenameUtils.getBaseName(originalFilename), Seq.getId(Seq.uploadSeqType), getExtension(file));
+    }
+
+    /**
+     * 编码文件名根据合同编号
+     */
+    public static final String extractFilenameLoanApplicationNumberNoHzm(String originalFilename) {
+        return StringUtils.format("{}_{}",
+                FilenameUtils.getBaseName(originalFilename), Seq.getId(Seq.uploadSeqType));
+    }
+
+    public static final File getAbsoluteFile(String uploadDir, String fileName) throws IOException {
         File desc = new File(uploadDir + File.separator + fileName);
 
-        if (!desc.exists())
-        {
-            if (!desc.getParentFile().exists())
-            {
+        if (!desc.exists()) {
+            if (!desc.getParentFile().exists()) {
                 desc.getParentFile().mkdirs();
             }
         }
         return desc;
     }
 
-    public static final String getPathFileName(String uploadDir, String fileName) throws IOException
-    {
+    public static final String getPathFileName(String uploadDir, String fileName) throws IOException {
         int dirLastIndex = RuoYiConfig.getProfile().length() + 1;
         String currentDir = StringUtils.substring(uploadDir, dirLastIndex);
         return Constants.RESOURCE_PREFIX + "/" + currentDir + "/" + fileName;
@@ -156,40 +226,28 @@ public class FileUploadUtils
      * @throws InvalidExtensionException
      */
     public static final void assertAllowed(MultipartFile file, String[] allowedExtension)
-            throws FileSizeLimitExceededException, InvalidExtensionException
-    {
+            throws FileSizeLimitExceededException, InvalidExtensionException {
         long size = file.getSize();
-        if (size > DEFAULT_MAX_SIZE)
-        {
+        if (size > DEFAULT_MAX_SIZE) {
             throw new FileSizeLimitExceededException(DEFAULT_MAX_SIZE / 1024 / 1024);
         }
 
         String fileName = file.getOriginalFilename();
         String extension = getExtension(file);
-        if (allowedExtension != null && !isAllowedExtension(extension, allowedExtension))
-        {
-            if (allowedExtension == MimeTypeUtils.IMAGE_EXTENSION)
-            {
+        if (allowedExtension != null && !isAllowedExtension(extension, allowedExtension)) {
+            if (allowedExtension == MimeTypeUtils.IMAGE_EXTENSION) {
                 throw new InvalidExtensionException.InvalidImageExtensionException(allowedExtension, extension,
                         fileName);
-            }
-            else if (allowedExtension == MimeTypeUtils.FLASH_EXTENSION)
-            {
+            } else if (allowedExtension == MimeTypeUtils.FLASH_EXTENSION) {
                 throw new InvalidExtensionException.InvalidFlashExtensionException(allowedExtension, extension,
                         fileName);
-            }
-            else if (allowedExtension == MimeTypeUtils.MEDIA_EXTENSION)
-            {
+            } else if (allowedExtension == MimeTypeUtils.MEDIA_EXTENSION) {
                 throw new InvalidExtensionException.InvalidMediaExtensionException(allowedExtension, extension,
                         fileName);
-            }
-            else if (allowedExtension == MimeTypeUtils.VIDEO_EXTENSION)
-            {
+            } else if (allowedExtension == MimeTypeUtils.VIDEO_EXTENSION) {
                 throw new InvalidExtensionException.InvalidVideoExtensionException(allowedExtension, extension,
                         fileName);
-            }
-            else
-            {
+            } else {
                 throw new InvalidExtensionException(allowedExtension, extension, fileName);
             }
         }
@@ -202,12 +260,9 @@ public class FileUploadUtils
      * @param allowedExtension
      * @return
      */
-    public static final boolean isAllowedExtension(String extension, String[] allowedExtension)
-    {
-        for (String str : allowedExtension)
-        {
-            if (str.equalsIgnoreCase(extension))
-            {
+    public static final boolean isAllowedExtension(String extension, String[] allowedExtension) {
+        for (String str : allowedExtension) {
+            if (str.equalsIgnoreCase(extension)) {
                 return true;
             }
         }
@@ -220,13 +275,130 @@ public class FileUploadUtils
      * @param file 表单文件
      * @return 后缀名
      */
-    public static final String getExtension(MultipartFile file)
-    {
+    public static final String getExtension(MultipartFile file) {
         String extension = FilenameUtils.getExtension(file.getOriginalFilename());
-        if (StringUtils.isEmpty(extension))
-        {
+        if (StringUtils.isEmpty(extension)) {
             extension = MimeTypeUtils.getExtension(Objects.requireNonNull(file.getContentType()));
         }
         return extension;
     }
+
+    public static String uploadLoanApplicationNumberOldName(String baseDir, MultipartFile file, String loanApplicationNumber, String originalFilename) throws IOException {
+        try {
+            return uploadLoanApplicationNumberOldName(baseDir, file, loanApplicationNumber, originalFilename, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
+        } catch (Exception e) {
+            throw new IOException(e.getMessage(), e);
+        }
+    }
+
+    private static String uploadLoanApplicationNumberOldName(String baseDir, MultipartFile file, String loanApplicationNumber, String originalFilename, String[] allowedExtension)
+            throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException,
+            InvalidExtensionException {
+        int fileNamelength = Objects.requireNonNull(originalFilename).length();
+        if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH) {
+            throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH);
+        }
+
+        assertAllowed(file, allowedExtension);
+
+        String fileName = extractFilenameLoanApplicationNumberOldName(file, loanApplicationNumber, originalFilename);
+
+        String absPath = getAbsoluteFile(baseDir, fileName).getAbsolutePath();
+        file.transferTo(Paths.get(absPath));
+        return getPathFileName(baseDir, fileName);
+    }
+
+    private static String extractFilenameLoanApplicationNumberOldName(MultipartFile file, String loanApplicationNumber, String originalFilename) {
+        return StringUtils.format("{}/{}.{}", loanApplicationNumber,
+                FilenameUtils.getBaseName(originalFilename), getExtension(file));
+    }
+
+    /**
+     * 合并图片生成PDF保存为文件
+     *
+     * @return
+     */
+    public static AjaxResult createPdfFromImages(List<String> imagePaths, File outputFile) throws IOException {
+        try (PDDocument document = new PDDocument()) {
+            float margin = 50f; // Define the margin
+            // 压缩图片质量,例如设置0.5的压缩质量
+            float quality = 0.5f;
+            for (String imagePath : imagePaths) {
+                // Load image
+                PDImageXObject image = JPEGFactory.createFromImage(document, ImageIO.read(new File(imagePath)), quality);
+
+                // Calculate scaling factor to fit image within the page minus margins, maintaining aspect ratio
+                float imgWidth = image.getWidth();
+                float imgHeight = image.getHeight();
+                float pageWidthForImage = PDRectangle.A4.getWidth() - 2 * margin; // Subtracting total margin from width
+                float pageHeightForImage = PDRectangle.A4.getHeight() - 2 * margin; // Subtracting total margin from height
+
+                float scaleX = pageWidthForImage / imgWidth;
+                float scaleY = pageHeightForImage / imgHeight;
+                float scale = Math.min(scaleX, scaleY);
+
+                // Resize the image dimensions with the scale
+                imgWidth *= scale;
+                imgHeight *= scale;
+
+                // Create a new page and add it to the document
+                PDPage page = new PDPage(PDRectangle.A4);
+                document.addPage(page);
+
+                // Get the content stream for the page
+                try (PDPageContentStream contentStream = new PDPageContentStream(document, page)) {
+                    // Calculate the centered position considering the total margin around the page
+                    float x = (page.getMediaBox().getWidth() - imgWidth) / 2; // Centered without adding margin again
+                    float y = (page.getMediaBox().getHeight() - imgHeight) / 2; // Centered without adding margin again
+
+                    // Draw the scaled image onto the page at the correctly centered position
+                    contentStream.drawImage(image, x, y, imgWidth, imgHeight); // Apply margin here
+                }
+            }
+
+            // Save the final document
+            document.save(outputFile);
+        }
+        return null;
+    }
+
+    //图片矫正
+    static final OkHttpClient HTTP_CLIENT = new OkHttpClient().newBuilder().build();
+
+    public static MultipartFile imageCorrection(MultipartFile file) {
+        String name = file.getName();
+        String originalFilename = file.getOriginalFilename();
+        //文件后缀
+        String extension = getExtension(file);
+        String pre = "data:image/" + extension + ";base64,";
+        try {
+            String imgParam = pre + Base64Util.encode(file.getBytes());
+            String param = "{\"image\":\"" + imgParam + "\"}";
+            /**
+             ** headerMap是添加的请求头,
+             body是传入的参数,这里选择json,后端使用@RequestBody接收
+             */
+            String response = HttpRequest.post("http://69.172.93.148:5000/process")
+                    .header("Content-Type", "application/json")
+                    .header("x-api-key", "123456789")
+                    .body(param)
+                    .execute().body();
+
+            if (StringUtils.isNotBlank(response)) {
+                JSONObject jsonObject = JSONObject.parseObject(response);
+                String image = jsonObject.getString("image");
+                if (StringUtils.isNotBlank(image)){
+                    //有前缀
+                    byte[] decode = Base64.getDecoder().decode(image.split(",")[1]);
+                    // 内容类型
+                    String contentType = "image/" + extension;
+                    return new MockMultipartFile(name, originalFilename, contentType, decode);
+                }
+                return null;
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
 }

+ 3 - 1
ruoyi-common/src/main/java/com/ruoyi/common/utils/file/MimeTypeUtils.java

@@ -36,7 +36,9 @@ public class MimeTypeUtils
             // 视频格式
             "mp4", "avi", "rmvb",
             // pdf
-            "pdf" };
+            "pdf" ,
+            //app
+            "wgt","apk"};
 
     public static String getExtension(String prefix)
     {

+ 80 - 0
ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java

@@ -11,6 +11,7 @@ import java.net.URL;
 import java.net.URLConnection;
 import java.nio.charset.StandardCharsets;
 import java.security.cert.X509Certificate;
+import java.util.Map;
 import javax.net.ssl.HostnameVerifier;
 import javax.net.ssl.HttpsURLConnection;
 import javax.net.ssl.SSLContext;
@@ -271,4 +272,83 @@ public class HttpUtils
             return true;
         }
     }
+
+    /**
+     * 向指定 URL 发送GET方法的请求
+     *
+     * @param url 发送请求的 URL
+     * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
+     * @return 所代表远程资源的响应结果
+     */
+    public static String sendGetMap(String url, String param, Map<String,String> map)
+    {
+        return sendGetMap(url, param, Constants.UTF8,map);
+    }
+    /**
+     * 向指定 URL 发送GET方法的请求(接收一个MAP头信息)
+     *
+     * @param url 发送请求的 URL
+     * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
+     * @param contentType 编码类型
+     * @return 所代表远程资源的响应结果
+     */
+    public static String sendGetMap(String url, String param, String contentType, Map<String,String> map)
+    {
+        StringBuilder result = new StringBuilder();
+        BufferedReader in = null;
+        try
+        {
+            String urlNameString = url + "?" + param;
+            log.info("sendGet - {}", urlNameString);
+            URL realUrl = new URL(urlNameString);
+            URLConnection connection = realUrl.openConnection();
+            connection.setRequestProperty("accept", "*/*");
+            connection.setRequestProperty("connection", "Keep-Alive");
+            connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
+            if (map != null && map.size() > 0){
+                for (String key : map.keySet()) {
+                    connection.setRequestProperty(key,map.get(key));
+                }
+            }
+            connection.connect();
+            in = new BufferedReader(new InputStreamReader(connection.getInputStream(), contentType));
+            String line;
+            while ((line = in.readLine()) != null)
+            {
+                result.append(line);
+            }
+            log.info("recv - {}", result);
+        }
+        catch (ConnectException e)
+        {
+            log.error("调用HttpUtils.sendGet ConnectException, url=" + url + ",param=" + param, e);
+        }
+        catch (SocketTimeoutException e)
+        {
+            log.error("调用HttpUtils.sendGet SocketTimeoutException, url=" + url + ",param=" + param, e);
+        }
+        catch (IOException e)
+        {
+            log.error("调用HttpUtils.sendGet IOException, url=" + url + ",param=" + param, e);
+        }
+        catch (Exception e)
+        {
+            log.error("调用HttpsUtil.sendGet Exception, url=" + url + ",param=" + param, e);
+        }
+        finally
+        {
+            try
+            {
+                if (in != null)
+                {
+                    in.close();
+                }
+            }
+            catch (Exception ex)
+            {
+                log.error("调用in.close Exception, url=" + url + ",param=" + param, ex);
+            }
+        }
+        return result.toString();
+    }
 }

+ 140 - 0
ruoyi-common/src/main/java/com/ruoyi/common/utils/jPush/AbstractJPushToolUtil.java

@@ -0,0 +1,140 @@
+package com.ruoyi.common.utils.jPush;
+
+import cn.jiguang.common.resp.APIConnectionException;
+import cn.jiguang.common.resp.APIRequestException;
+import cn.jpush.api.JPushClient;
+import cn.jpush.api.push.PushResult;
+import cn.jpush.api.push.model.Message;
+import cn.jpush.api.push.model.Options;
+import cn.jpush.api.push.model.Platform;
+import cn.jpush.api.push.model.PushPayload;
+import cn.jpush.api.push.model.audience.Audience;
+import cn.jpush.api.push.model.notification.AndroidNotification;
+import cn.jpush.api.push.model.notification.IosAlert;
+import cn.jpush.api.push.model.notification.Notification;
+import com.alibaba.fastjson2.JSON;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.PostConstruct;
+
+@Component
+public abstract class AbstractJPushToolUtil {
+
+    private static final Logger log = LoggerFactory.getLogger(AbstractJPushToolUtil.class);
+
+    /*@Autowired
+    private JPushConfig jPush;*/
+
+    protected static AbstractJPushToolUtil abstractJPushToolUtils;
+
+    @PostConstruct
+    public void init() {
+        abstractJPushToolUtils = this;
+    }
+
+
+    private final static String appKey = "a6413fdbfa71dd4f27f4c9f4";
+
+    private final static String masterSecret = "def1b7b57c7924339773e2cb";
+
+    private static JPushClient jPushClient = new JPushClient(masterSecret, appKey);
+
+    /**
+     * 发送给指定极光Id
+     *
+     * @param registrationId
+     * @param notificationTitle
+     * @param msgTitle
+     * @param msgContent
+     * @param jPushVO
+     * @return
+     */
+    public static boolean sendToRegistrationId1(String notificationTitle, String
+            msgTitle, String msgContent, String jPushVO, String... registrationId) {
+        boolean result = false;
+        try {
+            PushPayload pushPayload = buildPushObject_all_registrationId_alertWithTitle
+                    (notificationTitle, msgTitle, msgContent, jPushVO, registrationId);
+            //TODO
+            if(pushPayload == null){
+                return result;
+            }
+            log.info("极光推送入参信息pushPayload:{}", JSON.toJSONString(pushPayload));
+            PushResult pushResult = jPushClient.sendPush(pushPayload);
+            log.info("极光推送出参信息pushResult:{}", JSON.toJSONString(pushResult));
+            if (pushResult.getResponseCode() == 200) {
+                result = true;
+            }
+        } catch (APIConnectionException e) {
+            e.printStackTrace();
+        } catch (APIRequestException e) {
+            e.printStackTrace();
+        }
+        return result;
+
+    }
+    /**
+     * 给指定设备id推送
+     *
+     * @param notificationTitle 通知标题
+     * @param msgTitle          消息标题
+     * @param msgContent        消息内容
+     * @param jPushVO       附加字段
+     * @param registrationId     设备id
+     * @return
+     */
+
+    private static PushPayload buildPushObject_all_registrationId_alertWithTitle(
+            String notificationTitle, String msgTitle, String msgContent, String jPushVO, String... registrationId) {
+        return PushPayload.newBuilder()
+                //指定要推送的平台,all代表当前应用配置了的所有平台,也可以传android等具体平台
+                .setPlatform(Platform.all())
+                //指定推送的接收对象,all代表所有人,也可以指定已经设置成功的tag或alias或该应应用客户端调用接口获取到的registration id
+                .setAudience(Audience.registrationId(registrationId))
+                //jpush的通知,android的由jpush直接下发,iOS的由apns服务器下发,Winphone的由mpns下发
+                .setNotification(Notification.newBuilder()
+                        //指定当前推送的android通知
+                        .addPlatformNotification(
+                                AndroidNotification.newBuilder()
+                                        .setTitle(notificationTitle)
+                                        .setAlert(msgContent)
+                                        //此字段为透传字段(类型被极光限定,不能传object),不会显示在通知栏。用户可以通过此字段来做一些定制需求,如特定的key传要指定跳转的页面(value)
+                                        .addExtra("data", JSON.toJSONString(jPushVO))
+                                        .build())
+                        .build())
+
+                //Platform指定了哪些平台就会像指定平台中符合推送条件的设备进行推送。 jpush的自定义消息,
+                // sdk默认不做任何处理,不会有通知提示。建议看文档http://docs.jpush.io/guideline/faq/的
+                // [通知与自定义消息有什么区别?]了解通知和自定义消息的区别
+                .setMessage(Message.newBuilder()
+                        .setMsgContent(msgContent)
+                        .setTitle(msgTitle)
+                        .addExtra("data", JSON.toJSONString(jPushVO))
+                        .build())
+                .setOptions(Options.newBuilder()
+                        //此字段的值是用来指定本推送要推送的apns环境,false表示开发,true表示生产;对android和自定义消息无意义
+                        .setApnsProduction(false)
+                        //此字段是给开发者自己给推送编号,方便推送者分辨推送记录
+                        .setSendno(1)
+                        //此字段的值是用来指定本推送的离线保存时长,如果不传此字段则默认保存一天,最多指定保留十天;
+                        .setTimeToLive(86400)
+                        .build())
+                .build();
+    }
+
+
+    /**
+     * 获取IOS的IosAlert
+     *
+     * @param notificationTitle
+     * @param subTitle
+     * @param msgContent
+     * @return
+     */
+    private static IosAlert queryIosAlert(String notificationTitle, String subTitle, String msgContent) {
+        return IosAlert.newBuilder().setTitleAndBody(notificationTitle, subTitle, msgContent).build();
+    }
+
+    }

+ 62 - 0
ruoyi-common/src/main/java/com/ruoyi/common/utils/jPush/JPushConfig.java

@@ -0,0 +1,62 @@
+package com.ruoyi.common.utils.jPush;/*
+package com.ruoyi.common.utils.jPush;
+
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+@Component
+public class JPushConfig {
+
+    */
+/**
+     * 极光官网-个人管理中心-点击查看-secret
+     *//*
+
+    @Value("${jpush.masterSecret}")
+    private String masterSecret;
+
+    */
+/**
+     * 指定本推送要推送的apns环境,true表示生产,false表示开发
+     *//*
+
+    @Value("${jpush.environment}")
+    private boolean environment;
+
+    */
+/**
+     * 极光官网-个人管理中心-appkey
+     *//*
+
+    @Value("${push.appKey}")
+    private String appKey;
+
+    public String getMasterSecret() {
+        return masterSecret;
+    }
+
+    public boolean isEnvironment() {
+        return environment;
+    }
+
+    public String getAppKey() {
+        return appKey;
+    }
+
+    public void setMasterSecret(String masterSecret) {
+        this.masterSecret = masterSecret;
+    }
+
+    public void setEnvironment(boolean environment) {
+        this.environment = environment;
+    }
+
+    public void setAppKey(String appKey) {
+        this.appKey = appKey;
+    }
+
+
+
+}
+*/

+ 37 - 0
ruoyi-common/src/main/java/com/ruoyi/common/utils/jPush/JPushToolUtil.java

@@ -0,0 +1,37 @@
+package com.ruoyi.common.utils.jPush;
+
+
+import org.springframework.stereotype.Component;
+
+@Component
+public class JPushToolUtil extends AbstractJPushToolUtil {
+    /**
+     * 发送给指定的极光ID
+     * @param notificationTitle  通知标题
+     * @param msgTitle 内容标题
+     * @param msgContent 内容
+     * @param jPushVO 扩展的json
+     * @param registrationId 极光id
+     * @return
+     */
+    public static boolean sendToRegistrationId(
+            String notificationTitle,
+            String msgTitle,
+            String msgContent,
+            String jPushVO,
+            String... registrationId) {
+        return sendToRegistrationId1(notificationTitle,msgTitle,msgContent,jPushVO,registrationId);
+    }
+
+    /*public static void main(String[] args) {
+        String num = "-0405-别名";
+        String notificationTitle = "推送测试-通知标题" + num;
+        String msgTitle = "推送测试-内容标题" + num;
+        String msgContent = "我是内容" + num;
+        String jPushVO = "我是扩展的json" + num;
+        String[]  registrationId = {"", ""};
+        boolean b = JPushToolUtil.sendToRegistrationId(notificationTitle, msgTitle, msgContent, jPushVO, registrationId);
+        System.out.println("i="+b);
+    }*/
+}
+

+ 51 - 0
ruoyi-common/src/main/java/com/ruoyi/common/utils/jPush/JPushVO.java

@@ -0,0 +1,51 @@
+package com.ruoyi.common.utils.jPush;
+
+
+/**
+ * 极光拓展字段不能传输object,限制了类型,所以封装更好些
+ * 此类为极光推送拓展字段封装类(目前字段是暂定,你也可以拓展)
+ *
+ * @author juzi
+ * @date 2022-12-2
+ */
+public class JPushVO {
+    private Long id;
+
+    private String userName;
+
+    private String content;
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public String getUserName() {
+        return userName;
+    }
+
+    public void setUserName(String userName) {
+        this.userName = userName;
+    }
+
+    public String getContent() {
+        return content;
+    }
+
+    public void setContent(String content) {
+        this.content = content;
+    }
+
+    @Override
+    public String toString() {
+        return "JPushVO{" +
+                "id=" + id +
+                ", userName='" + userName + '\'' +
+                ", content='" + content + '\'' +
+                '}';
+    }
+}
+

+ 228 - 0
ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelFillUtils.java

@@ -0,0 +1,228 @@
+package com.ruoyi.common.utils.poi;
+import com.ruoyi.common.config.RuoYiConfig;
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.ss.util.CellUtil;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.*;
+import java.util.regex.Pattern;
+
+public class ExcelFillUtils {
+
+    //    public static final String FILL_EXPRESSION_REGEX = "\\{\\.\\w+\\}";
+    private static final String FILL_EXPRESSION_REGEX = "\\{\\.[\\p{L}\\p{M}\\S]+\\}";
+
+    /**
+     * 给定模板,指定某个页签,将数据填充到模板中的指定页签,并在模板所在目录生成新的副本文件。
+     * @param template 模板文件地址
+     * @param sheetName 页签名称
+     * @param data 待填充的数据,数据格式如下
+     *                  [
+     *                      {"colName1":v1 ,"colName2":v2...},
+     *                      {"colName1":v1 ,"colName2":v2...}
+     *                      ,...
+     *                  ]
+     * @return 新生成的副本文件的地址
+     *
+     * */
+    public static String fillOneSheet(String template ,String sheetName , List<Map<String,Object>> data) {
+        return fillOneSheet(template ,FileUtils.getAvailableFullName(template) ,sheetName ,data);
+    }
+
+    /**
+     * 给定模板,指定某个页签,将数据填充到模板中的指定页签,并将数据导入到指定文件上。
+     * @param template 模板文件地址
+     * @param outputFile 新生成的文件的地址
+     * @param sheetName 页签名称
+     * @param data 待填充的数据,数据格式如下
+     *                  [
+     *                      {"colName1":v1 ,"colName2":v2...},
+     *                      {"colName1":v1 ,"colName2":v2...}
+     *                      ,...
+     *                  ]
+     * @return 新生成的副本文件的地址
+     *
+     * */
+    public static String fillOneSheet(String template , String outputFile,String sheetName , List<Map<String,Object>> data){
+
+        try (Workbook workbook = new XSSFWorkbook(new FileInputStream(template))) {
+
+            fill(workbook,sheetName,data);//填充数据
+            refreshFormula(workbook);//刷新公式
+
+            try (FileOutputStream outputStream = new FileOutputStream(outputFile)) {
+                workbook.write(outputStream);
+            }catch (Exception e){
+                throw new RuntimeException(e);
+            }
+
+        }catch (IOException e){
+            throw new RuntimeException(e);
+        }
+
+        return outputFile;
+    }
+
+    /**
+     * 给定模板,将数据填充到模板中的多个页签,并在模板所在目录生成新的副本文件。
+     * @param template 模板文件地址
+     * @param datas 待填充的数据集,数据格式如下
+     *              {
+     *                  "SheetName1":[
+     *                      {"colName1":v1 ,"colName2":v2...},
+     *                      {"colName1":v1 ,"colName2":v2...}
+     *                      ,...
+     *                  ],
+     *                  "SheetName2":[
+     *                      {"colName1":v1 ,"colName2":v2...}
+     *                      {"colName1":v1 ,"colName2":v2...}
+     *                      ,...
+     *                  ],
+     *                  ...
+     *              }
+     *
+     * */
+    public static String fillMultipleSheet(String template ,Map<String,List<Map<String,Object>>> datas) {
+        return fillMultipleSheet(template ,FileUtils.getAvailableFullName(template) ,datas);
+    }
+
+    /**
+     * 给定模板,将数据填充到模板中的多个页签,并将数据导入到指定文件上。
+     * @param template 模板文件地址
+     * @param datas 待填充的数据集,数据格式如下
+     *              {
+     *                  "SheetName1":[
+     *                      {"colName1":v1 ,"colName2":v2...},
+     *                      {"colName1":v1 ,"colName2":v2...}
+     *                      ,...
+     *                  ],
+     *                  "SheetName2":[
+     *                      {"colName1":v1 ,"colName2":v2...}
+     *                      {"colName1":v1 ,"colName2":v2...}
+     *                      ,...
+     *                  ],
+     *                  ...
+     *              }
+     *
+     * */
+    public static String fillMultipleSheet(String template ,String outputFile ,Map<String,List<Map<String,Object>>> datas){
+
+        try (Workbook workbook = new XSSFWorkbook(new FileInputStream(template))) {
+
+            datas.forEach( (sheetName ,data)-> fill(workbook,sheetName,data) );//填充数据
+            refreshFormula(workbook);//刷新公式
+
+            try (FileOutputStream outputStream = new FileOutputStream(outputFile)) {
+                workbook.write(outputStream);
+            }catch (Exception e){
+                throw new RuntimeException(e);
+            }
+
+        }catch (IOException e){
+            throw new RuntimeException(e);
+        }
+
+        return outputFile;
+    }
+
+    private static Workbook fill(Workbook workbook ,String sheetName ,List<Map<String,Object>> data) {
+
+        Sheet sheet = workbook.getSheet(sheetName);
+        if (sheet == null) {
+            throw new RuntimeException(String.format("sheet [%s] does not exist.",sheetName));
+        }
+
+        //找到所有的表达式单元格
+        Map<String,Cell> expressionCellMap = new HashMap<>();
+        for( int i = 0 ;i < sheet.getPhysicalNumberOfRows() ;i++){
+            Row row = sheet.getRow(i);
+            for( int j = 0 ;j< row.getPhysicalNumberOfCells() ;j++){
+                Cell cell = row.getCell(j);
+                cell.setCellType(CellType.STRING);
+                if( !Objects.isNull(cell) && isFillExpression(cell.getStringCellValue()) ){//判断该单元格是否是填充公式
+                    expressionCellMap.put(getColNameFromEx(cell.getStringCellValue()),cell);
+                }
+            }
+        }
+
+        //填充数据
+        for(int i = 0 ;i< data.size() ;i++){
+            Map<String,Object> dataRow = data.get(i);
+            for (Map.Entry<String,Object> entry : dataRow.entrySet()){
+                String colName = entry.getKey();
+                Object value = entry.getValue();
+                if(expressionCellMap.containsKey(colName)){
+
+                    Cell cell = expressionCellMap.get(colName);//公式所在的单元格
+                    int rowID = cell.getRowIndex() + i;
+                    int colId = cell.getColumnIndex();
+
+                    Row fillRow = sheet.getRow(rowID);
+                    fillRow = Objects.isNull(fillRow) ? sheet.createRow(rowID) : fillRow;
+                    Cell fillCell = fillRow.getCell(colId);
+                    //创建的新单元格需要复制公式单元格的格式
+                    fillCell = Objects.isNull(fillCell) ? CellUtil.createCell(fillRow,colId,"", cell.getCellStyle()) : fillCell;
+
+                    if ( value instanceof String){
+                        fillCell.setCellValue( String.valueOf(value) );
+                    }else if( value instanceof Number ){
+                        fillCell.setCellValue( ((Number)value).doubleValue() );
+                    }else{
+                        throw new RuntimeException(String.format("Unsupported data type [%s].",value.getClass().toString()));
+                    }
+
+                }
+            }
+        }
+
+        return workbook;
+    }
+
+    private static void refreshFormula(Workbook workbook){
+        FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator();
+        evaluator.evaluateAll();
+    }
+
+    private static boolean isFillExpression(String ex){
+        if (ex.isEmpty()) return false;
+        return Pattern.matches(FILL_EXPRESSION_REGEX ,ex);
+    }
+
+    private static String getColNameFromEx(String ex){
+        if (!isFillExpression(ex)) throw new RuntimeException("Illegal expression " + ex );
+        return ex.substring(2,ex.length() - 1);
+    }
+
+    public static void main(String[] args) {
+        String time = "2024-07-30 14:50:00";
+        String timeData = time.split(" ")[0];
+        System.out.println("生成文档路径:" + timeData);
+        // 向列表中添加数据
+                /*list.add( Map.of("name","zou" ,"age" ,18) );
+                list.add( Map.of("name","li" ,"age" ,28) );
+                list.add( Map.of("name","wang" ,"age" ,15) );
+                list.add( Map.of("name","quan" ,"age" ,19) );
+                list.add( Map.of("name","zhao" ,"age" ,98) );*/
+        /*List<Map<String,Object>> list = new ArrayList<>();
+        Map<String,Object> map = new HashMap<>();
+        map.put("name","111");
+        map.put("name1","222");
+        map.put("name2","333");
+        map.put("name3","444");
+        map.put("name4","555");
+        list.add(map);
+        //fileName = FileUploadUtils.extractFilenameLoanApplicationNumberNoHzm("项目评审意见签批表");
+        String fileName = "-项目评审意见签批表";
+        String fileNameHz = fileName + ".xlsx";
+        //String templatePath = RuoYiConfig.getProfile() + "/mb/项目评审意见签批表.xlsx";
+        String templatePath = "D:\\ruoyi\\uploadPath\\mb\\项目评审意见签批表.xlsx";
+        //String fileDir = RuoYiConfig.getProfile() + "/mb/temporarily/" + fileNameHz;
+        String fileDir = "D:\\ruoyi\\uploadPath\\mb\\temporarily\\"+ fileNameHz;
+        String sheet = ExcelFillUtils.fillOneSheet(templatePath, fileDir, "Sheet1", list);
+        System.out.println("生成文档路径:" + sheet);*/
+    }
+
+}
+

+ 87 - 0
ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/FileUtils.java

@@ -0,0 +1,87 @@
+package com.ruoyi.common.utils.poi;
+
+import java.io.*;
+import java.util.HashSet;
+import java.util.Objects;
+import java.util.Set;
+
+public class FileUtils {
+
+    private static final String COPY_FILE_SUFFIX = "_副本";
+
+    /**
+     * 将输入流写入文件
+     * @param in 输入流
+     * @param path 输出文件的路径
+     * @param fileName 输出文件的名称
+     *
+     * */
+    public static void writeFile(InputStream in ,String path ,String fileName) throws FileNotFoundException {
+
+        FileOutputStream outputStream = new FileOutputStream("");
+
+    }
+
+
+    /**
+     * 给定一个目录和文件,若该目录存在名称相同的文件,则覆盖原先的文件。
+     * @param path 文件的目录
+     * @param fileName 文件名
+     * @return 可用的文件名
+     * */
+    public static String getAvailableName(String path ,String fileName){
+
+        File filePath = new File(path);
+
+        String suffix = fileName.substring(fileName.lastIndexOf("."));
+        File[] files = filePath.listFiles( f -> f.getName().endsWith(suffix) );
+        if ( Objects.isNull(files) ) return fileName;
+
+        Set<String> fileNameSet = new HashSet<>();
+        for (File file: files ) {
+            fileNameSet.add(file.getName().substring(0 , file.getName().lastIndexOf(".")));
+        }
+
+        //boolean isExist = true;
+        //int count = 1;
+        String tempFileName = fileName.substring(0,fileName.lastIndexOf("."));
+        String tempFileName1 = tempFileName;
+       /* while(isExist){
+
+            if (fileNameSet.contains(tempFileName)){
+                tempFileName = tempFileName1 + COPY_FILE_SUFFIX + count++;
+            }else{
+                isExist = false;
+            }
+
+        }*/
+
+        return tempFileName + suffix;
+    }
+
+
+    /**
+     * 给定一个文件的完整路径,若该文件已经存在,则覆盖原先的文件。
+     * @param fullPath 文件的完整路径
+     * @return 可用的文件名
+     * */
+    public static String getAvailableName( String fullPath ){
+        File file = new File(fullPath);
+        if ( !file.isFile() ) throw new RuntimeException( String.format("not a file [%s].",fullPath));
+
+        return getAvailableName( file.getParent() ,file.getName() );
+    }
+
+    /**
+     * 给定一个文件的完整路径,若该文件已经存在,则覆盖原先的文件。
+     * @param fullPath 文件的完整路径
+     * @return 完整可用的文件名
+     * */
+    public static String getAvailableFullName( String fullPath ){
+        File file = new File(fullPath);
+        if ( !file.isFile() ) throw new RuntimeException( String.format("not a file [%s].",fullPath));
+
+        return file.getParent() + File.separator + getAvailableName(fullPath);
+    }
+
+}

+ 100 - 0
ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/WordUtil.java

@@ -0,0 +1,100 @@
+package com.ruoyi.common.utils.poi;
+
+import com.deepoove.poi.XWPFTemplate;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.util.Assert;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author Jerry
+ * @Title: WordUtil
+ * @Description: Word工具类
+ * @date 219/10/6 9:09
+ */
+public class WordUtil {
+
+    private static Logger logger = LoggerFactory.getLogger(WordUtil.class);
+
+
+    /**
+     * 根据模板填充内容生成word
+     * 调用方法参考下面的main方法,详细文档参考官方文档
+     * Poi-tl模板引擎官方文档:http://deepoove.com/poi-tl/
+     *
+     * @param templatePath word模板文件路径
+     * @param fileDir      生成的文件存放地址
+     * @param fileName     生成的文件名,不带格式。假如要生成abc.docx,则fileName传入abc即可
+     * @param paramMap     替换的参数集合
+     * @return 生成word成功返回生成的文件的路径,失败返回空字符串
+     */
+    public static String createWord(String templatePath, String fileDir, String fileName, Map<String, Object> paramMap) {
+        Assert.notNull(templatePath, "word模板文件路径不能为空");
+        Assert.notNull(fileDir, "生成的文件存放地址不能为空");
+        Assert.notNull(fileName, "生成的文件名不能为空");
+
+        // 生成的word格式
+        String formatSuffix = ".docx";
+        // 拼接后的文件名
+        fileName = fileName + formatSuffix;
+
+        // 生成的文件的存放路径
+        if (!fileDir.endsWith("/")) {
+            fileDir = fileDir + File.separator;
+        }
+
+        File dir = new File(fileDir);
+        if (!dir.exists()) {
+            logger.info("生成word数据时存储文件目录{}不存在,为您创建文件夹!", fileDir);
+            dir.mkdirs();
+        }
+
+        //判断系统
+        /*String osName = System.getProperty("os.name").toLowerCase();
+        if (osName.contains("win")) {
+            fileDir = fileDir.replaceAll("/","\\\\");
+        }*/
+        String filePath = fileDir + fileName;
+        // 读取模板templatePath并将paramMap的内容填充进模板,即编辑模板+渲染数据
+        XWPFTemplate template = XWPFTemplate.compile(templatePath).render(paramMap);
+        try {
+            // 将填充之后的模板写入filePath
+            template.writeToFile(filePath);
+            template.close();
+        } catch (Exception e) {
+            logger.error("生成word异常", e);
+            e.printStackTrace();
+            return "";
+        }
+        return filePath;
+    }
+
+    public static void main(String[] args) {
+
+        String s = "D:/ruoyi/uploadPath/mb/temporarily/RZDB202405171421120925517/";
+
+        //判断系统
+        String osName = System.getProperty("os.name").toLowerCase();
+        if (osName.contains("win")) {
+            s = s.replaceAll("/","\\\\");
+        }
+
+        Map<String, Object> params = new HashMap<>();
+        // 渲染文本
+        //params.put("title", "XXX工程");
+        params.put("enterpriseName", "XXX工程");
+        //...
+        // 渲染图片
+        //params.put("picture", new PictureRenderData(120, 120, "D:\\wx.png"));
+        // TODO 渲染其他类型的数据请参考官方文档
+        String templatePath = "D:\\ruoyi\\uploadPath\\mb\\委托担保申请书.docx";
+        String fileDir = "D:\\ruoyi\\uploadPath\\mb\\temporarily";
+        String fileName = "wtdbsqs";
+
+        String wordPath = WordUtil.createWord(templatePath, fileDir, fileName, params);
+        System.out.println("生成文档路径:" + wordPath);
+    }
+}

BIN
ruoyi-common/src/main/java/resources/word/zdd.docx


+ 12 - 0
ruoyi-framework/pom.xml

@@ -58,6 +58,18 @@
             <groupId>com.ruoyi</groupId>
             <artifactId>ruoyi-system</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi-scratchpad</artifactId>
+            <version>5.2.3</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.hynnet</groupId>
+            <artifactId>jacob</artifactId>
+            <version>1.18</version>
+            <scope>compile</scope>
+        </dependency>
 
     </dependencies>
 

+ 18 - 2
ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java

@@ -1,5 +1,6 @@
 package com.ruoyi.framework.config;
 
+import com.ruoyi.common.encoder.AesPasswordEncoder;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Bean;
 import org.springframework.http.HttpMethod;
@@ -111,10 +112,14 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
                 // 过滤请求
                 .authorizeRequests()
                 // 对于登录login 注册register 验证码captchaImage 允许匿名访问
-                .antMatchers("/login", "/register", "/captchaImage").permitAll()
+                .antMatchers("/login", "/register", "/captchaImage","/pageoffice/**","/sendSms/sendLoginSms","/console/**").permitAll()
                 // 静态资源,可匿名访问
                 .antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**").permitAll()
                 .antMatchers("/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**").permitAll()
+                .antMatchers("/Excel.html", "/Word.html", "/*.zz", "/**/*.zz", "/pageoffice.js","/jquery.min.js").permitAll()
+                .antMatchers("/*.exe").permitAll()
+                .antMatchers("/common/uploadNew").permitAll()
+                .antMatchers("/sendSms/**","/applet/**").permitAll()
                 // 除上面外的所有请求全部需要鉴权认证
                 .anyRequest().authenticated()
                 .and()
@@ -137,12 +142,23 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
         return new BCryptPasswordEncoder();
     }
 
+
+    /**
+     * AES加密实现
+     */
+    @Bean
+    public AesPasswordEncoder aesPasswordEncoder()
+    {
+        return new AesPasswordEncoder();
+    }
+
     /**
      * 身份认证接口
      */
     @Override
     protected void configure(AuthenticationManagerBuilder auth) throws Exception
     {
-        auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
+        //auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
+        auth.userDetailsService(userDetailsService).passwordEncoder(aesPasswordEncoder());
     }
 }

+ 384 - 25
ruoyi-framework/src/main/java/com/ruoyi/framework/manager/factory/AsyncFactory.java

@@ -1,6 +1,28 @@
 package com.ruoyi.framework.manager.factory;
 
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
 import java.util.TimerTask;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+
+import com.ruoyi.common.config.RuoYiConfig;
+import com.ruoyi.common.core.redis.RedisCache;
+import com.ruoyi.common.utils.file.FileUploadUtils;
+import com.ruoyi.common.utils.uuid.Seq;
+import com.ruoyi.system.domain.guarantee.GuaranteeInfo;
+import com.ruoyi.system.domain.guarantee.GuaranteeInfoFj;
+import com.ruoyi.system.domain.loan.LoanApplicationFj;
+import com.ruoyi.system.domain.loan.ShareholderFj;
+import com.ruoyi.system.mapper.GuaranteeInfoFjMapper;
+import com.ruoyi.system.mapper.ShareholderFjMapper;
+import com.ruoyi.system.service.guarantee.IGuaranteeInfoFjService;
+import com.ruoyi.system.service.loan.ILoanApplicationFjService;
+import org.apache.commons.io.FilenameUtils;
+import org.apache.commons.lang3.ObjectUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import com.ruoyi.common.constant.Constants;
@@ -15,35 +37,48 @@ import com.ruoyi.system.domain.SysOperLog;
 import com.ruoyi.system.service.ISysLogininforService;
 import com.ruoyi.system.service.ISysOperLogService;
 import eu.bitwalker.useragentutils.UserAgent;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+
+import static com.ruoyi.common.constant.CommonConstants.*;
 
 /**
  * 异步工厂(产生任务用)
- * 
+ *
  * @author ruoyi
  */
-public class AsyncFactory
-{
+
+@Component
+public class AsyncFactory {
     private static final Logger sys_user_logger = LoggerFactory.getLogger("sys-user");
 
+    @Autowired
+    private static RedisCache redisCache;
+
+    @Autowired
+    public void setRedisCache(RedisCache redisCache) {
+        AsyncFactory.redisCache = redisCache;
+    }
+
     /**
      * 记录登录信息
-     * 
+     *
      * @param username 用户名
-     * @param status 状态
-     * @param message 消息
-     * @param args 列表
+     * @param status   状态
+     * @param message  消息
+     * @param args     列表
      * @return 任务task
      */
     public static TimerTask recordLogininfor(final String username, final String status, final String message,
-            final Object... args)
-    {
+                                             final Object... args) {
         final UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
         final String ip = IpUtils.getIpAddr();
-        return new TimerTask()
-        {
+        return new TimerTask() {
             @Override
-            public void run()
-            {
+            public void run() {
                 String address = AddressUtils.getRealAddressByIP(ip);
                 StringBuilder s = new StringBuilder();
                 s.append(LogUtils.getBlock(ip));
@@ -66,12 +101,9 @@ public class AsyncFactory
                 logininfor.setOs(os);
                 logininfor.setMsg(message);
                 // 日志状态
-                if (StringUtils.equalsAny(status, Constants.LOGIN_SUCCESS, Constants.LOGOUT, Constants.REGISTER))
-                {
+                if (StringUtils.equalsAny(status, Constants.LOGIN_SUCCESS, Constants.LOGOUT, Constants.REGISTER)) {
                     logininfor.setStatus(Constants.SUCCESS);
-                }
-                else if (Constants.LOGIN_FAIL.equals(status))
-                {
+                } else if (Constants.LOGIN_FAIL.equals(status)) {
                     logininfor.setStatus(Constants.FAIL);
                 }
                 // 插入数据
@@ -82,21 +114,348 @@ public class AsyncFactory
 
     /**
      * 操作日志记录
-     * 
+     *
      * @param operLog 操作日志信息
      * @return 任务task
      */
-    public static TimerTask recordOper(final SysOperLog operLog)
-    {
-        return new TimerTask()
-        {
+    public static TimerTask recordOper(final SysOperLog operLog) {
+        return new TimerTask() {
             @Override
-            public void run()
-            {
+            public void run() {
                 // 远程查询操作地点
                 operLog.setOperLocation(AddressUtils.getRealAddressByIP(operLog.getOperIp()));
                 SpringUtils.getBean(ISysOperLogService.class).insertOperlog(operLog);
             }
         };
     }
+
+    /**
+     * 合并图片生成PDF保存为文件
+     *
+     * @param loanApplicationFjList
+     * @return
+     */
+    public static TimerTask createPdfFromImages(List<LoanApplicationFj> loanApplicationFjList, String loanApplicationNumber) {
+        return new TimerTask() {
+            @Override
+            public void run() {
+                String key = "lock:A:" + loanApplicationNumber;
+                redisCache.setCacheObject(key, 1, 5, TimeUnit.MINUTES);
+                //自定义锁,必须要所有异步任务都跑完才能再次修改
+                //根据文件类型进行判断是否需要合成pdf
+                Map<String, List<LoanApplicationFj>> bigTypeMap = loanApplicationFjList.stream().collect(Collectors.groupingBy(LoanApplicationFj::getBigType));
+                if (bigTypeMap.size() > 0) {
+                    List<LoanApplicationFj> loanApplicationFjListA = bigTypeMap.get(A);
+                    List<LoanApplicationFj> loanApplicationFjListB = bigTypeMap.get(B);
+                    if (loanApplicationFjListA != null && loanApplicationFjListA.size() > 0) {
+                        createPdfFromImages(loanApplicationFjList, loanApplicationFjListA, loanApplicationNumber, A);
+                    }
+                    if (loanApplicationFjListB != null && loanApplicationFjListB.size() > 0) {
+                        createPdfFromImages(loanApplicationFjList, loanApplicationFjListB, loanApplicationNumber, B);
+                    }
+                }
+                //自定义锁,必须要所有异步任务都跑完才能再次修改
+                redisCache.deleteObject(key);
+            }
+        };
+    }
+
+    /**
+     * @param loanApplicationFjList  全体附件
+     * @param loanApplicationFjListA 分附件大类集合
+     * @return
+     */
+    public static void createPdfFromImages(List<LoanApplicationFj> loanApplicationFjList, List<LoanApplicationFj> loanApplicationFjListA, String loanApplicationNumber, String bigType) {
+        if (loanApplicationFjListA != null && loanApplicationFjListA.size() > 0) {
+            Map<String, List<LoanApplicationFj>> typeMap = loanApplicationFjListA.stream().collect(Collectors.groupingBy(LoanApplicationFj::getType));
+            List<LoanApplicationFj> list = new ArrayList<>();
+            for (String type : typeMap.keySet()) {
+                List<LoanApplicationFj> loanApplicationFjListInsert = typeMap.get(type);
+                //获取附件名称
+                String fjName = loanApplicationFjListInsert.get(0).getName().split("_")[0];
+                List<String> typeList = loanApplicationFjListInsert.stream().filter(e -> type.equals(e.getType()) && ("png".equals(e.getName().split("\\.")[1]) || "jpg".equals(e.getName().split("\\.")[1]) || "jpeg".equals(e.getName().split("\\.")[1]))).map(LoanApplicationFj::getUrl).collect(Collectors.toList());
+                if (typeList.size() > 0) {
+                    for (int i = 0; i < typeList.size(); i++) {
+                        ///profile/upload/RZDB202405281147018884551/公司章程_20240528114820A002.png 前缀替换
+                        String replaced = typeList.get(i).replace("/profile/upload", RuoYiConfig.getUploadPath());
+                        typeList.set(i, replaced);
+                    }
+                    //先删除原先的pdf数据库记录
+                    List<LoanApplicationFj> pdfOne = loanApplicationFjListInsert.stream().filter(e -> ObjectUtils.isNotEmpty(e.getRemark()) && e.getRemark().equals(ONE) && ("pdf".equals(e.getName().split("\\.")[1]))).collect(Collectors.toList());
+                    if (pdfOne.size() > 0) {
+                        for (LoanApplicationFj loanApplicationFj : pdfOne) {
+                            //删除数据库数据
+                            SpringUtils.getBean(ILoanApplicationFjService.class).deleteLoanApplicationFjByFjId(loanApplicationFj.getFjId());
+                            //删除服务器记录
+                            String urlPdf = loanApplicationFj.getUrl();
+                            if (StringUtils.isNotBlank(urlPdf)) {
+                                String filePath = urlPdf.replace("/profile/upload", RuoYiConfig.getUploadPath());
+                                //删除服务器上对应文件
+                                File file = new File(filePath);
+                                if (file.exists()) {
+                                    if (file.delete()) {
+                                        System.out.println("删除:" + filePath);
+                                    } else {
+                                        System.out.println("删除:" + filePath + "失败");
+                                    }
+                                }
+                            }
+                        }
+                    }
+                    createPdfFromImages(list, loanApplicationFjList, typeList, loanApplicationNumber, fjName + "_" + Seq.getId(Seq.uploadSeqType), type, bigType);
+                }
+            }
+            if (list.size() > 0){
+                // 插入数据
+                SpringUtils.getBean(ILoanApplicationFjService.class).insertLoanApplicationFj(list);
+            }
+        }
+    }
+
+    /**
+     * @param imagePaths            图片地址集合
+     * @param loanApplicationNumber 申请编号
+     * @param originalFilename      pdf文件名称
+     * @param type                  文件类型
+     */
+    public static List<LoanApplicationFj> createPdfFromImages(List<LoanApplicationFj> list, List<LoanApplicationFj> loanApplicationFjList, List<String> imagePaths, String loanApplicationNumber, String originalFilename, String type, String bigType) {
+        // 上传文件路径 = 根+申请编号
+        String filePath = StringUtils.format("{}/{}/{}.{}", RuoYiConfig.getUploadPath(), loanApplicationNumber,
+                FilenameUtils.getBaseName(originalFilename), "pdf");
+        //pdf保存位置
+        File outPutPdf = new File(filePath);
+        try {
+
+            FileUploadUtils.createPdfFromImages(imagePaths, outPutPdf);
+            //往附件信息中插入对应PDF数据
+            LoanApplicationFj applicationFj = new LoanApplicationFj();
+            applicationFj.setLoanApplicationId(loanApplicationFjList.get(0).getLoanApplicationId());
+            applicationFj.setLoanApplicationNumber(loanApplicationNumber);
+            applicationFj.setName(originalFilename + ".pdf");
+            applicationFj.setUrl(StringUtils.format("{}/{}/{}.{}", "/profile/upload", loanApplicationNumber,
+                    FilenameUtils.getBaseName(originalFilename), "pdf"));
+            applicationFj.setBigType(bigType);
+            applicationFj.setType(type);
+            //给前端判断是否是系统生成的pdf
+            applicationFj.setRemark(ONE);
+            list.add(applicationFj);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return list;
+    }
+
+
+    /**
+     * 股东附件合并图片生成PDF保存为文件
+     *
+     * @param shareholderFjList
+     * @return
+     */
+
+    public static TimerTask createPdfFromImagesShareholder(List<ShareholderFj> shareholderFjList, String loanApplicationNumber,Long loanApplicationId) {
+        return new TimerTask() {
+            @Override
+            public void run() {
+                String key = "lock:B:" + loanApplicationNumber;
+                redisCache.setCacheObject(key, 1, 5, TimeUnit.MINUTES);
+                List<String> imagePaths = new ArrayList<>();
+                //根据文件类型进行判断是否需要合成pdf
+                for (ShareholderFj shareholderFj : shareholderFjList) {
+                    //获取原先的pdf地址,去服务器上删除要替换路径
+                    String shareholderZxUrlPdf = shareholderFj.getShareholderZxUrlPdf();
+                    if (StringUtils.isNotBlank(shareholderZxUrlPdf)) {
+                        String filePath = shareholderZxUrlPdf.replace("/profile/upload", RuoYiConfig.getUploadPath());
+                        //删除服务器上对应文件
+                        File file = new File(filePath);
+                        if (file.exists()) {
+                            if (file.delete()) {
+                                System.out.println("删除:" + filePath);
+                            } else {
+                                System.out.println("删除:" + filePath + "失败");
+                            }
+                        }
+                    }
+                    String shareholderZxUrl = shareholderFj.getShareholderZxUrl();
+                    if (StringUtils.isNotEmpty(shareholderZxUrl)) {
+                        String[] split = shareholderZxUrl.split(",");
+                        for (String fileName : split) {
+                            if ("png".equals(fileName.split("\\.")[1]) || "jpg".equals(fileName.split("\\.")[1]) || "jpeg".equals(fileName.split("\\.")[1])) {
+                                imagePaths.add(fileName);
+                            }
+                        }
+                    }
+                    if (imagePaths.size() > 0) {
+                        String substring = imagePaths.get(0).substring(imagePaths.get(0).lastIndexOf("/") + 1, imagePaths.get(0).lastIndexOf("_")) + Seq.getId(Seq.uploadSeqType);
+
+                        for (int i = 0; i < imagePaths.size(); i++) {
+                            //前缀替换
+                            String replaced = imagePaths.get(i).replace("/profile/upload", RuoYiConfig.getUploadPath());
+                            imagePaths.set(i, replaced);
+                        }
+
+                        // 上传文件路径 = 根+申请编号
+                        String filePath = StringUtils.format("{}/{}/{}.{}", RuoYiConfig.getUploadPath(), loanApplicationNumber,
+                                FilenameUtils.getBaseName(substring), "pdf");
+                        //pdf保存位置
+                        File outPutPdf = new File(filePath);
+                        try {
+                            FileUploadUtils.createPdfFromImages(imagePaths, outPutPdf);
+                        } catch (IOException e) {
+                            e.printStackTrace();
+                        }
+                        shareholderFj.setShareholderZxUrlPdf(StringUtils.format("{}/{}/{}.{}", "/profile/upload", loanApplicationNumber,
+                                FilenameUtils.getBaseName(substring), "pdf"));
+                    }
+                }
+                //判断是否有股东shareholder_fj_id
+                List<ShareholderFj> shareholderFjsInsert = shareholderFjList.stream().filter(e -> ObjectUtils.isEmpty(e.getShareholderFjId())).collect(Collectors.toList());
+                if (shareholderFjsInsert.size() > 0) {
+                    for (ShareholderFj shareholderFj : shareholderFjsInsert) {
+                        shareholderFj.setLoanApplicationId(loanApplicationId);
+                        shareholderFj.setLoanApplicationNumber(loanApplicationNumber);
+                    }
+                    // 新增股东数据
+                    SpringUtils.getBean(ShareholderFjMapper.class).batchShareholderFj(shareholderFjsInsert);
+                }
+                List<ShareholderFj> shareholderFjsUpdate = shareholderFjList.stream().filter(e -> ObjectUtils.isNotEmpty(e.getShareholderFjId())).collect(Collectors.toList());
+                if (shareholderFjsUpdate.size() > 0) {
+                    for (ShareholderFj shareholderFj : shareholderFjsUpdate) {
+                        //更新股东信息
+                        SpringUtils.getBean(ShareholderFjMapper.class).updateShareholderFj(shareholderFj);
+                    }
+                }
+                redisCache.deleteObject(key);
+            }
+        };
+    }
+
+
+    /**
+     * 反担保附件合并图片生成PDF保存为文件
+     *
+     * @param guaranteeInfoList 反担保基础信息集合
+     * @return
+     */
+
+    public static TimerTask createPdfFromImagesGuaranteeInfo(List<GuaranteeInfo> guaranteeInfoList, String loanApplicationNumber) {
+        return new TimerTask() {
+            @Override
+            public void run() {
+                String key = "lock:C:" + loanApplicationNumber;
+                redisCache.setCacheObject(key, 1, 5, TimeUnit.MINUTES);
+                List<GuaranteeInfoFj> list = new ArrayList();
+                //根据文件类型进行判断是否需要合成pdf
+                for (GuaranteeInfo guaranteeInfo : guaranteeInfoList) {
+                    Long loanApplicationId = guaranteeInfo.getLoanApplicationId();
+                    Long guaranteeInfoId = guaranteeInfo.getGuaranteeInfoId();
+                    //所有反担保信息的附件
+                    List<GuaranteeInfoFj> guaranteeInfoFjList = guaranteeInfo.getGuaranteeInfoFjList();
+                    if (guaranteeInfoFjList != null && guaranteeInfoFjList.size() > 0) {
+                        for (GuaranteeInfoFj guaranteeInfoFj : guaranteeInfoFjList) {
+                            guaranteeInfoFj.setGuaranteeInfoId(guaranteeInfoId);
+                            guaranteeInfoFj.setLoanApplicationId(loanApplicationId);
+                            guaranteeInfoFj.setLoanApplicationNumber(loanApplicationNumber);
+                        }
+                        Map<String, List<GuaranteeInfoFj>> typeMap = guaranteeInfoFjList.stream().collect(Collectors.groupingBy(GuaranteeInfoFj::getType));
+                        for (String type : typeMap.keySet()) {
+                            //每个反担保信息的单个分类的附件集合
+                            List<GuaranteeInfoFj> guaranteeInfoFjInsert = typeMap.get(type);
+                            String fjName = guaranteeInfoFjInsert.get(0).getName().split("_")[0];
+                            List<String> imagePaths = guaranteeInfoFjInsert.stream().filter(e -> type.equals(e.getType()) && ("png".equals(e.getName().split("\\.")[1]) || "jpg".equals(e.getName().split("\\.")[1]) || "jpeg".equals(e.getName().split("\\.")[1]))).map(GuaranteeInfoFj::getUrl).collect(Collectors.toList());
+                            //替换前缀,获取服务器上地址
+                            if (imagePaths.size() > 0) {
+                                for (int i = 0; i < imagePaths.size(); i++) {
+                                    ///profile/upload/RZDB202405281147018884551/公司章程_20240528114820A002.png 前缀替换
+                                    String replaced = imagePaths.get(i).replace("/profile/upload", RuoYiConfig.getUploadPath());
+                                    imagePaths.set(i, replaced);
+                                }
+
+                                //先删除原先的所有pdf数据库记录
+                                GuaranteeInfoFj gInfoFj = new GuaranteeInfoFj();
+                                gInfoFj.setLoanApplicationId(loanApplicationId);
+                                gInfoFj.setLoanApplicationNumber(loanApplicationNumber);
+                                gInfoFj.setGuaranteeInfoId(guaranteeInfoId);
+                                gInfoFj.setRemark("1");
+                                List<GuaranteeInfoFj> pdfOne = SpringUtils.getBean(GuaranteeInfoFjMapper.class).selectGuaranteeInfoFjList(gInfoFj);
+                                if (pdfOne.size() > 0) {
+                                    for (GuaranteeInfoFj guaranteeInfoFj : pdfOne) {
+                                        //删除数据库数据附件记录
+                                        SpringUtils.getBean(IGuaranteeInfoFjService.class).deleteGuaranteeInfoFjByGuaranteeInfoFjId(guaranteeInfoFj.getGuaranteeInfoFjId());
+                                        //删除服务器记录
+                                        String urlPdf = guaranteeInfoFj.getUrl();
+                                        if (StringUtils.isNotBlank(urlPdf)) {
+                                            String filePath = urlPdf.replace("/profile/upload", RuoYiConfig.getUploadPath());
+                                            //删除服务器上对应文件
+                                            File file = new File(filePath);
+                                            if (file.exists()) {
+                                                if (file.delete()) {
+                                                    System.out.println("删除:" + filePath);
+                                                } else {
+                                                    System.out.println("删除:" + filePath + "失败");
+                                                }
+                                            }
+                                        }
+                                    }
+                                }
+                                //生成PDF数据库数据
+                                createPdfFromImagesGuaranteeInfoFj(list,guaranteeInfoFjInsert, imagePaths, loanApplicationNumber, fjName + "_" + Seq.getId(Seq.uploadSeqType), type, loanApplicationId, guaranteeInfoId);
+                            }
+                        }
+                        //判断是否有反担保GuaranteeInfoFjId
+                        List<GuaranteeInfoFj> guaranteeInfoFjListInsert = guaranteeInfoFjList.stream().filter(e -> ObjectUtils.isEmpty(e.getGuaranteeInfoFjId())).collect(Collectors.toList());
+                        if (guaranteeInfoFjListInsert.size() > 0) {
+                            // 新增反担保附件数据
+                            SpringUtils.getBean(GuaranteeInfoFjMapper.class).batchGuaranteeInfoFj(guaranteeInfoFjListInsert);
+                        }
+                        List<GuaranteeInfoFj> guaranteeInfoFjListUpdate = guaranteeInfoFjList.stream().filter(e -> ObjectUtils.isNotEmpty(e.getGuaranteeInfoFjId())).collect(Collectors.toList());
+                        if (guaranteeInfoFjListUpdate.size() > 0) {
+                            for (GuaranteeInfoFj guaranteeInfoFj : guaranteeInfoFjListUpdate) {
+                                //更新反担保附件信息
+                                SpringUtils.getBean(GuaranteeInfoFjMapper.class).updateGuaranteeInfoFj(guaranteeInfoFj);
+                            }
+                        }
+                    }
+                }
+                //插入附件数据库数据生成的pdf
+                if (list.size() > 0){
+                    SpringUtils.getBean(IGuaranteeInfoFjService.class).batchGuaranteeInfoFj(list);
+                }
+                redisCache.deleteObject(key);
+            }
+        };
+    }
+
+    /**
+     * @param imagePaths            图片地址集合
+     * @param loanApplicationNumber 申请编号
+     * @param originalFilename      pdf文件名称
+     * @param type                  文件类型
+     */
+    public static List<GuaranteeInfoFj> createPdfFromImagesGuaranteeInfoFj( List<GuaranteeInfoFj> list ,List<GuaranteeInfoFj> guaranteeInfoFjInsert, List<String> imagePaths, String loanApplicationNumber, String originalFilename, String type, Long loanApplicationId, Long guaranteeInfoId) {
+        // 上传文件路径 = 根+申请编号
+        String filePath = StringUtils.format("{}/{}/{}.{}", RuoYiConfig.getUploadPath(), loanApplicationNumber,
+                FilenameUtils.getBaseName(originalFilename), "pdf");
+        //pdf保存位置
+        File outPutPdf = new File(filePath);
+        try {
+            FileUploadUtils.createPdfFromImages(imagePaths, outPutPdf);
+            //往附件信息中插入对应PDF数据
+            GuaranteeInfoFj guaranteeInfoFj = new GuaranteeInfoFj();
+            guaranteeInfoFj.setLoanApplicationId(loanApplicationId);
+            guaranteeInfoFj.setLoanApplicationNumber(loanApplicationNumber);
+            guaranteeInfoFj.setGuaranteeInfoId(guaranteeInfoId);
+            guaranteeInfoFj.setName(originalFilename + ".pdf");
+            guaranteeInfoFj.setUrl(StringUtils.format("{}/{}/{}.{}", "/profile/upload", loanApplicationNumber,
+                    FilenameUtils.getBaseName(originalFilename), "pdf"));
+            guaranteeInfoFj.setType(type);
+            //给前端判断是否是系统生成的pdf
+            guaranteeInfoFj.setRemark(ONE);
+            list.add(guaranteeInfoFj);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return list;
+    }
 }
+

+ 2503 - 0
ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/LoanApplicationServiceImpl.java

@@ -0,0 +1,2503 @@
+package com.ruoyi.framework.web.service;
+
+
+import com.alibaba.fastjson2.JSONObject;
+import com.deepoove.poi.data.PictureRenderData;
+import com.deepoove.poi.data.Pictures;
+import com.itextpdf.text.DocumentException;
+import com.ruoyi.common.config.RuoYiConfig;
+import com.ruoyi.common.constant.Constants;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.domain.entity.SysRole;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.core.redis.RedisCache;
+import com.ruoyi.common.enums.FjType;
+import com.ruoyi.common.utils.*;
+import com.ruoyi.common.utils.jPush.JPushToolUtil;
+import com.ruoyi.common.utils.poi.ExcelFillUtils;
+import com.ruoyi.common.utils.poi.WordUtil;
+import com.ruoyi.common.utils.uuid.Seq;
+import com.ruoyi.common.utils.uuid.IdUtils;
+import com.ruoyi.framework.manager.AsyncManager;
+import com.ruoyi.framework.manager.factory.AsyncFactory;
+import com.ruoyi.system.domain.SysUserRole;
+import com.ruoyi.system.domain.conference.SysUserConference;
+import com.ruoyi.system.domain.enterprise.SysUserEnterprise;
+import com.ruoyi.system.domain.guarantee.GuaranteeInfo;
+import com.ruoyi.system.domain.guarantee.GuaranteeInfoFj;
+import com.ruoyi.system.domain.loan.LoanApplication;
+import com.ruoyi.system.domain.loan.LoanApplicationFj;
+import com.ruoyi.system.domain.loan.LoanSchedule;
+import com.ruoyi.system.domain.loan.ShareholderFj;
+import com.ruoyi.system.domain.remind.WaitRemind;
+import com.ruoyi.system.domain.review.ReviewComments;
+import com.ruoyi.system.mapper.*;
+import com.ruoyi.system.service.ISysUserService;
+import com.ruoyi.system.service.loan.ILoanApplicationService;
+import org.apache.commons.lang3.ObjectUtils;
+import org.apache.poi.hwpf.HWPFDocument;
+import org.apache.poi.hwpf.usermodel.Range;
+import org.apache.poi.xwpf.extractor.XWPFWordExtractor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.io.*;
+import java.util.*;
+import java.io.File;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+
+import java.io.FileInputStream;
+import java.io.IOException;
+
+import org.apache.poi.xwpf.usermodel.XWPFDocument;
+import org.apache.poi.xwpf.usermodel.XWPFParagraph;
+
+import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.text.PDFTextStripper;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+
+
+import static com.ruoyi.common.constant.CommonConstants.*;
+
+import javax.annotation.Resource;
+
+/**
+ * 贷款申请主Service业务层处理
+ *
+ * @author boman
+ * @date 2024-04-24
+ */
+@Service
+public class LoanApplicationServiceImpl implements ILoanApplicationService {
+    @Autowired
+    private LoanApplicationMapper loanApplicationMapper;
+    @Autowired
+    private LoanApplicationFjMapper loanApplicationFjMapper;
+    @Autowired
+    private ShareholderFjMapper shareholderFjMapper;
+    @Autowired
+    private LoanScheduleMapper loanScheduleMapper;
+    @Autowired
+    private SysUserEnterpriseMapper sysUserEnterpriseMapper;
+    @Autowired
+    private SysUserConferenceMapper sysUserConferenceMapper;
+    @Autowired
+    private ReviewCommentsMapper reviewCommentsMapper;
+    @Resource
+    private WaitRemindMapper waitRemindMapper;
+    @Resource
+    private SysDictDataMapper dictDataMapper;
+    @Resource
+    private GuaranteeInfoMapper guaranteeInfoMapper;
+    @Resource
+    private GuaranteeInfoFjMapper guaranteeInfoFjMapper;
+
+    @Autowired
+    private RedisCache redisCache;
+    @Resource
+    private SysUserRoleMapper sysUserRoleMapper;
+    @Autowired
+    private ISysUserService sysUserService;
+
+
+    /**
+     * 查询贷款申请主
+     *
+     * @param loanApplicationId 贷款申请主主键
+     * @return 贷款申请主
+     */
+    @Override
+    public AjaxResult selectLoanApplicationByLoanApplicationId(Long loanApplicationId) {
+
+        LoanApplication loanApplication = loanApplicationMapper.selectLoanApplicationByLoanApplicationId(loanApplicationId);
+        if (loanApplication != null) {
+            String loanApplicationNumber = loanApplication.getLoanApplicationNumber();
+            //判断自定义锁,必须全部释放,才能修改
+            String keyA = "lock:A:" + loanApplicationNumber;
+            String keyB = "lock:B:" + loanApplicationNumber;
+            String keyC = "lock:C:" + loanApplicationNumber;
+            Object cacheObjectA = redisCache.getCacheObject(keyA);
+            Object cacheObjectB = redisCache.getCacheObject(keyB);
+            Object cacheObjectC = redisCache.getCacheObject(keyC);
+            if (ObjectUtils.isNotEmpty(cacheObjectA) || ObjectUtils.isNotEmpty(cacheObjectB) || ObjectUtils.isNotEmpty(cacheObjectC)) {
+                return AjaxResult.error("稍后重试,文件正在生成");
+            }
+        }
+
+        //查询企业信息
+        if (ObjectUtils.isNotEmpty(loanApplication.getEnterpriseId())) {
+            SysUserEnterprise sysUserEnterprise = sysUserEnterpriseMapper.selectSysUserEnterpriseByEnterpriseId(loanApplication.getEnterpriseId());
+            loanApplication.setSysUserEnterprise(sysUserEnterprise);
+        }
+
+        //查询相关附件
+        List<LoanApplicationFj> loanApplicationFjs = loanApplicationFjMapper.selectLoanApplicationFjByLoanApplicationId(loanApplicationId);
+        if (loanApplicationFjs != null && loanApplicationFjs.size() > 0) {
+            //所有附件不分类
+            loanApplication.setLoanApplicationFjList(loanApplicationFjs);
+            //进行大类区分
+            Map<String, List<LoanApplicationFj>> bigTypeFj = loanApplicationFjs.stream().collect(Collectors.groupingBy(LoanApplicationFj::getBigType));
+            List<LoanApplicationFj> loanApplicationFjsA = bigTypeFj.get(A);
+            if (loanApplicationFjsA != null && loanApplicationFjsA.size() > 0) {
+                loanApplication.setBasicFj(loanApplicationFjsA.stream().collect(Collectors.groupingBy(LoanApplicationFj::getType)));
+            }
+            List<LoanApplicationFj> loanApplicationFjsB = bigTypeFj.get(B);
+            if (loanApplicationFjsB != null && loanApplicationFjsB.size() > 0) {
+                loanApplication.setDeclareFj(loanApplicationFjsB.stream().collect(Collectors.groupingBy(LoanApplicationFj::getType)));
+            }
+            List<LoanApplicationFj> loanApplicationFjsC = bigTypeFj.get(C);
+            if (loanApplicationFjsC != null && loanApplicationFjsC.size() > 0) {
+                loanApplication.setFileFj(loanApplicationFjsC.stream().collect(Collectors.groupingBy(LoanApplicationFj::getType)));
+            }
+            List<LoanApplicationFj> loanApplicationFjsD = bigTypeFj.get(D);
+            if (loanApplicationFjsD != null && loanApplicationFjsD.size() > 0) {
+                loanApplication.setOtherFj(loanApplicationFjsD.stream().collect(Collectors.groupingBy(LoanApplicationFj::getType)));
+            }
+            List<LoanApplicationFj> loanApplicationFjsF = bigTypeFj.get(F);
+            if (loanApplicationFjsF != null && loanApplicationFjsF.size() > 0) {
+                loanApplication.setBackFj(loanApplicationFjsF.stream().collect(Collectors.groupingBy(LoanApplicationFj::getType)));
+            }
+        }
+        List<ShareholderFj> shareholderFjs = shareholderFjMapper.selectShareholderFjLoanApplicationId(loanApplicationId);
+        if (shareholderFjs != null && shareholderFjs.size() > 0) {
+            loanApplication.setShareholderFjList(shareholderFjs);
+        }
+        //会议状态
+        loanApplication.setVotingResult(FOR);
+        if (redisCache.getCacheObject(loanApplication.getLoanApplicationNumber() + "tp") != null) {
+            loanApplication.setVotingResult(redisCache.getCacheObject(loanApplication.getLoanApplicationNumber() + "tp"));
+        }
+        //查询反担保人信息
+        List<GuaranteeInfo> guaranteeInfos = guaranteeInfoMapper.selectGuaranteeInfoListByLoanApplicationId(loanApplicationId);
+        //查询对应的附件
+        if (guaranteeInfos != null && guaranteeInfos.size() > 0) {
+            for (GuaranteeInfo guaranteeInfo : guaranteeInfos) {
+                GuaranteeInfoFj guaranteeInfoFj = new GuaranteeInfoFj();
+                guaranteeInfoFj.setLoanApplicationId(loanApplicationId);
+                guaranteeInfoFj.setGuaranteeInfoId(guaranteeInfo.getGuaranteeInfoId());
+                List<GuaranteeInfoFj> guaranteeInfoFjs = guaranteeInfoFjMapper.selectGuaranteeInfoFjList(guaranteeInfoFj);
+                guaranteeInfo.setGuaranteeInfoFjList(guaranteeInfoFjs);
+            }
+        }
+        loanApplication.setGuaranteeInfoList(guaranteeInfos);
+        return AjaxResult.success(loanApplication);
+    }
+
+    /**
+     * 查询贷款申请主列表
+     *
+     * @param loanApplication 贷款申请主
+     * @return 贷款申请主
+     */
+    @Override
+    public List<LoanApplication> selectLoanApplicationList(LoanApplication loanApplication) {
+/*        //判断是否是admin或者管理员manager
+        List<SysRole> roles = SecurityUtils.getLoginUser().getUser().getRoles();
+        String roleKey = "admin,manager,auditing_risk";*/
+        List<LoanApplication> loanApplications = new ArrayList<>();
+/*        for (SysRole role : roles) {
+            if (roleKey.contains(role.getRoleKey())) {
+                loanApplications = loanApplicationMapper.selectLoanApplicationList(loanApplication);
+                return loanApplications;
+            }
+        }
+        loanApplication.setUserId(SecurityUtils.getUserId());*/
+        loanApplications = loanApplicationMapper.selectLoanApplicationList(loanApplication);
+        return loanApplications;
+    }
+
+    /**
+     * 查询需要保后的数据
+     *
+     * @param loanApplication
+     * @return
+     */
+    @Override
+    public List<LoanApplication> selectLoanAfterList(LoanApplication loanApplication) {
+        loanApplication.setActuallyTime(DateUtils.getNowDate());
+        List<LoanApplication> loanApplications = loanApplicationMapper.selectLoanAfterList(loanApplication);
+        return loanApplications;
+    }
+
+    @Override
+    public List<LoanApplication> conferenceList(LoanApplication loanApplication) {
+        //查询人员id
+        SysUser user = SecurityUtils.getLoginUser().getUser();
+        //判断当前角色是否是管理员和admin,董事长
+        List<SysRole> roles = user.getRoles();
+        Boolean bl = false;
+        for (SysRole role : roles) {
+            if (role.getRoleKey().equals("admin") || role.getRoleKey().equals("manager") || role.getRoleKey().equals("sensible")) {
+                bl = true;
+                break;
+            }
+        }
+        if (!bl) {
+            loanApplication.setUserId(user.getUserId());
+        }
+        List<LoanApplication> loanApplications = new ArrayList<>();
+        if ("druid".equals(RuoYiConfig.getIsYml())) {
+            loanApplications = loanApplicationMapper.conferenceList(loanApplication);
+        } else {
+            loanApplications = loanApplicationMapper.conferenceProdList(loanApplication);
+        }
+
+
+        for (LoanApplication application : loanApplications) {
+            application.setVotingResult(FOR);
+            if (redisCache.getCacheObject(application.getLoanApplicationNumber() + "tp") != null) {
+                application.setVotingResult(redisCache.getCacheObject(application.getLoanApplicationNumber() + "tp"));
+            }
+        }
+        return loanApplications;
+    }
+
+    /**
+     * 文件管理
+     *
+     * @param loanApplication
+     * @return
+     */
+    @Override
+    public List<LoanApplication> listOss(LoanApplication loanApplication) {
+        loanApplication.setLoanSchedule(TEN);
+        loanApplication.setLoanApplicationType(FOR);
+        List<LoanApplication> loanApplications = loanApplicationMapper.selectLoanApplicationList(loanApplication);
+        if (loanApplications != null && loanApplications.size() > 0) {
+            for (LoanApplication application : loanApplications) {
+                //去查询压缩包
+                LoanApplicationFj loanApplicationFj = new LoanApplicationFj();
+                loanApplicationFj.setLoanApplicationId(application.getLoanApplicationId());
+                loanApplicationFj.setBigType("e");
+                List<LoanApplicationFj> loanApplicationFjList = loanApplicationFjMapper.selectLoanApplicationFjList(loanApplicationFj);
+                application.setLoanApplicationFjList(loanApplicationFjList);
+            }
+        }
+        return loanApplications;
+    }
+
+    /**
+     * 新增贷款申请主
+     *
+     * @param loanApplication 贷款申请主
+     * @return 结果
+     */
+    @Override
+    @Transactional
+    public int insertLoanApplication(LoanApplication loanApplication) {
+        if (loanApplicationMapper.selectLoanApplicationList(loanApplication).size() > 0) {
+            return 0;
+        }
+        //先去查询贷款编码是否已经存在
+        //设置为audit_schedule=1 audit_type=1
+        loanApplication.setAuditSchedule(ONE);
+        loanApplication.setAuditType(ONE);
+        //设置申请人用户ID
+        loanApplication.setUserId(SecurityUtils.getUserId());
+        loanApplication.setApplicationTime(DateUtils.getNowDate());
+        //贷款申请进度进入业务审核/分配
+        loanApplication.setLoanSchedule(TWO);
+        loanApplication.setLoanApplicationType(TWO);
+        loanApplication.setUserId(SecurityUtils.getUserId());
+        int i = loanApplicationMapper.insertLoanApplication(loanApplication);
+        List<LoanApplicationFj> loanApplicationFjList = loanApplication.getLoanApplicationFjList();
+        if (loanApplicationFjList != null && loanApplicationFjList.size() > 0) {
+            for (LoanApplicationFj loanApplicationFj : loanApplicationFjList) {
+                loanApplicationFj.setLoanApplicationId(loanApplication.getLoanApplicationId());
+                loanApplicationFj.setLoanApplicationNumber(loanApplication.getLoanApplicationNumber());
+            }
+            AsyncManager.me().execute(AsyncFactory.createPdfFromImages(loanApplicationFjList, loanApplication.getLoanApplicationNumber()));
+            loanApplicationFjMapper.batchLoanApplicationFj(loanApplicationFjList);
+        }
+        List<ShareholderFj> shareholderFjList = loanApplication.getShareholderFjList();
+        if (shareholderFjList != null && shareholderFjList.size() > 0) {
+            for (ShareholderFj shareholderFj : shareholderFjList) {
+                shareholderFj.setLoanApplicationId(loanApplication.getLoanApplicationId());
+                shareholderFj.setLoanApplicationNumber(loanApplication.getLoanApplicationNumber());
+            }
+            AsyncManager.me().execute(AsyncFactory.createPdfFromImagesShareholder(shareholderFjList, loanApplication.getLoanApplicationNumber(), loanApplication.getLoanApplicationId()));
+        }
+        //反担保基础信息和附件新增
+        List<GuaranteeInfo> guaranteeInfoList = loanApplication.getGuaranteeInfoList();
+        if (guaranteeInfoList != null && guaranteeInfoList.size() > 0) {
+            for (GuaranteeInfo guaranteeInfo : guaranteeInfoList) {
+                guaranteeInfo.setLoanApplicationId(loanApplication.getLoanApplicationId());
+                guaranteeInfo.setLoanApplicationNumber(loanApplication.getLoanApplicationNumber());
+            }
+            //先新增反担保基础信息,再去异步插入附件
+            guaranteeInfoMapper.batchGuaranteeInfo(guaranteeInfoList);
+            //异步插入附件
+            AsyncManager.me().execute(AsyncFactory.createPdfFromImagesGuaranteeInfo(guaranteeInfoList, loanApplication.getLoanApplicationNumber()));
+        }
+        //往业务进度表 loan_schedule 插入数据
+        LoanSchedule loanSchedule = new LoanSchedule();
+        loanSchedule.setLoanApplicationId(loanApplication.getLoanApplicationId());
+        loanSchedule.setLoanApplicationNumber(loanApplication.getLoanApplicationNumber());
+        loanSchedule.setLoanScheduleName(loanApplication.getLoanScheduleName());
+        loanSchedule.setLoanScheduleValue(loanApplication.getLoanSchedule());
+        loanSchedule.setLoanScheduleScore(0L);
+        loanSchedule.setLoanScheduleTime(DateUtils.getNowDate());
+        loanScheduleMapper.insertLoanSchedule(loanSchedule);
+        return i;
+    }
+
+
+    /**
+     * 修改贷款申请主
+     *
+     * @param loanApplication 贷款申请主
+     * @return 结果
+     */
+    @Override
+    @Transactional
+    public AjaxResult updateLoanApplication(LoanApplication loanApplication) {
+
+        loanApplication.setUpdateTime(DateUtils.getNowDate());
+        loanApplication.setLoanApplicationType(TWO);
+        loanApplication.setApplicationTime(DateUtils.getNowDate());
+        Long loanApplicationId = loanApplication.getLoanApplicationId();
+        //判断如果是审核进度 =1 贷款申请进度 =2业务审核/分配 审核状态 = 3(未通过的时候)把审核状态改为1 待审核
+        if (loanApplication.getLoanSchedule().equals(TWO) && loanApplication.getAuditSchedule().equals(ONE) && loanApplication.getAuditType().equals(THR)) {
+            loanApplication.setAuditType(ONE);
+        }
+
+        //需要删除的id集合
+        Long[] loanApplicationFjIdList = loanApplication.getLoanApplicationFjIdList();
+        Long[] shareholderFjIdList = loanApplication.getShareholderFjIdList();
+        Long[] guaranteeInfoIdList = loanApplication.getGuaranteeInfoIdList();
+        //反担保附件删除id集合
+        Long[] guaranteeInfoFjIdList = loanApplication.getGuaranteeInfoFjIdList();
+        List<LoanApplicationFj> loanApplicationFjList = loanApplication.getLoanApplicationFjList();
+        if (loanApplicationFjList != null && loanApplicationFjList.size() > 0) {
+            //判断有附件id的附件进行修改,没有的进行新增
+            List<LoanApplicationFj> loanApplicationFjsInsert = loanApplicationFjList.stream().filter(e -> ObjectUtils.isEmpty(e.getFjId())).collect(Collectors.toList());
+            if (loanApplicationFjsInsert.size() > 0) {
+                for (LoanApplicationFj loanApplicationFj : loanApplicationFjsInsert) {
+                    loanApplicationFj.setLoanApplicationId(loanApplicationId);
+                    loanApplicationFj.setLoanApplicationNumber(loanApplication.getLoanApplicationNumber());
+                }
+                //新增新增的附件
+                loanApplicationFjMapper.batchLoanApplicationFj(loanApplicationFjsInsert);
+            }
+            if (loanApplicationFjsInsert.size() > 0 || (loanApplicationFjIdList != null && loanApplicationFjIdList.length > 0)) {
+                AsyncManager.me().execute(AsyncFactory.createPdfFromImages(loanApplicationFjList, loanApplication.getLoanApplicationNumber()));
+            }
+        }
+        //需要删除附件表数据
+        if (loanApplicationFjIdList != null && loanApplicationFjIdList.length > 0) {
+            loanApplicationFjMapper.deleteLoanApplicationFjByFjIds(loanApplicationFjIdList);
+        }
+
+        //shareholderFjMapper.deleteShareholderFjByLoanApplicationId(loanApplicationId);
+        List<ShareholderFj> shareholderFjList = loanApplication.getShareholderFjList();
+        if (shareholderFjList != null && shareholderFjList.size() > 0) {
+            AsyncManager.me().execute(AsyncFactory.createPdfFromImagesShareholder(shareholderFjList, loanApplication.getLoanApplicationNumber(), loanApplication.getLoanApplicationId()));
+            // shareholderFjMapper.batchShareholderFj(shareholderFjList);
+        }
+        //需要删除股东附件表数据
+        if (shareholderFjIdList != null && shareholderFjIdList.length > 0) {
+            shareholderFjMapper.deleteShareholderFjByShareholderFjIds(shareholderFjIdList);
+        }
+
+        //反担保基础信息和附件新增
+        List<GuaranteeInfo> guaranteeInfoList = loanApplication.getGuaranteeInfoList();
+        if (guaranteeInfoList != null && guaranteeInfoList.size() > 0) {
+            for (GuaranteeInfo guaranteeInfo : guaranteeInfoList) {
+                guaranteeInfo.setLoanApplicationId(loanApplication.getLoanApplicationId());
+                guaranteeInfo.setLoanApplicationNumber(loanApplication.getLoanApplicationNumber());
+            }
+            //判断有反担保信息表id的进行修改,没有的进行新增
+            List<GuaranteeInfo> guaranteeInfosInsert = guaranteeInfoList.stream().filter(e -> ObjectUtils.isEmpty(e.getGuaranteeInfoId())).collect(Collectors.toList());
+            List<GuaranteeInfo> guaranteeInfosUpdate = guaranteeInfoList.stream().filter(e -> ObjectUtils.isNotEmpty(e.getGuaranteeInfoId())).collect(Collectors.toList());
+            if (guaranteeInfosInsert.size() > 0) {
+                guaranteeInfoMapper.batchGuaranteeInfo(guaranteeInfosInsert);
+            }
+            if (guaranteeInfosUpdate.size() > 0) {
+                for (GuaranteeInfo guaranteeInfo : guaranteeInfosUpdate) {
+                    guaranteeInfoMapper.updateGuaranteeInfo(guaranteeInfo);
+                }
+            }
+            //先新增反担保基础信息,再去异步插入附件
+            //异步插入附件
+            AsyncManager.me().execute(AsyncFactory.createPdfFromImagesGuaranteeInfo(guaranteeInfoList, loanApplication.getLoanApplicationNumber()));
+        }
+
+        if (guaranteeInfoFjIdList != null && guaranteeInfoFjIdList.length > 0) {
+            guaranteeInfoFjMapper.deleteGuaranteeInfoFjByGuaranteeInfoFjIds(guaranteeInfoFjIdList);
+        }
+        if (guaranteeInfoIdList != null && guaranteeInfoIdList.length > 0) {
+            guaranteeInfoMapper.deleteGuaranteeInfoByGuaranteeInfoIds(guaranteeInfoIdList);
+            guaranteeInfoFjMapper.deleteGuaranteeInfoFjByGuaranteeInfoIds(guaranteeInfoIdList);
+        }
+        int rows = loanApplicationMapper.updateLoanApplication(loanApplication);
+        return rows > 0 ? AjaxResult.success() : AjaxResult.error();
+    }
+
+    /**
+     * 修改贷款申请主新只新增实际放款金额(万元)实际放款时间
+     */
+    @Override
+    public AjaxResult updateLoanApplicationActually(LoanApplication loanApplication) {
+        int rows = loanApplicationMapper.updateLoanApplication(loanApplication);
+        return rows > 0 ? AjaxResult.success() : AjaxResult.error();
+    }
+
+    /**
+     * 暂存
+     *
+     * @param loanApplication 贷款申请主
+     * @return
+     */
+    @Override
+    @Transactional
+    public AjaxResult temporary(LoanApplication loanApplication) {
+        loanApplication.setLoanApplicationType(ONE);
+        Long loanApplicationId = loanApplication.getLoanApplicationId();
+        //走修改
+        if (loanApplicationId != null) {
+            //需要删除的id集合
+            Long[] loanApplicationFjIdList = loanApplication.getLoanApplicationFjIdList();
+            Long[] shareholderFjIdList = loanApplication.getShareholderFjIdList();
+            Long[] guaranteeInfoIdList = loanApplication.getGuaranteeInfoIdList();
+            //反担保附件删除id集合
+            Long[] guaranteeInfoFjIdList = loanApplication.getGuaranteeInfoFjIdList();
+            List<LoanApplicationFj> loanApplicationFjList = loanApplication.getLoanApplicationFjList();
+            if (loanApplicationFjList != null && loanApplicationFjList.size() > 0) {
+                //判断有附件id的附件进行修改,没有的进行新增
+                List<LoanApplicationFj> loanApplicationFjsInsert = loanApplicationFjList.stream().filter(e -> ObjectUtils.isEmpty(e.getFjId())).collect(Collectors.toList());
+                if (loanApplicationFjsInsert.size() > 0) {
+                    for (LoanApplicationFj loanApplicationFj : loanApplicationFjsInsert) {
+                        loanApplicationFj.setLoanApplicationId(loanApplicationId);
+                        loanApplicationFj.setLoanApplicationNumber(loanApplication.getLoanApplicationNumber());
+                    }
+                    //新增新增的附件
+                    loanApplicationFjMapper.batchLoanApplicationFj(loanApplicationFjsInsert);
+                }
+                if (loanApplicationFjsInsert.size() > 0 || (loanApplicationFjIdList != null && loanApplicationFjIdList.length > 0)) {
+                    AsyncManager.me().execute(AsyncFactory.createPdfFromImages(loanApplicationFjList, loanApplication.getLoanApplicationNumber()));
+                }
+            }
+            //需要删除附件表数据
+            if (loanApplicationFjIdList != null && loanApplicationFjIdList.length > 0) {
+                loanApplicationFjMapper.deleteLoanApplicationFjByFjIds(loanApplicationFjIdList);
+            }
+
+            List<ShareholderFj> shareholderFjList = loanApplication.getShareholderFjList();
+            if (shareholderFjList != null && shareholderFjList.size() > 0) {
+                for (ShareholderFj shareholderFj : shareholderFjList) {
+                    shareholderFj.setLoanApplicationId(loanApplicationId);
+                    shareholderFj.setLoanApplicationNumber(loanApplication.getLoanApplicationNumber());
+                }
+                AsyncManager.me().execute(AsyncFactory.createPdfFromImagesShareholder(shareholderFjList, loanApplication.getLoanApplicationNumber(), loanApplication.getLoanApplicationId()));
+            }
+            //需要删除股东附件表数据
+            if (shareholderFjIdList != null && shareholderFjIdList.length > 0) {
+                shareholderFjMapper.deleteShareholderFjByShareholderFjIds(shareholderFjIdList);
+            }
+
+            //反担保基础信息和附件新增
+            List<GuaranteeInfo> guaranteeInfoList = loanApplication.getGuaranteeInfoList();
+            if (guaranteeInfoList != null && guaranteeInfoList.size() > 0) {
+                for (GuaranteeInfo guaranteeInfo : guaranteeInfoList) {
+                    guaranteeInfo.setLoanApplicationId(loanApplication.getLoanApplicationId());
+                    guaranteeInfo.setLoanApplicationNumber(loanApplication.getLoanApplicationNumber());
+                }
+                //判断有反担保信息表id的进行修改,没有的进行新增
+                List<GuaranteeInfo> guaranteeInfosInsert = guaranteeInfoList.stream().filter(e -> ObjectUtils.isEmpty(e.getGuaranteeInfoId())).collect(Collectors.toList());
+                List<GuaranteeInfo> guaranteeInfosUpdate = guaranteeInfoList.stream().filter(e -> ObjectUtils.isNotEmpty(e.getGuaranteeInfoId())).collect(Collectors.toList());
+                if (guaranteeInfosInsert.size() > 0) {
+                    guaranteeInfoMapper.batchGuaranteeInfo(guaranteeInfosInsert);
+                }
+                if (guaranteeInfosUpdate.size() > 0) {
+                    for (GuaranteeInfo guaranteeInfo : guaranteeInfosUpdate) {
+                        guaranteeInfoMapper.updateGuaranteeInfo(guaranteeInfo);
+                    }
+                }
+                //先新增反担保基础信息,再去异步插入附件
+                //异步插入附件
+                AsyncManager.me().execute(AsyncFactory.createPdfFromImagesGuaranteeInfo(guaranteeInfoList, loanApplication.getLoanApplicationNumber()));
+            }
+            if (guaranteeInfoFjIdList != null && guaranteeInfoFjIdList.length > 0) {
+                guaranteeInfoFjMapper.deleteGuaranteeInfoFjByGuaranteeInfoFjIds(guaranteeInfoFjIdList);
+            }
+            if (guaranteeInfoIdList != null && guaranteeInfoIdList.length > 0) {
+                guaranteeInfoMapper.deleteGuaranteeInfoByGuaranteeInfoIds(guaranteeInfoIdList);
+                guaranteeInfoFjMapper.deleteGuaranteeInfoFjByGuaranteeInfoIds(guaranteeInfoIdList);
+            }
+
+            int rows = loanApplicationMapper.updateLoanApplication(loanApplication);
+            return rows > 0 ? AjaxResult.success() : AjaxResult.error();
+        }
+        LoanApplication loanApplicationNew = new LoanApplication();
+        loanApplicationNew.setLoanApplicationNumber(loanApplication.getLoanApplicationNumber());
+        //暂存先去判断项目编号是否重复
+        List<LoanApplication> loanApplications = loanApplicationMapper.selectLoanApplicationList(loanApplicationNew);
+        if (loanApplications != null && loanApplications.size() > 0) {
+            return AjaxResult.error("请勿重复暂存");
+        }
+        //设置为audit_schedule=1 audit_type=1
+        loanApplication.setAuditSchedule(ONE);
+        loanApplication.setAuditType(ONE);
+        //设置申请人用户ID
+        loanApplication.setUserId(SecurityUtils.getUserId());
+        //贷款申请进度进入业务审核/分配
+        loanApplication.setLoanSchedule(TWO);
+        int rows = loanApplicationMapper.insertLoanApplication(loanApplication);
+        loanApplicationId = loanApplication.getLoanApplicationId();
+        List<LoanApplicationFj> loanApplicationFjList = loanApplication.getLoanApplicationFjList();
+        if (loanApplicationFjList != null && loanApplicationFjList.size() > 0) {
+            for (LoanApplicationFj loanApplicationFj : loanApplicationFjList) {
+                loanApplicationFj.setLoanApplicationId(loanApplicationId);
+                loanApplicationFj.setLoanApplicationNumber(loanApplication.getLoanApplicationNumber());
+            }
+            AsyncManager.me().execute(AsyncFactory.createPdfFromImages(loanApplicationFjList, loanApplication.getLoanApplicationNumber()));
+            loanApplicationFjMapper.batchLoanApplicationFj(loanApplicationFjList);
+        }
+        List<ShareholderFj> shareholderFjList = loanApplication.getShareholderFjList();
+        if (shareholderFjList != null && shareholderFjList.size() > 0) {
+            for (ShareholderFj shareholderFj : shareholderFjList) {
+                shareholderFj.setLoanApplicationId(loanApplicationId);
+                shareholderFj.setLoanApplicationNumber(loanApplication.getLoanApplicationNumber());
+            }
+            AsyncManager.me().execute(AsyncFactory.createPdfFromImagesShareholder(shareholderFjList, loanApplication.getLoanApplicationNumber(), loanApplication.getLoanApplicationId()));
+            //shareholderFjMapper.batchShareholderFj(shareholderFjList);
+        }
+
+        //反担保基础信息和附件新增
+        List<GuaranteeInfo> guaranteeInfoList = loanApplication.getGuaranteeInfoList();
+        if (guaranteeInfoList != null && guaranteeInfoList.size() > 0) {
+            for (GuaranteeInfo guaranteeInfo : guaranteeInfoList) {
+                guaranteeInfo.setLoanApplicationId(loanApplication.getLoanApplicationId());
+                guaranteeInfo.setLoanApplicationNumber(loanApplication.getLoanApplicationNumber());
+            }
+            //判断有反担保信息表id的进行修改,没有的进行新增
+            List<GuaranteeInfo> guaranteeInfosInsert = guaranteeInfoList.stream().filter(e -> ObjectUtils.isEmpty(e.getGuaranteeInfoId())).collect(Collectors.toList());
+            List<GuaranteeInfo> guaranteeInfosUpdate = guaranteeInfoList.stream().filter(e -> ObjectUtils.isNotEmpty(e.getGuaranteeInfoId())).collect(Collectors.toList());
+            if (guaranteeInfosInsert.size() > 0) {
+                guaranteeInfoMapper.batchGuaranteeInfo(guaranteeInfosInsert);
+            }
+            if (guaranteeInfosUpdate.size() > 0) {
+                for (GuaranteeInfo guaranteeInfo : guaranteeInfosUpdate) {
+                    guaranteeInfoMapper.updateGuaranteeInfo(guaranteeInfo);
+                }
+            }
+            //先新增反担保基础信息,再去异步插入附件
+            //异步插入附件
+            AsyncManager.me().execute(AsyncFactory.createPdfFromImagesGuaranteeInfo(guaranteeInfoList, loanApplication.getLoanApplicationNumber()));
+        }
+        return rows > 0 ? AjaxResult.success() : AjaxResult.error();
+    }
+
+    /**
+     * 批量删除贷款申请主
+     *
+     * @param loanApplicationIds 需要删除的贷款申请主主键
+     * @return 结果
+     */
+    @Override
+    public int deleteLoanApplicationByLoanApplicationIds(Long[] loanApplicationIds) {
+        return loanApplicationMapper.deleteLoanApplicationByLoanApplicationIds(loanApplicationIds);
+    }
+
+    /**
+     * 删除贷款申请主信息
+     *
+     * @param loanApplicationId 贷款申请主主键
+     * @return 结果
+     */
+    @Override
+    public int deleteLoanApplicationByLoanApplicationId(Long loanApplicationId) {
+        return loanApplicationMapper.deleteLoanApplicationByLoanApplicationId(loanApplicationId);
+    }
+
+    /**
+     * 审核
+     *
+     * @param reviewComments
+     * @return
+     */
+    @Override
+    @Transactional
+    public AjaxResult sh(ReviewComments reviewComments) {
+        reviewComments.setAuditTime(DateUtils.getNowDate());
+        //List<SysUserConference> sysUserConferenceList = reviewComments.getSysUserConferenceList();
+        //审核进度1:业务审核/分配 2:A角色审核 3:B角色审核 4:风险审核 5:初审风险合规 6:尽职调查7:上会评审
+        String auditSchedule = reviewComments.getAuditSchedule();
+        //审核状态 1:待审核 2:已通过 3:未通过 4:申诉
+        String auditType = reviewComments.getAuditType();
+        //校验当前项目进度
+        Long loanApplicationId = reviewComments.getLoanApplicationId();
+        //获取数据库中项目详情
+        LoanApplication loanApplication = loanApplicationMapper.selectLoanApplicationByLoanApplicationId(loanApplicationId);
+        String loanScheduleOld = loanApplication.getLoanSchedule();
+        String auditScheduleOld = loanApplication.getAuditSchedule();
+        String auditTypeOld = loanApplication.getAuditType();
+        String loanApplicationType = loanApplication.getLoanApplicationType();
+        String enterpriseName = loanApplication.getEnterpriseName();
+        //判断是否已归档
+        if (loanApplication.getLoanApplicationType().equals(FOR)) {
+            return AjaxResult.error("当前项目已归档");
+        }
+        //判断是否无需审核
+        if (Integer.parseInt(loanScheduleOld) > 6) {
+            return AjaxResult.error("当前项目无需审核");
+        }
+        if (!Objects.equals(loanApplicationType, TWO)) {
+            return AjaxResult.error("当前贷款申请状态非正常,请检查后重新操作");
+        }
+        if (ObjectUtils.isEmpty(loanApplication)) {
+            return AjaxResult.error("当前贷款申请不存在,请重新刷新");
+        }
+
+        //判断数据库中进度是否小于当前申请进度
+        if (Integer.parseInt(auditSchedule) <= Integer.parseInt(auditScheduleOld) && !Objects.equals(auditTypeOld, ONE)) {
+            return AjaxResult.error("当前进度已审核,请勿重复审核");
+        }
+        List<LoanApplicationFj> fjUrl = reviewComments.getFjUrl();
+        if (fjUrl != null && fjUrl.size() > 0) {
+            StringBuilder type = new StringBuilder();
+            for (LoanApplicationFj loanApplicationFj : fjUrl) {
+                type.append(loanApplicationFj.getType()).append(",");
+            }
+            type.deleteCharAt(type.lastIndexOf(","));
+            loanApplicationFjMapper.deleteLoanApplicationFjByLoanApplicationIdAndType(loanApplicationId, type.toString().split(","));
+            //需要删除当前状态下已存在的附件
+            loanApplicationFjMapper.batchLoanApplicationFj(fjUrl);
+        }
+        //业务审核意见
+        reviewComments.setCreateBy(SecurityUtils.getUsername());
+        reviewCommentsMapper.insertReviewComments(reviewComments);
+        //待办信息集合
+        List<WaitRemind> waitRemindList = new ArrayList<>();
+        //查询审核管理员用户id
+        List<SysUserRole> sysUserRoles = sysUserRoleMapper.selectRoleListNoDataScope();
+        //A角色进度之前审核不通过,给客户回馈不通过问题,之后的进入到申诉状态
+        if (THR.equals(auditType) && ONE.equals(auditSchedule)) {
+            loanApplication.setAuditType(auditType);
+            loanApplication.setAuditSchedule(auditSchedule);
+            loanApplication.setLoanSchedule(TWO);
+            loanApplication.setLoanApplicationType(TWO);
+            //插入不通过原因
+            loanApplication.setRejectionReason(reviewComments.getAuditView());
+            loanApplicationMapper.updateLoanApplication(loanApplication);
+          /*  //给A角色,审核管理员发送待办
+            WaitRemind waitRemind = new WaitRemind();
+            waitRemind.setLoanApplicationId(loanApplicationId);
+            waitRemind.setLoanApplicationNumber(loanApplication.getLoanApplicationNumber());
+            waitRemind.setRemindTitle("您有一条【" + enterpriseName + "】的审核信息进入回收站");
+            waitRemind.setRemindTime(DateUtils.getNowDate());
+            waitRemind.setRemindType(TWO);
+            waitRemind.setReadUserId(loanApplication.getaUserId().toString());
+            waitRemind.setRemindContent(enterpriseName + "有一条贷款申请进入回收站需及时处理");
+            waitRemindList.add(waitRemind);
+            if (sysUserRoles != null && sysUserRoles.size() > 0) {
+                for (SysUserRole sysUserRole : sysUserRoles) {
+                    WaitRemind waitRemindManager = new WaitRemind();
+                    waitRemindManager.setLoanApplicationId(loanApplicationId);
+                    waitRemindManager.setLoanApplicationNumber(loanApplication.getLoanApplicationNumber());
+                    waitRemindManager.setRemindTitle("有一条【" + enterpriseName + "】的审核信息进入回收站");
+                    waitRemindManager.setRemindTime(DateUtils.getNowDate());
+                    waitRemindManager.setRemindType(TWO);
+                    waitRemindManager.setReadUserId(loanApplication.getaUserId().toString());
+                    waitRemindManager.setRemindContent(enterpriseName + "有一条贷款申请进入回收站需及时查看");
+                    //给管理员发送待办提醒
+                    waitRemindManager.setReadUserId(sysUserRole.getUserId().toString());
+                    waitRemindList.add(waitRemindManager);
+                }
+            }
+            waitRemindMapper.batchWaitRemind(waitRemindList);*/
+            return AjaxResult.success();
+            //A角色审核不通过 audit_schedule = 2的时候贷款申请进度处于担保初审状态
+        } else if (THR.equals(auditType) && auditSchedule.equals(TWO)) {
+            loanApplication.setLoanSchedule(THR);
+            loanApplication.setAuditType(FOR);
+            loanApplication.setLoanApplicationType(TWO);
+            loanApplicationMapper.updateLoanApplication(loanApplication);
+            //删除已处理的待办信息
+            WaitRemind waitRemindDelete = new WaitRemind();
+            waitRemindDelete.setLoanApplicationId(loanApplication.getLoanApplicationId());
+            waitRemindDelete.setReadUserId(loanApplication.getaUserId().toString());
+            waitRemindDelete.setRemindType(TWO);
+            waitRemindMapper.deleteWaitRemindByLoanApplicationId(waitRemindDelete);
+            //给A角色,审核管理员发送待办
+            WaitRemind waitRemind = new WaitRemind();
+            waitRemind.setLoanApplicationId(loanApplicationId);
+            waitRemind.setLoanApplicationNumber(loanApplication.getLoanApplicationNumber());
+            waitRemind.setRemindTitle("您有一条【" + enterpriseName + "】的审核信息未通过");
+            waitRemind.setRemindTime(DateUtils.getNowDate());
+            waitRemind.setRemindType(TWO);
+            waitRemind.setReadUserId(loanApplication.getaUserId().toString());
+            waitRemind.setRemindContent(enterpriseName + "有一条贷款申请进入未通过需及时处理");
+            waitRemindList.add(waitRemind);
+            List<Long> userIdList = new ArrayList<>();
+            if (sysUserRoles != null && sysUserRoles.size() > 0) {
+                userIdList = sysUserRoles.stream().map(SysUserRole::getUserId).collect(Collectors.toList());
+                for (SysUserRole sysUserRole : sysUserRoles) {
+                    //删除已处理的待办信息
+                    waitRemindDelete.setLoanApplicationId(loanApplication.getLoanApplicationId());
+                    waitRemindDelete.setReadUserId(sysUserRole.getUserId().toString());
+                    waitRemindDelete.setRemindType(TWO);
+                    waitRemindMapper.deleteWaitRemindByLoanApplicationId(waitRemindDelete);
+
+                    WaitRemind waitRemindManager = new WaitRemind();
+                    waitRemindManager.setLoanApplicationId(loanApplicationId);
+                    waitRemindManager.setLoanApplicationNumber(loanApplication.getLoanApplicationNumber());
+                    waitRemindManager.setRemindTitle("有一条【" + enterpriseName + "】的审核信息未通过");
+                    waitRemindManager.setRemindTime(DateUtils.getNowDate());
+                    waitRemindManager.setRemindType(TWO);
+                    waitRemindManager.setRemindContent(enterpriseName + "有一条贷款申请进入未通过需及时查看");
+                    //给管理员发送待办提醒
+                    waitRemindManager.setReadUserId(sysUserRole.getUserId().toString());
+                    waitRemindList.add(waitRemindManager);
+                }
+            }
+            waitRemindMapper.batchWaitRemind(waitRemindList);
+
+            //发极光推送id
+            //获取所有的userid
+            userIdList.add(loanApplication.getaUserId());
+            List<SysUser> sysUsers = sysUserService.selectUserListByIdList(userIdList);
+            if (sysUsers != null && sysUsers.size() > 0) {
+                String notificationTitle = "消息通知";
+                String msgTitle = "审核信息";
+                String msgContent = enterpriseName + "有一条贷款申请进入未通过需及时处理";
+                String jPushVO = "";
+                List<String> listS = sysUsers.stream().map(SysUser::getJgId).collect(Collectors.toList());
+                listS.removeAll(Collections.singleton(null));
+                if (listS != null && listS.size() > 0) {
+                    String[] registrationId = listS.toArray(new String[listS.size()]);
+                    JPushToolUtil.sendToRegistrationId(notificationTitle, msgTitle, msgContent, jPushVO, registrationId);
+                }
+            }
+
+            return AjaxResult.success();
+            //审核流程结束
+        } else if (THR.equals(auditType) && Integer.parseInt(auditSchedule) > 2) {
+            //进入到A角色申诉状态保留当前项目状态,只把audit_type改为申诉
+            loanApplication.setAuditType(FOR);
+            loanApplicationMapper.updateLoanApplication(loanApplication);
+            //删除已处理的待办信息
+            WaitRemind waitRemindDelete = new WaitRemind();
+            waitRemindDelete.setLoanApplicationId(loanApplication.getLoanApplicationId());
+            waitRemindDelete.setReadUserId(loanApplication.getaUserId().toString());
+            waitRemindDelete.setRemindType(TWO);
+            waitRemindMapper.deleteWaitRemindByLoanApplicationId(waitRemindDelete);
+            //给A角色发送待办提醒
+            WaitRemind waitRemind = new WaitRemind();
+            waitRemind.setLoanApplicationId(loanApplicationId);
+            waitRemind.setLoanApplicationNumber(loanApplication.getLoanApplicationNumber());
+            waitRemind.setRemindTitle("您有一条【" + enterpriseName + "】的审核信息进入申诉状态");
+            waitRemind.setRemindTime(DateUtils.getNowDate());
+            waitRemind.setRemindType(TWO);
+            waitRemind.setReadUserId(loanApplication.getaUserId().toString());
+            waitRemind.setRemindContent(enterpriseName + "有一条贷款申请进入申诉状态需及时处理");
+            waitRemindList.add(waitRemind);
+            List<Long> userIdList = new ArrayList<>();
+            if (sysUserRoles != null && sysUserRoles.size() > 0) {
+                userIdList = sysUserRoles.stream().map(SysUserRole::getUserId).collect(Collectors.toList());
+                for (SysUserRole sysUserRole : sysUserRoles) {
+                    //删除已处理的待办信息
+                    waitRemindDelete.setLoanApplicationId(loanApplication.getLoanApplicationId());
+                    waitRemindDelete.setReadUserId(sysUserRole.getUserId().toString());
+                    waitRemindDelete.setRemindType(TWO);
+                    waitRemindMapper.deleteWaitRemindByLoanApplicationId(waitRemindDelete);
+
+                    WaitRemind waitRemindManager = new WaitRemind();
+                    waitRemindManager.setLoanApplicationId(loanApplicationId);
+                    waitRemindManager.setLoanApplicationNumber(loanApplication.getLoanApplicationNumber());
+                    waitRemindManager.setRemindTitle("有一条【" + enterpriseName + "】的审核信息进入申诉状态");
+                    waitRemindManager.setRemindTime(DateUtils.getNowDate());
+                    waitRemindManager.setRemindType(TWO);
+                    waitRemindManager.setReadUserId(loanApplication.getaUserId().toString());
+                    waitRemindManager.setRemindContent(enterpriseName + "有一条贷款申请进入申诉状态需及时处理");
+                    //给管理员发送待办提醒
+                    waitRemindManager.setReadUserId(sysUserRole.getUserId().toString());
+                    waitRemindList.add(waitRemindManager);
+                }
+            }
+            waitRemindMapper.batchWaitRemind(waitRemindList);
+
+            //发极光推送id
+            //获取所有的userid
+            userIdList.add(loanApplication.getaUserId());
+            List<SysUser> sysUsers = sysUserService.selectUserListByIdList(userIdList);
+            if (sysUsers != null && sysUsers.size() > 0) {
+                String notificationTitle = "消息通知";
+                String msgTitle = "审核信息";
+                String msgContent = enterpriseName + "有一条贷款申请进入申诉状态需及时处理";
+                String jPushVO = "";
+                List<String> listS = sysUsers.stream().map(SysUser::getJgId).collect(Collectors.toList());
+                listS.removeAll(Collections.singleton(null));
+                if (listS != null && listS.size() > 0) {
+                    String[] registrationId = listS.toArray(new String[listS.size()]);
+                    JPushToolUtil.sendToRegistrationId(notificationTitle, msgTitle, msgContent, jPushVO, registrationId);
+                }
+            }
+            return AjaxResult.success();
+        }
+        //通过,进入到下一个步骤
+        if (TWO.equals(auditType)) {
+
+            WaitRemind waitRemindDelete = new WaitRemind();
+            List<Long> userIdList = new ArrayList<>();
+
+            WaitRemind waitRemind = new WaitRemind();
+            waitRemind.setLoanApplicationId(loanApplicationId);
+            waitRemind.setLoanApplicationNumber(loanApplication.getLoanApplicationNumber());
+            waitRemind.setRemindTitle("您有一条【" + enterpriseName + "】的审核信息通过");
+            waitRemind.setRemindTime(DateUtils.getNowDate());
+            waitRemind.setRemindType(TWO);
+            if (auditSchedule.equals(ONE)) {
+                //删除已处理的待办信息
+                waitRemindDelete.setLoanApplicationId(loanApplication.getLoanApplicationId());
+                waitRemindDelete.setReadUserId(loanApplication.getaUserId().toString());
+                waitRemindDelete.setRemindType(TWO);
+                waitRemindMapper.deleteWaitRemindByLoanApplicationId(waitRemindDelete);
+                loanApplication.setLoanSchedule(String.valueOf(Integer.parseInt(loanScheduleOld) + 1));
+                loanApplication.setAuditSchedule(String.valueOf(Integer.parseInt(auditSchedule) + 1));
+                loanApplication.setAuditType(ONE);
+                //设置AB角色id和风险ID
+                loanApplication.setaUserId(reviewComments.getaUserId());
+                loanApplication.setaUserName(reviewComments.getaUserName());
+                loanApplication.setbUserId(reviewComments.getbUserId());
+                loanApplication.setbUserName(reviewComments.getbUserName());
+                loanApplication.setfUserId(reviewComments.getfUserId());
+                loanApplication.setfUserName(reviewComments.getfUserName());
+                //给A角色发送待办提醒
+                waitRemind.setReadUserId(reviewComments.getaUserId().toString());
+                waitRemind.setRemindContent(enterpriseName + "有一条申请贷款信息审核通过");
+                waitRemindList.add(waitRemind);
+                if (sysUserRoles != null && sysUserRoles.size() > 0) {
+                    //极光推送
+                    userIdList = sysUserRoles.stream().map(SysUserRole::getUserId).collect(Collectors.toList());
+
+                    for (SysUserRole sysUserRole : sysUserRoles) {
+                        //删除已处理的待办信息
+                        waitRemindDelete.setLoanApplicationId(loanApplication.getLoanApplicationId());
+                        waitRemindDelete.setReadUserId(sysUserRole.getUserId().toString());
+                        waitRemindDelete.setRemindType(TWO);
+                        waitRemindMapper.deleteWaitRemindByLoanApplicationId(waitRemindDelete);
+
+                        WaitRemind waitRemindManager = new WaitRemind();
+                        waitRemindManager.setLoanApplicationId(loanApplicationId);
+                        waitRemindManager.setLoanApplicationNumber(loanApplication.getLoanApplicationNumber());
+                        waitRemindManager.setRemindTitle("有一条【" + enterpriseName + "】的审核信息申请通过进入到下一阶段");
+                        waitRemindManager.setRemindTime(DateUtils.getNowDate());
+                        waitRemindManager.setRemindType(TWO);
+                        waitRemindManager.setRemindContent(enterpriseName + "有一条贷款申请审核通过进入到下一阶段");
+                        //给管理员发送待办提醒
+                        waitRemindManager.setReadUserId(sysUserRole.getUserId().toString());
+                        waitRemindList.add(waitRemindManager);
+                    }
+                }
+                userIdList.add(reviewComments.getaUserId());
+            }
+/*            //保存参会人员数据 当管理同意上会后A角色选择上会日期,系统自动选择5名评委(评委排除AB角色和风险)
+            if (sysUserConferenceList != null && sysUserConferenceList.size() > 0 && auditSchedule.equals(SEV)) {
+                sysUserConferenceMapper.batchSysUserConference(sysUserConferenceList);
+            }*/
+            //audit_schedule = 2,3的时候贷款申请进度处于担保初审状态
+            else if (auditSchedule.equals(TWO) || auditSchedule.equals(THR)) {
+                loanApplication.setLoanSchedule(THR);
+                loanApplication.setAuditSchedule(String.valueOf(Integer.parseInt(auditSchedule) + 1));
+                loanApplication.setAuditType(ONE);
+                if (auditSchedule.equals(TWO)) {
+                    //删除已处理的待办信息
+
+                    waitRemindDelete.setLoanApplicationId(loanApplication.getLoanApplicationId());
+                    waitRemindDelete.setReadUserId(loanApplication.getbUserId().toString());
+                    waitRemindDelete.setRemindType(TWO);
+                    waitRemindMapper.deleteWaitRemindByLoanApplicationId(waitRemindDelete);
+                    //给B角色发送待办提醒
+                    waitRemind.setReadUserId(loanApplication.getbUserId().toString());
+                    waitRemind.setRemindContent(enterpriseName + "有一条贷款申请需及时处理");
+                    waitRemindList.add(waitRemind);
+                    if (sysUserRoles != null && sysUserRoles.size() > 0) {
+                        //极光推送
+                        userIdList = sysUserRoles.stream().map(SysUserRole::getUserId).collect(Collectors.toList());
+
+                        for (SysUserRole sysUserRole : sysUserRoles) {
+                            //删除已处理的待办信息
+                            waitRemindDelete.setLoanApplicationId(loanApplication.getLoanApplicationId());
+                            waitRemindDelete.setReadUserId(sysUserRole.getUserId().toString());
+                            waitRemindDelete.setRemindType(TWO);
+                            waitRemindMapper.deleteWaitRemindByLoanApplicationId(waitRemindDelete);
+
+                            WaitRemind waitRemindManager = new WaitRemind();
+                            waitRemindManager.setLoanApplicationId(loanApplicationId);
+                            waitRemindManager.setLoanApplicationNumber(loanApplication.getLoanApplicationNumber());
+                            waitRemindManager.setRemindTitle("有一条【" + enterpriseName + "】的审核信息申请通过进入到下一阶段");
+                            waitRemindManager.setRemindTime(DateUtils.getNowDate());
+                            waitRemindManager.setRemindType(TWO);
+                            waitRemindManager.setReadUserId(loanApplication.getaUserId().toString());
+                            waitRemindManager.setRemindContent(enterpriseName + "有一条贷款申请审核通过进入到下一阶段");
+                            //给管理员发送待办提醒
+                            waitRemindManager.setReadUserId(sysUserRole.getUserId().toString());
+                            waitRemindList.add(waitRemindManager);
+                        }
+                    }
+                    userIdList.add(loanApplication.getbUserId());
+                }
+                if (auditSchedule.equals(THR)) {
+                    //删除已处理的待办信息
+
+                    waitRemindDelete.setLoanApplicationId(loanApplication.getLoanApplicationId());
+                    waitRemindDelete.setReadUserId(loanApplication.getfUserId().toString());
+                    waitRemindDelete.setRemindType(TWO);
+                    waitRemindMapper.deleteWaitRemindByLoanApplicationId(waitRemindDelete);
+                    //给风险角色发送待办提醒
+                    waitRemind.setReadUserId(loanApplication.getfUserId().toString());
+                    waitRemind.setRemindContent(enterpriseName + "有一条贷款申请需及时处理");
+                    waitRemindList.add(waitRemind);
+                    if (sysUserRoles != null && sysUserRoles.size() > 0) {
+                        //极光推送
+                        userIdList = sysUserRoles.stream().map(SysUserRole::getUserId).collect(Collectors.toList());
+
+
+                        for (SysUserRole sysUserRole : sysUserRoles) {
+                            //删除已处理的待办信息
+                            waitRemindDelete.setLoanApplicationId(loanApplication.getLoanApplicationId());
+                            waitRemindDelete.setReadUserId(sysUserRole.getUserId().toString());
+                            waitRemindDelete.setRemindType(TWO);
+                            waitRemindMapper.deleteWaitRemindByLoanApplicationId(waitRemindDelete);
+
+                            WaitRemind waitRemindManager = new WaitRemind();
+                            waitRemindManager.setLoanApplicationId(loanApplicationId);
+                            waitRemindManager.setLoanApplicationNumber(loanApplication.getLoanApplicationNumber());
+                            waitRemindManager.setRemindTitle("有一条【" + enterpriseName + "】的审核信息申请通过进入到下一阶段");
+                            waitRemindManager.setRemindTime(DateUtils.getNowDate());
+                            waitRemindManager.setRemindType(TWO);
+                            waitRemindManager.setReadUserId(loanApplication.getaUserId().toString());
+                            waitRemindManager.setRemindContent(enterpriseName + "有一条贷款申请审核通过进入到下一阶段");
+                            //给管理员发送待办提醒
+                            waitRemindManager.setReadUserId(sysUserRole.getUserId().toString());
+                            waitRemindList.add(waitRemindManager);
+                        }
+                    }
+                    userIdList.add(loanApplication.getfUserId());
+                }
+                //审核流程结束
+            } else {
+                loanApplication.setLoanSchedule(String.valueOf(Integer.parseInt(loanScheduleOld) + 1));
+                loanApplication.setAuditSchedule(String.valueOf(Integer.parseInt(auditSchedule) + 1));
+                loanApplication.setAuditType(ONE);
+                //删除已处理的待办信息
+
+                waitRemindDelete.setLoanApplicationId(loanApplication.getLoanApplicationId());
+                waitRemindDelete.setReadUserId(loanApplication.getaUserId().toString());
+                waitRemindDelete.setRemindType(loanApplication.getLoanSchedule());
+                waitRemindMapper.deleteWaitRemindByLoanApplicationId(waitRemindDelete);
+                //给A角色发送待办提醒
+                waitRemind.setRemindType(loanApplication.getLoanSchedule());
+                waitRemind.setReadUserId(loanApplication.getaUserId().toString());
+                waitRemind.setRemindContent(enterpriseName + "的审核信息申请通过进入到下一阶段");
+                waitRemindList.add(waitRemind);
+                if (sysUserRoles != null && sysUserRoles.size() > 0) {
+                    //极光推送
+                    userIdList = sysUserRoles.stream().map(SysUserRole::getUserId).collect(Collectors.toList());
+
+                    for (SysUserRole sysUserRole : sysUserRoles) {
+                        //删除已处理的待办信息
+                        waitRemindDelete.setLoanApplicationId(loanApplication.getLoanApplicationId());
+                        waitRemindDelete.setReadUserId(sysUserRole.getUserId().toString());
+                        waitRemindDelete.setRemindType(TWO);
+                        waitRemindMapper.deleteWaitRemindByLoanApplicationId(waitRemindDelete);
+                        WaitRemind waitRemindManager = new WaitRemind();
+                        waitRemindManager.setLoanApplicationId(loanApplicationId);
+                        waitRemindManager.setLoanApplicationNumber(loanApplication.getLoanApplicationNumber());
+                        waitRemindManager.setRemindTitle("有一条【" + enterpriseName + "】的审核信息进入到下一阶段");
+                        waitRemindManager.setRemindTime(DateUtils.getNowDate());
+                        waitRemindManager.setRemindType(loanApplication.getLoanSchedule());
+                        waitRemindManager.setRemindContent(enterpriseName + "的审核信息申请通过进入到下一阶段");
+                        //给管理员发送待办提醒
+                        waitRemindManager.setReadUserId(sysUserRole.getUserId().toString());
+                        waitRemindList.add(waitRemindManager);
+                    }
+                }
+                userIdList.add(loanApplication.getaUserId());
+            }
+            loanApplicationMapper.updateLoanApplication(loanApplication);
+            //插入流程记录表
+            LoanSchedule loanSchedule = new LoanSchedule();
+            loanSchedule.setLoanApplicationId(loanApplicationId);
+            loanSchedule.setLoanApplicationNumber(loanApplication.getLoanApplicationNumber());
+            loanSchedule.setLoanScheduleValue(loanApplication.getLoanSchedule());
+            loanSchedule.setLoanScheduleScore(Long.parseLong(loanApplication.getLoanSchedule()));
+            loanSchedule.setLoanScheduleTime(DateUtils.getNowDate());
+            loanScheduleMapper.insertLoanSchedule(loanSchedule);
+            //插入审核通过的待办提醒
+            if (waitRemindList.size() > 0) {
+                waitRemindMapper.batchWaitRemind(waitRemindList);
+
+                //发极光推送id
+                List<SysUser> sysUsers = sysUserService.selectUserListByIdList(userIdList);
+                if (sysUsers != null && sysUsers.size() > 0) {
+                    String notificationTitle = "消息通知";
+                    String msgTitle = "审核信息";
+                    String msgContent = enterpriseName + "的审核信息申请通过进入到下一阶段";
+                    String jPushVO = "";
+                    List<String> listS = sysUsers.stream().map(SysUser::getJgId).collect(Collectors.toList());
+                    listS.removeAll(Collections.singleton(null));
+                    if (listS != null && listS.size() > 0) {
+                        String[] registrationId = listS.toArray(new String[listS.size()]);
+                        JPushToolUtil.sendToRegistrationId(notificationTitle, msgTitle, msgContent, jPushVO, registrationId);
+                    }
+                }
+            }
+        }
+        return AjaxResult.success();
+    }
+
+    /**
+     * 申诉
+     *
+     * @param loanApplication
+     * @return
+     */
+    @Override
+    @Transactional
+    public AjaxResult ss(LoanApplication loanApplication) {
+        Long loanApplicationId = loanApplication.getLoanApplicationId();
+        //先判断当前人是否是A角色或者B角色
+        Long userId = SecurityUtils.getUserId();
+        Long aLong = loanApplication.getaUserId();
+        Long bLong = loanApplication.getbUserId();
+        if (Objects.equals(userId, aLong) || Objects.equals(userId, bLong)) {
+            //判断当前项目是否是在申诉状态
+            String auditType = loanApplication.getAuditType();
+            if (!FOR.equals(auditType)) {
+                return AjaxResult.error("当前项目无需申诉或状态异常");
+            }
+            //判断是否是放弃申诉 如果AB角色都放弃申诉则项目结束 = 放到回收站
+            String ssType = loanApplication.getSsType();
+            if (ONE.equals(ssType)) {
+                //申诉中判断评审会进度不是1等待上会,则重置为1
+                loanApplication.setReviewSchedule(ONE);
+                //进入待审核
+                loanApplication.setAuditType(ONE);
+                loanApplicationMapper.updateLoanApplication(loanApplication);
+                //删除基础附件外的所有附件
+                //loanApplicationFjMapper.deleteLoanApplicationFjByLoanApplicationIdAndBigType(loanApplication.getLoanApplicationId());
+
+                //业务审核意见
+                ReviewComments reviewComments = new ReviewComments();
+                reviewComments.setLoanApplicationId(loanApplicationId);
+                reviewComments.setLoanApplicationNumber(loanApplication.getLoanApplicationNumber());
+                reviewComments.setAuditSchedule(TWO);
+                reviewComments.setAuditType(FOR);
+                reviewComments.setAuditTime(DateUtils.getNowDate());
+                reviewComments.setCreateBy(SecurityUtils.getUsername());
+                reviewCommentsMapper.insertReviewComments(reviewComments);
+            } else if (TWO.equals(ssType)) {
+                //放弃申诉需要AB角色都要放弃
+                //先判断是A还是B角色
+                String key = loanApplicationId + ":ss:";
+                if (Objects.equals(userId, aLong)) {
+                    Object cacheObjectA = redisCache.getCacheObject(key + A);
+                    if (ObjectUtils.isNotEmpty(cacheObjectA)) {
+                        //
+                        return AjaxResult.error("请勿重复放弃");
+                    } else {
+                        //A是空则查询B
+                        Object cacheObjectB = redisCache.getCacheObject(key + B);
+                        if (ObjectUtils.isNotEmpty(cacheObjectB)) {
+                            //修改项目状态到回收站
+                            loanApplication.setLoanApplicationType(THR);
+                            loanApplicationMapper.updateLoanApplication(loanApplication);
+                        } else {
+                            redisCache.setCacheObject(key + A, aLong);
+                        }
+                    }
+                }
+                if (Objects.equals(userId, bLong)) {
+                    Object cacheObjectB = redisCache.getCacheObject(key + B);
+                    if (ObjectUtils.isNotEmpty(cacheObjectB)) {
+                        //
+                        return AjaxResult.error("请勿重复放弃");
+                    } else {
+                        //B是空则查询A
+                        Object cacheObjectA = redisCache.getCacheObject(key + A);
+                        if (ObjectUtils.isNotEmpty(cacheObjectA)) {
+                            //修改项目状态到回收站
+                            loanApplication.setLoanApplicationType(THR);
+                            loanApplicationMapper.updateLoanApplication(loanApplication);
+                        } else {
+                            redisCache.setCacheObject(key + B, aLong);
+                        }
+                    }
+                }
+            }
+            return AjaxResult.success();
+        }
+        return AjaxResult.error("当前您无权限申诉,请联系管理员");
+    }
+
+    /**
+     * 管理员同意/不同意上会审核按钮
+     *
+     * @param loanApplication
+     * @return
+     */
+    @Override
+    @Transactional
+    public AjaxResult review(LoanApplication loanApplication) {
+        String loanSchedule = loanApplication.getLoanSchedule();
+        String auditSchedule = loanApplication.getAuditSchedule();
+        String auditType = loanApplication.getAuditType();
+        String reviewSchedule = loanApplication.getReviewSchedule();
+        //判断项目状态
+        if (!loanSchedule.equals(SIX) || !auditSchedule.equals(SEV) || !auditType.equals(ONE)) {
+            return AjaxResult.error("当前项目状态异常,不允许上会");
+        }
+        int rows = loanApplicationMapper.updateLoanApplication(loanApplication);
+        //删除所有状态小于的待办事项
+        WaitRemind waitRemindDelete = new WaitRemind();
+        waitRemindDelete.setLoanApplicationId(loanApplication.getLoanApplicationId());
+        waitRemindDelete.setReadUserId(loanApplication.getaUserId().toString());
+        waitRemindDelete.setRemindType(SIX);
+        waitRemindMapper.deleteWaitRemindByLoanApplicationId(waitRemindDelete);
+        //给A角色发送上会审核信息
+        WaitRemind waitRemindManager = new WaitRemind();
+        waitRemindManager.setLoanApplicationId(loanApplication.getLoanApplicationId());
+        waitRemindManager.setLoanApplicationNumber(loanApplication.getLoanApplicationNumber());
+        waitRemindManager.setRemindTitle("有一条【" + loanApplication.getEnterpriseName() + "】的上会审核信息");
+        waitRemindManager.setRemindTime(DateUtils.getNowDate());
+        waitRemindManager.setRemindType(SIX);
+        waitRemindManager.setReadUserId(loanApplication.getaUserId().toString());
+        String result = "通过";
+        if (TWO.equals(reviewSchedule)) {
+            result = "不通过";
+        }
+        waitRemindManager.setRemindContent(loanApplication.getEnterpriseName() + "的上会审核信息申请" + result);
+        //给管理员发送待办提醒
+        waitRemindManager.setReadUserId(String.valueOf(loanApplication.getaUserId()));
+        waitRemindMapper.insertWaitRemind(waitRemindManager);
+
+        //发极光推送
+        SysUser user = sysUserService.selectUserById(loanApplication.getaUserId());
+        if (StringUtils.isNotEmpty(user.getJgId())) {
+            String notificationTitle = "消息通知";
+            String msgTitle = "上会审核信息";
+            String msgContent = loanApplication.getEnterpriseName() + "的上会审核信息申请" + result;
+            String jPushVO = "";
+            JPushToolUtil.sendToRegistrationId(notificationTitle, msgTitle, msgContent, jPushVO, user.getJgId());
+        }
+
+        return rows > 0 ? AjaxResult.success() : AjaxResult.error();
+    }
+
+    /**
+     * 7:合同签约 8:放款合规风险审核推进到下一步功能
+     *
+     * @param loanApplication
+     * @return
+     */
+    @Override
+    @Transactional
+    public AjaxResult schedule(LoanApplication loanApplication) {
+        String loanSchedule = loanApplication.getLoanSchedule();
+        if (!SEV.equals(loanSchedule) && !EIG.equals(loanSchedule)) {
+            return AjaxResult.error("当前项目进度错误。");
+        }
+        LoanApplication application = new LoanApplication();
+        application.setLoanApplicationId(loanApplication.getLoanApplicationId());
+        application.setAuditType(TWO);
+        if (SEV.equals(loanSchedule)) {
+            application.setLoanSchedule(EIG);
+            application.setAuditSchedule(NIN);
+        }
+        if (EIG.equals(loanSchedule)) {
+            application.setLoanSchedule(NIN);
+            application.setAuditSchedule(TEN);
+        }
+        loanApplicationMapper.updateLoanApplication(application);
+        //删除所有状态小于的待办事项
+        WaitRemind waitRemindDelete = new WaitRemind();
+        waitRemindDelete.setLoanApplicationId(loanApplication.getLoanApplicationId());
+        waitRemindDelete.setReadUserId(loanApplication.getaUserId().toString());
+        waitRemindDelete.setRemindType(loanSchedule);
+        waitRemindMapper.deleteWaitRemindByLoanApplicationId(waitRemindDelete);
+        //给A角色发送待办提醒
+        //待办信息集合
+        //查询审核管理员用户id
+        List<SysUserRole> sysUserRoles = sysUserRoleMapper.selectRoleListNoDataScope();
+        List<WaitRemind> waitRemindList = new ArrayList<>();
+        WaitRemind waitRemind = new WaitRemind();
+        waitRemind.setLoanApplicationId(loanApplication.getLoanApplicationId());
+        waitRemind.setLoanApplicationNumber(loanApplication.getLoanApplicationNumber());
+        waitRemind.setRemindTitle("您有一条【" + loanApplication.getEnterpriseName() + "】的审核信息进入到下一阶段");
+        waitRemind.setRemindTime(DateUtils.getNowDate());
+        waitRemind.setRemindType(loanSchedule);
+        waitRemind.setReadUserId(loanApplication.getaUserId().toString());
+        waitRemind.setRemindContent(loanApplication.getEnterpriseName() + "的审核信息申请通过进入到下一阶段");
+        waitRemindList.add(waitRemind);
+        List<Long> userIdList = new ArrayList<>();
+        if (sysUserRoles != null && sysUserRoles.size() > 0) {
+            //极光推送
+            userIdList = sysUserRoles.stream().map(SysUserRole::getUserId).collect(Collectors.toList());
+
+
+            for (SysUserRole sysUserRole : sysUserRoles) {
+                //删除所有状态小于的待办事项
+                waitRemindDelete.setLoanApplicationId(loanApplication.getLoanApplicationId());
+                waitRemindDelete.setReadUserId(sysUserRole.getUserId().toString());
+                waitRemindDelete.setRemindType(loanSchedule);
+                waitRemindMapper.deleteWaitRemindByLoanApplicationId(waitRemindDelete);
+
+                WaitRemind waitRemindManager = new WaitRemind();
+                waitRemindManager.setLoanApplicationId(loanApplication.getLoanApplicationId());
+                waitRemindManager.setLoanApplicationNumber(loanApplication.getLoanApplicationNumber());
+                waitRemindManager.setRemindTitle("有一条【" + loanApplication.getEnterpriseName() + "】的审核信息进入到下一阶段");
+                waitRemindManager.setRemindTime(DateUtils.getNowDate());
+                waitRemindManager.setRemindType(loanSchedule);
+                waitRemindManager.setReadUserId(loanApplication.getaUserId().toString());
+                waitRemindManager.setRemindContent(loanApplication.getEnterpriseName() + "的审核信息申请通过进入到下一阶段");
+                //给管理员发送待办提醒
+                waitRemindManager.setReadUserId(sysUserRole.getUserId().toString());
+                waitRemindList.add(waitRemindManager);
+            }
+        }
+        waitRemindMapper.batchWaitRemind(waitRemindList);
+
+        //发极光推送id
+        userIdList.add(loanApplication.getaUserId());
+        List<SysUser> sysUsers = sysUserService.selectUserListByIdList(userIdList);
+        if (sysUsers != null && sysUsers.size() > 0) {
+            String notificationTitle = "消息通知";
+            String msgTitle = "审核信息";
+            String msgContent = loanApplication.getEnterpriseName() + "的审核信息申请通过进入到下一阶段";
+            String jPushVO = "";
+            List<String> listS = sysUsers.stream().map(SysUser::getJgId).collect(Collectors.toList());
+            listS.removeAll(Collections.singleton(null));
+            if (listS != null && listS.size() > 0) {
+                String[] registrationId = listS.toArray(new String[listS.size()]);
+                JPushToolUtil.sendToRegistrationId(notificationTitle, msgTitle, msgContent, jPushVO, registrationId);
+            }
+        }
+
+
+        //业务审核意见
+        ReviewComments reviewComments = new ReviewComments();
+        reviewComments.setLoanApplicationId(loanApplication.getLoanApplicationId());
+        reviewComments.setLoanApplicationNumber(loanApplication.getLoanApplicationNumber());
+        reviewComments.setAuditSchedule(loanApplication.getAuditSchedule());
+        reviewComments.setAuditType(TWO);
+        reviewComments.setAuditTime(DateUtils.getNowDate());
+        reviewComments.setCreateBy(SecurityUtils.getUsername());
+        //业务审核意见
+        reviewCommentsMapper.insertReviewComments(reviewComments);
+        return AjaxResult.success();
+    }
+
+    /**
+     * 撤销返回到上一步
+     *
+     * @param loanApplication
+     * @return
+     */
+    @Override
+    @Transactional
+    public AjaxResult cx(LoanApplication loanApplication) {
+
+        List<Long> userIdList = new ArrayList<>();
+
+        Long loanApplicationId = loanApplication.getLoanApplicationId();
+        //获取当前状态
+        String loanSchedule = loanApplication.getLoanSchedule();
+        String auditSchedule = loanApplication.getAuditSchedule();
+        String loanApplicationType = loanApplication.getLoanApplicationType();
+        String auditType = loanApplication.getAuditType();
+        List<WaitRemind> waitRemindList = new ArrayList<>();
+
+        LoanApplication loanApplicationOld = loanApplicationMapper.selectLoanApplicationByLoanApplicationId(loanApplicationId);
+        //reviewCommentsMapper.deleteReviewCommentsByLoanApplicationIdAndAuditSchedule(loanApplicationId, auditSchedule);
+        if (Integer.parseInt(loanSchedule) < 2 || Integer.parseInt(auditSchedule) < 1 || Integer.parseInt(loanApplicationType) != 2) {
+            return AjaxResult.error("当前项目不可撤销");
+        }
+        if (Integer.parseInt(loanSchedule) > 7) {
+            //撤销只返回贷款申请进度到上一步
+            loanApplication.setLoanSchedule(String.valueOf(Integer.parseInt(loanSchedule) - 1));
+            loanApplication.setAuditSchedule(String.valueOf(Integer.parseInt(auditSchedule) - 1));
+        } else {
+            //如果是待审核的撤销就退一步否则就是改为待审核
+            if (ONE.equals(auditType)) {
+                String reviewSchedule = loanApplication.getReviewSchedule();
+                //等于6:评审会撤销
+                if (SIX.equals(loanSchedule) && !ONE.equals(reviewSchedule)) {
+                    loanApplication.setReviewSchedule(ONE);
+                    if (Integer.parseInt(reviewSchedule) > 3) {
+                        //撤销到确认上会
+                        loanApplication.setReviewSchedule(THR);
+                        loanApplication.setReviewTime("");
+                        //删掉参会人员
+                        sysUserConferenceMapper.deleteSysUserConferenceByTime(loanApplicationOld.getReviewTime(), loanApplicationOld.getLoanApplicationId());
+                    }
+                } else if (auditSchedule.equals(FOR) || auditSchedule.equals(THR)) {
+                    loanApplication.setLoanSchedule(THR);
+                    loanApplication.setAuditSchedule(String.valueOf(Integer.parseInt(auditSchedule) - 1));
+                } else {
+                    loanApplication.setAuditSchedule(String.valueOf(Integer.parseInt(auditSchedule) - 1));
+                    loanApplication.setLoanSchedule(String.valueOf(Integer.parseInt(loanSchedule) - 1));
+                    //撤销完成后是到上会评审=评审会进度到 3:同意上会
+                    if (SIX.equals(loanApplication.getLoanSchedule())) {
+                        loanApplication.setReviewSchedule(THR);
+                        loanApplication.setReviewTime("");
+                        //删掉参会人员
+                        sysUserConferenceMapper.deleteSysUserConferenceByTime(loanApplicationOld.getReviewTime(), loanApplicationOld.getLoanApplicationId());
+                    }
+                    if (loanApplication.getLoanSchedule().equals(TWO) && loanApplication.getAuditSchedule().equals(ONE)) {
+                        //撤回到重新分配AB风险,重置主表数据
+                        loanApplication.setaUserId(null);
+                        loanApplication.setaUserName("");
+                        loanApplication.setbUserId(null);
+                        loanApplication.setbUserName("");
+                        loanApplication.setfUserId(null);
+                        loanApplication.setfUserName("");
+                    }
+                }
+            } else {
+                //进入待审核
+                loanApplication.setAuditType(ONE);
+            }
+            String enterpriseName = loanApplicationOld.getEnterpriseName();
+            String loanApplicationNumber = loanApplicationOld.getLoanApplicationNumber();
+
+            //如果退到 A角色审核 B角色审核 还需要插入待办提醒
+            if (loanApplication.getAuditSchedule().equals(TWO)) {
+                //删除所有状态小于的待办事项
+                WaitRemind waitRemindDelete = new WaitRemind();
+                waitRemindDelete.setLoanApplicationId(loanApplication.getLoanApplicationId());
+                waitRemindDelete.setReadUserId(loanApplicationOld.getaUserId().toString());
+                waitRemindDelete.setRemindType(TWO);
+                waitRemindMapper.deleteWaitRemindByLoanApplicationId(waitRemindDelete);
+                WaitRemind waitRemind = new WaitRemind();
+                waitRemind.setLoanApplicationId(loanApplicationId);
+                waitRemind.setLoanApplicationNumber(loanApplicationNumber);
+                waitRemind.setRemindTitle("您有一条【" + enterpriseName + "】的审核信息待办");
+                waitRemind.setRemindTime(DateUtils.getNowDate());
+                waitRemind.setRemindType(TWO);
+                //给A角色发送待办提醒
+                waitRemind.setReadUserId(loanApplicationOld.getaUserId().toString());
+                waitRemind.setRemindContent(enterpriseName + "有一条贷款申请需及时处理");
+                waitRemindList.add(waitRemind);
+
+                userIdList.add(loanApplicationOld.getaUserId());
+            }
+            if (loanApplication.getAuditSchedule().equals(THR)) {
+                //删除所有状态小于的待办事项
+                WaitRemind waitRemindDelete = new WaitRemind();
+                waitRemindDelete.setLoanApplicationId(loanApplication.getLoanApplicationId());
+                waitRemindDelete.setReadUserId(loanApplicationOld.getbUserId().toString());
+                waitRemindDelete.setRemindType(TWO);
+                waitRemindMapper.deleteWaitRemindByLoanApplicationId(waitRemindDelete);
+                WaitRemind waitRemind = new WaitRemind();
+                waitRemind.setLoanApplicationId(loanApplicationId);
+                waitRemind.setLoanApplicationNumber(loanApplicationNumber);
+                waitRemind.setRemindTitle("您有一条【" + enterpriseName + "】的审核信息待办");
+                waitRemind.setRemindTime(DateUtils.getNowDate());
+                waitRemind.setRemindType(TWO);
+                //给B角色发送待办提醒
+                waitRemind.setReadUserId(loanApplicationOld.getbUserId().toString());
+                waitRemind.setRemindContent(enterpriseName + "有一条贷款申请需及时处理");
+                waitRemindList.add(waitRemind);
+
+                userIdList.add(loanApplicationOld.getbUserId());
+            }
+        }
+        loanApplicationMapper.updateLoanApplication2(loanApplication);
+
+
+        //给A角色发送待办提醒
+        //待办信息集合
+        //查询审核管理员用户id
+        List<SysUserRole> sysUserRoles = sysUserRoleMapper.selectRoleListNoDataScope();
+        if (ObjectUtils.isNotEmpty(loanApplication.getaUserId())) {
+
+            //删除所有状态小于的待办事项
+            WaitRemind waitRemindDelete = new WaitRemind();
+            waitRemindDelete.setLoanApplicationId(loanApplication.getLoanApplicationId());
+            waitRemindDelete.setReadUserId(loanApplication.getaUserId().toString());
+            waitRemindDelete.setRemindType(loanSchedule);
+            waitRemindMapper.deleteWaitRemindByLoanApplicationId(waitRemindDelete);
+
+            WaitRemind waitRemind = new WaitRemind();
+            waitRemind.setLoanApplicationId(loanApplication.getLoanApplicationId());
+            waitRemind.setLoanApplicationNumber(loanApplication.getLoanApplicationNumber());
+            waitRemind.setRemindTitle("您有一条【" + loanApplication.getEnterpriseName() + "】的信息进行了撤销");
+            waitRemind.setRemindTime(DateUtils.getNowDate());
+            waitRemind.setRemindType(loanSchedule);
+            waitRemind.setReadUserId(loanApplication.getaUserId().toString());
+            waitRemind.setRemindContent(loanApplication.getEnterpriseName() + "的信息进行了撤销");
+            waitRemindList.add(waitRemind);
+            if (sysUserRoles != null && sysUserRoles.size() > 0) {
+                //极光推送
+                List<Long> userIds = sysUserRoles.stream().map(SysUserRole::getUserId).collect(Collectors.toList());
+                userIdList.addAll(userIds);
+
+                for (SysUserRole sysUserRole : sysUserRoles) {
+
+                    //删除所有状态小于的待办事项
+
+                    waitRemindDelete.setLoanApplicationId(loanApplication.getLoanApplicationId());
+                    waitRemindDelete.setReadUserId(sysUserRole.getUserId().toString());
+                    waitRemindDelete.setRemindType(loanSchedule);
+                    waitRemindMapper.deleteWaitRemindByLoanApplicationId(waitRemindDelete);
+
+                    WaitRemind waitRemindManager = new WaitRemind();
+                    waitRemindManager.setLoanApplicationId(loanApplication.getLoanApplicationId());
+                    waitRemindManager.setLoanApplicationNumber(loanApplication.getLoanApplicationNumber());
+                    waitRemindManager.setRemindTitle("有一条【" + loanApplication.getEnterpriseName() + "】的信息进行了撤销");
+                    waitRemindManager.setRemindTime(DateUtils.getNowDate());
+                    waitRemindManager.setRemindType(loanSchedule);
+                    waitRemindManager.setRemindContent(loanApplication.getEnterpriseName() + "的信息进行了撤销");
+                    //给管理员发送待办提醒
+                    waitRemindManager.setReadUserId(sysUserRole.getUserId().toString());
+                    waitRemindList.add(waitRemindManager);
+                }
+            }
+            userIdList.add(loanApplication.getaUserId());
+        }
+
+        if (waitRemindList != null && waitRemindList.size() > 0) {
+            waitRemindMapper.batchWaitRemind(waitRemindList);
+
+            //发极光推送id
+            List<SysUser> sysUsers = sysUserService.selectUserListByIdList(userIdList);
+            if (sysUsers != null && sysUsers.size() > 0) {
+                String notificationTitle = "消息通知";
+                String msgTitle = "撤销信息";
+                String msgContent = loanApplication.getEnterpriseName() + "的信息进行了撤销";
+                String jPushVO = "";
+                List<String> listS = sysUsers.stream().map(SysUser::getJgId).collect(Collectors.toList());
+                listS.removeAll(Collections.singleton(null));
+                if (listS != null && listS.size() > 0) {
+                    String[] registrationId = listS.toArray(new String[listS.size()]);
+                    JPushToolUtil.sendToRegistrationId(notificationTitle, msgTitle, msgContent, jPushVO, registrationId);
+                }
+            }
+        }
+
+        //业务审核意见插入撤销
+        ReviewComments reviewComments = new ReviewComments();
+        reviewComments.setLoanApplicationId(loanApplication.getLoanApplicationId());
+        reviewComments.setLoanApplicationNumber(loanApplication.getLoanApplicationNumber());
+        int auditScheduleNew = Integer.parseInt(loanApplication.getAuditSchedule());
+        if (Integer.parseInt(loanApplication.getLoanSchedule()) > 6) {
+            auditScheduleNew = auditScheduleNew + 1;
+        }
+        reviewComments.setAuditSchedule(String.valueOf(auditScheduleNew));
+        reviewComments.setAuditType(FIV);
+        reviewComments.setAuditTime(DateUtils.getNowDate());
+        reviewComments.setCreateBy(SecurityUtils.getUsername());
+        reviewCommentsMapper.insertReviewComments(reviewComments);
+        return AjaxResult.success();
+    }
+
+    /**
+     * 一键归档
+     *
+     * @param loanApplication
+     * @return
+     */
+    @Override
+    @Transactional
+    public AjaxResult gd(LoanApplication loanApplication) {
+        //判断项目是否能归档
+        String loanSchedule = loanApplication.getLoanSchedule();
+        String loanApplicationType = loanApplication.getLoanApplicationType();
+        String auditType = loanApplication.getAuditType();
+        if (!NIN.equals(loanSchedule) && !TWO.equals(loanApplicationType) && !TWO.equals(auditType)) {
+            return AjaxResult.error("当前项目进度不能归档");
+        }
+        loanApplication.setLoanSchedule(TEN);
+        loanApplication.setLoanApplicationType(FOR);
+        loanApplication.setAuditSchedule(ELE);
+        loanApplication.setFileTime(DateUtils.getNowDate());
+
+        //插入流程记录表
+        LoanSchedule loanScheduleNew = new LoanSchedule();
+        loanScheduleNew.setLoanApplicationId(loanApplication.getLoanApplicationId());
+        loanScheduleNew.setLoanScheduleValue(loanApplication.getLoanSchedule());
+        loanScheduleNew.setLoanScheduleScore(Long.parseLong(loanApplication.getLoanSchedule()));
+        loanScheduleNew.setLoanScheduleTime(DateUtils.getNowDate());
+        loanScheduleNew.setLoanApplicationNumber(loanApplication.getLoanApplicationNumber());
+        loanScheduleMapper.insertLoanSchedule(loanScheduleNew);
+        // 上传文件路径
+        String filePath = RuoYiConfig.getUploadPath() + "/";
+        Long loanApplicationId = loanApplication.getLoanApplicationId();
+        //附件
+        List<LoanApplicationFj> loanApplicationFjList = loanApplicationFjMapper.selectLoanApplicationFjByLoanApplicationId(loanApplicationId);
+        //基础附件
+        LoanApplication loanApplicationOld = loanApplicationMapper.selectLoanApplicationByLoanApplicationId(loanApplicationId);
+        //股东附件
+        List<ShareholderFj> shareholderFjs = shareholderFjMapper.selectShareholderFjLoanApplicationId(loanApplicationId);
+
+        //反担保人附件
+        List<GuaranteeInfoFj> guaranteeInfoFjs = guaranteeInfoFjMapper.selectGuaranteeInfoFjByLoanApplicationId(loanApplicationId);
+        Map<File, Integer> map = new HashMap<>();
+        List<File> fileList = new ArrayList<>();
+        if (loanApplicationFjList != null && loanApplicationFjList.size() > 0) {
+            for (LoanApplicationFj loanApplicationFj : loanApplicationFjList) {
+                File file = new File(loanApplicationFj.getUrl().replace("/profile/upload/", filePath));
+                map.put(file, FjType.getDriverType(loanApplicationFj.getType()));
+            }
+        }
+        String corporationFront = loanApplicationOld.getCorporationFront();
+        String corporationBack = loanApplicationOld.getCorporationBack();
+        String spouseFront = loanApplicationOld.getSpouseFront();
+        String spouseBack = loanApplicationOld.getSpouseBack();
+
+        if (StringUtils.isNotEmpty(corporationFront)) {
+            map.put(new File(corporationFront.replace("/profile/upload/", filePath)), FjType.getDriverType("frsfzrmx"));
+        }
+        if (StringUtils.isNotEmpty(corporationBack)) {
+            map.put(new File(corporationBack.replace("/profile/upload/", filePath)), FjType.getDriverType("frsfzghm"));
+        }
+        if (StringUtils.isNotEmpty(spouseFront)) {
+            map.put(new File(spouseFront.replace("/profile/upload/", filePath)), FjType.getDriverType("frsfzpormx"));
+        }
+        if (StringUtils.isNotEmpty(spouseBack)) {
+            map.put(new File(spouseBack.replace("/profile/upload/", filePath)), FjType.getDriverType("frsfzpoghm"));
+        }
+        //进行排序
+        List<Map.Entry<File, Integer>> list = new ArrayList<>(map.entrySet());
+        // 根据 value 进行排序,这里使用了 lambda 表达式和比较器
+        list.sort(Collections.reverseOrder(Map.Entry.comparingByValue()));
+        for (Map.Entry<File, Integer> fileIntegerEntry : list) {
+            fileList.add(fileIntegerEntry.getKey());
+        }
+        //股东附件
+        if (shareholderFjs != null && shareholderFjs.size() > 0) {
+            for (ShareholderFj shareholderFj : shareholderFjs) {
+                fileList.add(new File(shareholderFj.getShareholderZxUrl().replace("/profile/upload/", filePath)));
+                String shareholderFrontUrl = shareholderFj.getShareholderFrontUrl();
+                String shareholderBackUrl = shareholderFj.getShareholderBackUrl();
+                String shareholderBusinessUrl = shareholderFj.getShareholderBusinessUrl();
+                if (StringUtils.isNotBlank(shareholderFrontUrl)) {
+                    fileList.add(new File(shareholderFj.getShareholderFrontUrl().replace("/profile/upload/", filePath)));
+                }
+                if (StringUtils.isNotBlank(shareholderBackUrl)) {
+                    fileList.add(new File(shareholderFj.getShareholderBackUrl().replace("/profile/upload/", filePath)));
+                }
+                if (StringUtils.isNotBlank(shareholderBusinessUrl)) {
+                    fileList.add(new File(shareholderFj.getShareholderBusinessUrl().replace("/profile/upload/", filePath)));
+                }
+            }
+        }
+
+        if (guaranteeInfoFjs != null && guaranteeInfoFjs.size() > 0) {
+            for (GuaranteeInfoFj guaranteeInfoFj : guaranteeInfoFjs) {
+                fileList.add(new File(guaranteeInfoFj.getUrl().replace("/profile/upload/", filePath)));
+            }
+        }
+
+        //16位序列号
+        String id = Seq.getId(Seq.uploadSeqType);
+        String name = StringUtils.format("{}_{}.{}",
+                loanApplicationOld.getEnterpriseName(), id + "文档", "zip");
+        String zipFileName = StringUtils.format("{}/{}_{}.{}", loanApplicationOld.getLoanApplicationNumber(),
+                loanApplicationOld.getEnterpriseName(), id + "文档", "zip");
+        //进行压缩
+        zipEncryptExample(fileList, filePath, zipFileName, "123");
+        //把压缩包的url插入附件表
+        LoanApplicationFj loanApplicationFj = new LoanApplicationFj();
+        loanApplicationFj.setLoanApplicationId(loanApplicationId);
+        loanApplicationFj.setLoanApplicationNumber(loanApplicationOld.getLoanApplicationNumber());
+        loanApplicationFj.setOldName(name);
+        loanApplicationFj.setName(name);
+        loanApplicationFj.setUrl("/profile/upload/" + loanApplicationOld.getLoanApplicationNumber() + "/" + name);
+        loanApplicationFj.setBigType("e");
+        loanApplicationFj.setCreateTime(DateUtils.getNowDate());
+        loanApplicationFjMapper.insertLoanApplicationFj(loanApplicationFj);
+        loanApplicationMapper.updateLoanApplication(loanApplication);
+
+/*        //给A角色发送待办提醒
+        //待办信息集合
+        //查询审核管理员用户id
+        List<SysUserRole> sysUserRoles = sysUserRoleMapper.selectRoleListNoDataScope();
+        List<WaitRemind> waitRemindList = new ArrayList<>();
+        WaitRemind waitRemind = new WaitRemind();
+        waitRemind.setLoanApplicationId(loanApplication.getLoanApplicationId());
+        waitRemind.setLoanApplicationNumber(loanApplication.getLoanApplicationNumber());
+        waitRemind.setRemindTitle("您有一条【" + loanApplication.getEnterpriseName() + "】的信息进入归档");
+        waitRemind.setRemindTime(DateUtils.getNowDate());
+        waitRemind.setRemindType(loanSchedule);
+        waitRemind.setReadUserId(loanApplication.getaUserId().toString());
+        waitRemind.setRemindContent(loanApplication.getEnterpriseName() + "的信息进入归档");
+        waitRemindList.add(waitRemind);
+        List<Long> userIdList = new ArrayList<>();
+        if (sysUserRoles != null && sysUserRoles.size() > 0) {
+            //极光推送
+            userIdList = sysUserRoles.stream().map(SysUserRole::getUserId).collect(Collectors.toList());
+
+            for (SysUserRole sysUserRole : sysUserRoles) {
+                WaitRemind waitRemindManager = new WaitRemind();
+                waitRemindManager.setLoanApplicationId(loanApplication.getLoanApplicationId());
+                waitRemindManager.setLoanApplicationNumber(loanApplication.getLoanApplicationNumber());
+                waitRemindManager.setRemindTitle("有一条【" + loanApplication.getEnterpriseName() + "】的信息进入归档");
+                waitRemindManager.setRemindTime(DateUtils.getNowDate());
+                waitRemindManager.setRemindType(loanSchedule);
+                waitRemindManager.setReadUserId(loanApplication.getaUserId().toString());
+                waitRemindManager.setRemindContent(loanApplication.getEnterpriseName() + "的信息进入归档");
+                //给管理员发送待办提醒
+                waitRemindManager.setReadUserId(sysUserRole.getUserId().toString());
+                waitRemindList.add(waitRemindManager);
+            }
+        }
+        waitRemindMapper.batchWaitRemind(waitRemindList);*/
+
+        //发极光推送id
+        /*userIdList.add(loanApplication.getaUserId());
+        List<SysUser> sysUsers = sysUserService.selectUserListByIdList(userIdList);
+        if(sysUsers!=null && sysUsers.size()>0){
+            String notificationTitle = "消息通知";
+            String msgTitle = "信息归档";
+            String msgContent = loanApplication.getEnterpriseName() + "的信息进入归档";
+            String jPushVO = "";
+            List<String> listS = sysUsers.stream().map(SysUser::getJgId).collect(Collectors.toList());
+            listS.removeAll(Collections.singleton(null));
+            if(listS!=null && listS.size()>0){
+                String[]  registrationId = listS.toArray(new String[listS.size()]);
+                JPushToolUtil.sendToRegistrationId(notificationTitle,msgTitle,msgContent,jPushVO,registrationId);
+            }
+        }*/
+
+        //业务审核意见
+        ReviewComments reviewComments = new ReviewComments();
+        reviewComments.setLoanApplicationId(loanApplication.getLoanApplicationId());
+        reviewComments.setLoanApplicationNumber(loanApplication.getLoanApplicationNumber());
+        //归档
+        reviewComments.setAuditSchedule(ELE);
+        reviewComments.setAuditType(TWO);
+        reviewComments.setAuditTime(DateUtils.getNowDate());
+        reviewComments.setCreateBy(SecurityUtils.getUsername());
+        reviewCommentsMapper.insertReviewComments(reviewComments);
+        return AjaxResult.success();
+    }
+
+    /**
+     * 暂缓出具放款合规表-风险使用
+     *
+     * @param loanApplication
+     * @return
+     */
+    @Override
+    public AjaxResult zanHuan(LoanApplication loanApplication) {
+        //删除所有状态小于的待办事项
+        WaitRemind waitRemindDelete = new WaitRemind();
+        waitRemindDelete.setLoanApplicationId(loanApplication.getLoanApplicationId());
+        waitRemindDelete.setReadUserId(loanApplication.getaUserId().toString());
+        waitRemindDelete.setRemindType(EIG);
+        waitRemindMapper.deleteWaitRemindByLoanApplicationId(waitRemindDelete);
+        WaitRemind waitRemind = new WaitRemind();
+        waitRemind.setLoanApplicationId(loanApplication.getLoanApplicationId());
+        waitRemind.setLoanApplicationNumber(loanApplication.getLoanApplicationNumber());
+        waitRemind.setRemindTitle("您有一条风险部暂缓出具【" + loanApplication.getEnterpriseName() + "】放款合规表的申请");
+        waitRemind.setRemindTime(DateUtils.getNowDate());
+        waitRemind.setRemindType(EIG);
+        //给A角色发送待办提醒
+        waitRemind.setReadUserId(loanApplication.getaUserId().toString());
+        //getRemark()风险部暂缓出具的原因
+        waitRemind.setRemindContent(loanApplication.getRemark());
+        waitRemindMapper.insertWaitRemind(waitRemind);
+        //给管理员发送 = 查询所有role_key等于manager的账号
+        List<SysUserRole> sysUserRoles = sysUserRoleMapper.selectRoleListNoDataScope();
+        if (sysUserRoles != null && sysUserRoles.size() > 0) {
+            for (SysUserRole sysUserRole : sysUserRoles) {
+                //删除所有状态小于的待办事项
+                waitRemindDelete.setLoanApplicationId(loanApplication.getLoanApplicationId());
+                waitRemindDelete.setReadUserId(sysUserRole.getUserId().toString());
+                waitRemindDelete.setRemindType(EIG);
+                waitRemindMapper.deleteWaitRemindByLoanApplicationId(waitRemindDelete);
+                WaitRemind waitRemindRole = new WaitRemind();
+                waitRemindRole.setLoanApplicationId(loanApplication.getLoanApplicationId());
+                waitRemindRole.setLoanApplicationNumber(loanApplication.getLoanApplicationNumber());
+                waitRemindRole.setRemindTitle("您有一条风险部暂缓出具【" + loanApplication.getEnterpriseName() + "】放款合规表的申请");
+                waitRemindRole.setRemindTime(DateUtils.getNowDate());
+                waitRemindRole.setRemindType(EIG);
+                //给管理员发送待办提醒
+                waitRemindRole.setReadUserId(sysUserRole.getUserId().toString());
+                //getRemark()风险部暂缓出具的原因
+                waitRemindRole.setRemindContent(loanApplication.getRemark());
+                waitRemindMapper.insertWaitRemind(waitRemindRole);
+            }
+            //发极光推送id
+            //获取所有的userid
+            List<Long> userIdList = sysUserRoles.stream().map(SysUserRole::getUserId).collect(Collectors.toList());
+            userIdList.add(loanApplication.getaUserId());
+            List<SysUser> sysUsers = sysUserService.selectUserListByIdList(userIdList);
+            if (sysUsers != null && sysUsers.size() > 0) {
+                String notificationTitle = "消息通知";
+                String msgTitle = "放款合规表的申请";
+                String msgContent = "您有一条风险部暂缓出具【" + loanApplication.getEnterpriseName() + "】放款合规表的申请";
+                String jPushVO = "";
+                List<String> listS = sysUsers.stream().map(SysUser::getJgId).collect(Collectors.toList());
+                listS.removeAll(Collections.singleton(null));
+                if (listS != null && listS.size() > 0) {
+                    String[] registrationId = listS.toArray(new String[listS.size()]);
+                    JPushToolUtil.sendToRegistrationId(notificationTitle, msgTitle, msgContent, jPushVO, registrationId);
+                }
+            }
+
+        }
+        return AjaxResult.success();
+    }
+
+    /**
+     * 管理员授权A角色开具放款通知书
+     */
+    @Override
+    public AjaxResult authorize(LoanApplication loanApplication) {
+        loanApplication.setLoanSchedule(NIN);
+        loanApplication.setaAuthorize(Y);
+        loanApplicationMapper.updateLoanApplication(loanApplication);
+        return AjaxResult.success();
+    }
+
+    /**
+     * 压缩文件,返回地址
+     *
+     * @param fileList    源文件或目录路径
+     * @param zipPathDir  ZIP文件输出路径
+     * @param zipFileName ZIP文件名称
+     * @param password    加密密码
+     * @return
+     */
+    public void zipEncryptExample(List<File> fileList, String zipPathDir, String zipFileName, String password) {
+        String zipFilePath = zipPathDir + "/" + zipFileName;
+        ZipOutputStream out = null;
+        BufferedOutputStream bo = null;
+        try {
+            out = new ZipOutputStream(new FileOutputStream(zipFilePath));
+
+            bo = new BufferedOutputStream(out);
+            for (File file : fileList) {
+                if (file.exists()) {
+                    ZipEntry zipEntry = new ZipEntry(file.getName());
+
+                    out.putNextEntry(zipEntry);
+
+                    FileInputStream in = new FileInputStream(file);
+
+                    BufferedInputStream bi = new BufferedInputStream(in);
+                    int b;
+                    while ((b = bi.read()) != -1) {
+                        bo.write(b);
+                    }
+                    bo.flush();
+                    bi.close();
+                    in.close();
+                }
+            }
+            bo.close();
+            out.close();
+            System.out.println("文件保存位置:" + zipFilePath);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 导出模板附件
+     */
+    @Override
+    public AjaxResult exportMb(LoanApplication loanApplication) {
+        Map<String, Object> map = new HashMap<>();
+        //导出的附件
+        String type = loanApplication.getType();
+        //附件小类
+        String fileType = loanApplication.getFileType();
+        //附件大类
+        String bigType = loanApplication.getBigType();
+        if (loanApplication.getLoanApplicationId() != null && loanApplication.getLoanApplicationId() != 0L) {
+            loanApplication = loanApplicationMapper.selectLoanApplicationByLoanApplicationId(loanApplication.getLoanApplicationId());
+            loanApplication.setType(type);
+            //判断附件存不存在
+            LoanApplicationFj loanApplicationFj = new LoanApplicationFj();
+            loanApplicationFj.setLoanApplicationId(loanApplication.getLoanApplicationId());
+            loanApplicationFj.setType(fileType);
+            List<LoanApplicationFj> loanApplicationFjs = loanApplicationFjMapper.selectLoanApplicationFjList(loanApplicationFj);
+            if (loanApplicationFjs != null && loanApplicationFjs.size() > 0) {
+                for (LoanApplicationFj applicationFj : loanApplicationFjs) {
+                    redisCache.setCacheObject(applicationFj.getFjId() + "info", applicationFj, 2, TimeUnit.HOURS);
+                    map.put("fileId", applicationFj.getFjId());
+                    map.put("path", applicationFj.getUrl());
+                    map.put("fileName", applicationFj.getName());
+                    return AjaxResult.success(map);
+                }
+            }
+        }
+        String loanApplicationNumber = loanApplication.getLoanApplicationNumber();
+        // 向word中添加数据
+        Map<String, Object> params = new HashMap<>();
+        // 向列表中添加数据
+        Map<String, Object> excelMap = new HashMap<>();
+        //获取当前年、月、日
+        String year = DateUtils.getYear();
+        String month = DateUtils.getMonth();
+        String day = DateUtils.getDay();
+        params.put("year", year);
+        params.put("month", month);
+        params.put("day", day);
+
+        String path = "/profile/mb/temporarily/" + loanApplicationNumber;
+        //查询公司信息
+        SysUserEnterprise sysUserEnterprise = sysUserEnterpriseMapper.selectSysUserEnterpriseByEnterpriseId(loanApplication.getEnterpriseId());
+        params.put("loanApplication", loanApplication);
+        params.put("sysUserEnterprise", sysUserEnterprise);
+        //查询银行名称
+        String backName = dictDataMapper.selectDictLabel("shendai_bank", loanApplication.getApplicationBank());
+        params.put("backName", backName);
+        //将贷款金额转成中文
+        String chineseNum = loanApplication.getLoanApplicationNumber();
+        if (StringUtils.isNumeric(loanApplication.getLoanApplicationNumber())) {
+            chineseNum = StringUtils.convert(Integer.parseInt(loanApplication.getLoanApplicationNumber()));
+        }
+        params.put("chineseNum", chineseNum);
+
+        String templatePath = RuoYiConfig.getProfile();
+        String fileDir = RuoYiConfig.getProfile();
+        String fileName = "";
+        String fileNameHz = "";
+        String wordPath = "";
+        String sheet = "";
+        //生成二维码
+        String ewmPath = RuoYiConfig.getProfile() + "/mb/ewm";
+        JSONObject json = new JSONObject();
+        json.put("type", "2");
+        json.put("loanApplicationNumber", loanApplication.getLoanApplicationNumber());
+        json.put("bigType", bigType);
+        json.put("fileType", fileType);
+        String imagePath = null;
+        try {
+            imagePath = QRCodeUtils.encodeNodate(json.toString(), null, ewmPath, true);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        if (StringUtils.isNotEmpty(imagePath)) {
+            PictureRenderData picture = Pictures.ofLocal(imagePath).size(70, 70).create();//本地图片地址
+            params.put("signPicture", picture);
+        }
+
+        SysUserConference userConference = new SysUserConference();
+
+        LoanApplicationFj loanApplicationFjTzs = new LoanApplicationFj();
+
+        // 创建一个列表,用来存储要填充到Excel中的数据
+        List<Map<String, Object>> list = new ArrayList<>();
+        switch (type) {
+            case "1":
+                //params.put("enterpriseName", loanApplication.getEnterpriseName());
+                //path = path + "/委托担保申请书.doc";
+                templatePath = RuoYiConfig.getProfile() + "/mb/委托担保申请书.docx";
+                fileDir = RuoYiConfig.getProfile() + "/mb/temporarily/" + loanApplicationNumber;
+                //fileName = FileUploadUtils.extractFilenameLoanApplicationNumberNoHzm("委托担保申请书");
+                fileName = loanApplication.getEnterpriseName() + "-委托担保申请书";
+                fileNameHz = fileName + ".docx";
+                wordPath = WordUtil.createWord(templatePath, fileDir, fileName, params);
+                path = path + "/" + fileName + ".docx";
+                break;
+            case "2":
+                params.put("enterpriseAddres", sysUserEnterprise.getEnterpriseAddress());
+                params.put("corporationPhone", loanApplication.getCorporationPhone());
+                //path = path + "/委托担保申请书.doc";
+                templatePath = RuoYiConfig.getProfile() + "/mb/委托保证合同.docx";
+                fileDir = RuoYiConfig.getProfile() + "/mb/temporarily/" + loanApplicationNumber;
+                //fileName = FileUploadUtils.extractFilenameLoanApplicationNumberNoHzm("委托担保申请书");
+                fileName = loanApplication.getEnterpriseName() + "-委托担保申请书";
+                fileNameHz = fileName + ".docx";
+                wordPath = WordUtil.createWord(templatePath, fileDir, fileName, params);
+                path = path + "/" + fileName + ".docx";
+                break;
+            case "3":
+                //params.put("enterpriseName", loanApplication.getEnterpriseName());
+                //path = path + "/委托担保申请书.doc";
+                templatePath = templatePath + "/mb/担保意向函.docx";
+                fileDir = fileDir + "/mb/temporarily/" + loanApplicationNumber;
+                //fileName = FileUploadUtils.extractFilenameLoanApplicationNumberNoHzm("担保意向函");
+                fileName = loanApplication.getEnterpriseName() + "-担保意向函";
+                fileNameHz = fileName + ".docx";
+                wordPath = WordUtil.createWord(templatePath, fileDir, fileName, params);
+                path = path + "/" + fileName + ".docx";
+                break;
+            case "4":
+                //查询借据附件
+                loanApplicationFjTzs.setLoanApplicationId(loanApplication.getLoanApplicationId());
+                loanApplicationFjTzs.setType("jj");
+                List<LoanApplicationFj> loanApplicationFjs = loanApplicationFjMapper.selectLoanApplicationFjList(loanApplicationFjTzs);
+                if (loanApplicationFjs != null && loanApplicationFjs.size() > 0) {
+                    loanApplicationFjTzs = loanApplicationFjs.get(0);
+                }
+
+                //查询最新的一条投票数据
+                userConference = sysUserConferenceMapper.selectSysUserConferenceNew(loanApplication.getLoanApplicationId());
+                //将贷款金额转成中文
+                if (ObjectUtils.isNotEmpty(userConference.getLineGuarantee())) {
+                    chineseNum = userConference.getLineGuarantee();
+                }
+                params.put("chineseNum", chineseNum);
+                if (StringUtils.isNotEmpty(loanApplicationFjTzs.getUrl())) {
+                    // 上传文件路径
+                    String filePath = RuoYiConfig.getUploadPath();
+                    //服务器路径
+                    String urlOnline = filePath + loanApplicationFjTzs.getUrl().replace("/profile/upload", "");
+                    //百度图片识别
+                    Map<String, Object> imgMap = IdCardUtil.accurateBasicCj(urlOnline);
+                    if (map != null || map.size() != 0) {
+                        params.put("dkdw", imgMap.get("dkdw"));
+                        params.put("jkr", imgMap.get("jkr"));
+                        //params.put("jkje", imgMap.get("jkje"));
+                        params.put("jkytsm", imgMap.get("jkytsm"));
+                        params.put("hksj", imgMap.get("hksj"));
+                    }
+                }
+
+                //params.put("enterpriseName", loanApplication.getEnterpriseName());
+                //path = path + "/委托担保申请书.doc";
+                templatePath = RuoYiConfig.getProfile() + "/mb/放款(出票)通知书.docx";
+                fileDir = RuoYiConfig.getProfile() + "/mb/temporarily/" + loanApplicationNumber;
+                //fileName = FileUploadUtils.extractFilenameLoanApplicationNumberNoHzm("放款(出票)通知书");
+                fileName = loanApplication.getEnterpriseName() + "-放款(出票)通知书";
+                fileNameHz = fileName + ".docx";
+                wordPath = WordUtil.createWord(templatePath, fileDir, fileName, params);
+                path = path + "/" + fileName + ".docx";
+                break;
+            case "5":
+                //params.put("enterpriseName", loanApplication.getEnterpriseName());
+                //path = path + "/委托担保申请书.doc";
+                templatePath = RuoYiConfig.getProfile() + "/mb/保证反担保合同(适用于法人).docx";
+                fileDir = RuoYiConfig.getProfile() + "/mb/temporarily/" + loanApplicationNumber;
+                //fileName = FileUploadUtils.extractFilenameLoanApplicationNumberNoHzm("保证反担保合同(适用于法人)");
+                fileName = loanApplication.getEnterpriseName() + "-保证反担保合同(适用于法人)";
+                fileNameHz = fileName + ".docx";
+                wordPath = WordUtil.createWord(templatePath, fileDir, fileName, params);
+                path = path + "/" + fileName + ".docx";
+                break;
+            case "6":
+                //params.put("enterpriseName", loanApplication.getEnterpriseName());
+                //path = path + "/委托担保申请书.doc";
+                templatePath = RuoYiConfig.getProfile() + "/mb/保证反担保合同(适用于自然人).docx";
+                fileDir = RuoYiConfig.getProfile() + "/mb/temporarily/" + loanApplicationNumber;
+                //fileName = FileUploadUtils.extractFilenameLoanApplicationNumberNoHzm("保证反担保合同(适用于自然人)");
+                fileName = loanApplication.getEnterpriseName() + "-保证反担保合同(适用于自然人)";
+                fileNameHz = fileName + ".docx";
+                wordPath = WordUtil.createWord(templatePath, fileDir, fileName, params);
+                path = path + "/" + fileName + ".docx";
+                break;
+            case "7":
+                //params.put("enterpriseName", loanApplication.getEnterpriseName());
+                //path = path + "/委托担保申请书.doc";
+                templatePath = RuoYiConfig.getProfile() + "/mb/抵押反担保合同(适用于法人).docx";
+                fileDir = RuoYiConfig.getProfile() + "/mb/temporarily/" + loanApplicationNumber;
+                //fileName = FileUploadUtils.extractFilenameLoanApplicationNumberNoHzm("抵押反担保合同(适用于法人)");
+                fileName = loanApplication.getEnterpriseName() + "-抵押反担保合同(适用于法人)";
+                fileNameHz = fileName + ".docx";
+                wordPath = WordUtil.createWord(templatePath, fileDir, fileName, params);
+                path = path + "/" + fileName + ".docx";
+                break;
+            case "8":
+                //params.put("enterpriseName", loanApplication.getEnterpriseName());
+                //path = path + "/委托担保申请书.doc";
+                templatePath = RuoYiConfig.getProfile() + "/mb/抵押反担保合同(适用于自然人).docx";
+                fileDir = RuoYiConfig.getProfile() + "/mb/temporarily/" + loanApplicationNumber;
+                //fileName = FileUploadUtils.extractFilenameLoanApplicationNumberNoHzm("抵押反担保合同(适用于自然人)");
+                fileName = loanApplication.getEnterpriseName() + "-抵押反担保合同(适用于自然人)";
+                fileNameHz = fileName + ".docx";
+                wordPath = WordUtil.createWord(templatePath, fileDir, fileName, params);
+                path = path + "/" + fileName + ".docx";
+                break;
+            case "9":
+                //params.put("enterpriseName", loanApplication.getEnterpriseName());
+                //path = path + "/委托担保申请书.doc";
+                templatePath = RuoYiConfig.getProfile() + "/mb/权利质权反担保合同(适用于法人).docx";
+                fileDir = RuoYiConfig.getProfile() + "/mb/temporarily/" + loanApplicationNumber;
+                //fileName = FileUploadUtils.extractFilenameLoanApplicationNumberNoHzm("权利质权反担保合同(适用于法人)");
+                fileName = loanApplication.getEnterpriseName() + "-权利质权反担保合同(适用于法人)";
+                fileNameHz = fileName + ".docx";
+                wordPath = WordUtil.createWord(templatePath, fileDir, fileName, params);
+                path = path + "/" + fileName + ".docx";
+                break;
+            case "10":
+                //params.put("enterpriseName", loanApplication.getEnterpriseName());
+                //path = path + "/委托担保申请书.doc";
+                templatePath = RuoYiConfig.getProfile() + "/mb/权利质权反担保合同(适用于自然人).docx";
+                fileDir = RuoYiConfig.getProfile() + "/mb/temporarily/" + loanApplicationNumber;
+                //fileName = FileUploadUtils.extractFilenameLoanApplicationNumberNoHzm("权利质权反担保合同(适用于自然人)");
+                fileName = loanApplication.getEnterpriseName() + "-权利质权反担保合同(适用于自然人)";
+                fileNameHz = fileName + ".docx";
+                wordPath = WordUtil.createWord(templatePath, fileDir, fileName, params);
+                path = path + "/" + fileName + ".docx";
+                break;
+            case "11":
+                //判断有多少公司  股东、反担保人
+
+                params.put("gsName", loanApplication.getEnterpriseName());
+                params.put("bgs", "本公司");
+                //params.put("enterpriseName", loanApplication.getEnterpriseName());
+                //path = path + "/委托担保申请书.doc";
+                templatePath = RuoYiConfig.getProfile() + "/mb/股东会决议.docx";
+                fileDir = RuoYiConfig.getProfile() + "/mb/temporarily/" + loanApplicationNumber;
+                //fileName = FileUploadUtils.extractFilenameLoanApplicationNumberNoHzm("股东会决议");
+                fileName = loanApplication.getEnterpriseName() + "-股东会决议";
+                fileNameHz = fileName + ".docx";
+                wordPath = WordUtil.createWord(templatePath, fileDir, fileName, params);
+                path = path + "/" + fileName + ".docx";
+
+                //生成股东公司的股东会决议
+                ShareholderFj shareholderFj = new ShareholderFj();
+                shareholderFj.setLoanApplicationId(loanApplication.getLoanApplicationId());
+                List<ShareholderFj> shareholderFjs = shareholderFjMapper.selectShareholderFjList(shareholderFj);
+                int index = 1;
+                if (shareholderFjs != null && shareholderFjs.size() > 0) {
+                    for (ShareholderFj fj : shareholderFjs) {
+                        if (StringUtils.isNotEmpty(fj.getShareholderBusinessUrl())) {
+                            String shareholderName = "";
+                            if(StringUtils.isNotEmpty(fj.getShareholderName()) && !StringUtils.equals("null",fj.getShareholderName())){
+                                shareholderName = fj.getShareholderName();
+                            }
+                            params.put("gsName", shareholderName);
+                            params.put("bgs", loanApplication.getEnterpriseName());
+
+                            String fileDirg = RuoYiConfig.getProfile() + "/upload/" + loanApplicationNumber;
+                            //fileName = FileUploadUtils.extractFilenameLoanApplicationNumberNoHzm("股东会决议");
+                            String fileNameg = shareholderName + "-股东会决议" + index;
+                            //fileNameHz = fileName + ".docx";
+                            wordPath = WordUtil.createWord(templatePath, fileDirg, fileNameg, params);
+                            //将文件存入loan_application_fj表
+                            LoanApplicationFj loanApplicationFj = new LoanApplicationFj();
+                            loanApplicationFj.setLoanApplicationId(loanApplication.getLoanApplicationId());
+                            loanApplicationFj.setLoanApplicationNumber(loanApplication.getLoanApplicationNumber());
+                            loanApplicationFj.setOldName(fileNameg + ".docx");
+                            loanApplicationFj.setName(fileNameg + ".docx");
+                            loanApplicationFj.setUrl(Constants.RESOURCE_PREFIX + "/upload/" + loanApplicationNumber + "/" + fileNameg + ".docx");
+                            loanApplicationFj.setBigType(bigType);
+                            loanApplicationFj.setType(fileType);
+                            loanApplicationFj.setCreateTime(DateUtils.getNowDate());
+                            loanApplicationFjMapper.insertLoanApplicationFj(loanApplicationFj);
+                            index++;
+                        }
+                    }
+
+                }
+                //生成反担保公司的股东会决议
+                GuaranteeInfo guaranteeInfo = new GuaranteeInfo();
+                guaranteeInfo.setLoanApplicationId(loanApplication.getLoanApplicationId());
+                guaranteeInfo.setType("2");
+                List<GuaranteeInfo> guaranteeInfos = guaranteeInfoMapper.selectGuaranteeInfoList(guaranteeInfo);
+                if (guaranteeInfos != null && guaranteeInfos.size() > 0) {
+                    for (GuaranteeInfo info : guaranteeInfos) {
+                        String guaranteeName = "";
+                        if(StringUtils.isNotEmpty(info.getGuaranteeName()) && !StringUtils.equals("null",info.getGuaranteeName()) ){
+                            guaranteeName = info.getGuaranteeName();
+                        }
+                        params.put("gsName", guaranteeName);
+                        params.put("bgs", loanApplication.getEnterpriseName());
+
+                        String fileDirf = RuoYiConfig.getProfile() + "/upload/" + loanApplicationNumber;
+                        //fileName = FileUploadUtils.extractFilenameLoanApplicationNumberNoHzm("股东会决议");
+                        String fileNamef = guaranteeName + "-股东会决议" + index;
+                        //fileNameHz = fileName + ".docx";
+                        wordPath = WordUtil.createWord(templatePath, fileDirf, fileNamef, params);
+                        //将文件存入loan_application_fj表
+                        LoanApplicationFj loanApplicationFj = new LoanApplicationFj();
+                        loanApplicationFj.setLoanApplicationId(loanApplication.getLoanApplicationId());
+                        loanApplicationFj.setLoanApplicationNumber(loanApplication.getLoanApplicationNumber());
+                        loanApplicationFj.setOldName(fileNamef + ".docx");
+                        loanApplicationFj.setName(fileNamef + ".docx");
+                        loanApplicationFj.setUrl(Constants.RESOURCE_PREFIX + "/upload/" + loanApplicationNumber + "/" + fileNamef + ".docx");
+                        loanApplicationFj.setBigType(bigType);
+                        loanApplicationFj.setType(fileType);
+                        loanApplicationFj.setCreateTime(DateUtils.getNowDate());
+                        loanApplicationFjMapper.insertLoanApplicationFj(loanApplicationFj);
+                        index++;
+                    }
+
+                }
+
+                break;
+            case "12":
+
+                //申请人名称
+                excelMap.put("sqr", loanApplication.getEnterpriseName() + "   " + loanApplication.getCorporationName());
+                //公司住址
+                excelMap.put("address", sysUserEnterprise.getEnterpriseAddress());
+                //家庭住址
+                excelMap.put("fraddress", loanApplication.getCorporationAddress());
+                //申请金额
+                excelMap.put("sqje", loanApplication.getApplicationAmount());
+                //申请期限
+                excelMap.put("sqqx", loanApplication.getUsagePeriod());
+                //申请银行
+                excelMap.put("bank", loanApplication.getApplicationBank());
+                //还款方式
+                excelMap.put("hkfs", loanApplication.getRepaymentSource());
+                //参会日期
+                String timeData = loanApplication.getReviewTime().split(" ")[0];
+                String[] split = timeData.split("-");
+                excelMap.put("year", split[0]);
+                excelMap.put("month", split[1]);
+                excelMap.put("day", split[2]);
+                //查询投票信息
+                excelMap.put("ty", "");
+                excelMap.put("fj", "");
+                excelMap.put("qx", "");
+                int ty = 0;
+                int fj = 0;
+                int qx = 0;
+
+                userConference.setConferenceTime(loanApplication.getReviewTime());
+                userConference.setLoanApplicationId(loanApplication.getLoanApplicationId());
+                List<SysUserConference> userConferences = sysUserConferenceMapper.selectSysUserConferenceList(userConference);
+                if (userConferences != null && userConferences.size() > 0) {
+                    for (SysUserConference conference : userConferences) {
+                        if ("Y".equals(conference.getVotingResult())) {
+                            ty++;
+                        } else if ("N".equals(conference.getVotingResult())) {
+                            fj++;
+                        } else {
+                            qx++;
+                        }
+                    }
+                    excelMap.put("ty", ty);
+                    excelMap.put("fj", fj);
+                    excelMap.put("qx", qx);
+                }
+                //贷款金额
+                excelMap.put("je", loanApplication.getActuallyAmount());
+                //贷款期限
+                list.add(excelMap);
+                //fileName = FileUploadUtils.extractFilenameLoanApplicationNumberNoHzm("项目评审意见签批表");
+                fileName = loanApplication.getEnterpriseName() + "-项目评审意见签批表";
+                fileNameHz = fileName + ".xlsx";
+                templatePath = RuoYiConfig.getProfile() + "/mb/项目评审意见签批表.xlsx";
+                fileDir = RuoYiConfig.getProfile() + "/mb/temporarily/" + loanApplicationNumber + "/" + fileNameHz;
+                sheet = ExcelFillUtils.fillOneSheet(templatePath, fileDir, "Sheet1", list);
+
+                path = path + "/" + fileNameHz;
+                break;
+            case "13":
+                //params.put("enterpriseName", loanApplication.getEnterpriseName());
+                //path = path + "/委托担保申请书.doc";
+                templatePath = RuoYiConfig.getProfile() + "/mb/担保项目合法合规表企业.xlsx";
+                //fileName = FileUploadUtils.extractFilenameLoanApplicationNumberNoHzm("担保项目合法合规表企业");
+                fileName = loanApplication.getEnterpriseName() + "-担保项目合法合规表企业";
+                if ("2".equals(loanApplication.getApplicationType())) {
+                    templatePath = RuoYiConfig.getProfile() + "/mb/担保项目合法合规表个人个体户.xlsx";
+                    //fileName = FileUploadUtils.extractFilenameLoanApplicationNumberNoHzm("担保项目合法合规表个人个体户");
+                    fileName = loanApplication.getEnterpriseName() + "-担保项目合法合规表个人个体户";
+                }
+                fileNameHz = fileName + ".xlsx";
+                fileDir = RuoYiConfig.getProfile() + "/mb/temporarily/" + loanApplicationNumber + "/" + fileNameHz;
+                sheet = ExcelFillUtils.fillOneSheet(templatePath, fileDir, "Sheet1", list);
+                path = path + "/" + fileNameHz;
+                break;
+            case "14":
+                //params.put("enterpriseName", loanApplication.getEnterpriseName());
+                //path = path + "/委托担保申请书.doc";
+                templatePath = RuoYiConfig.getProfile() + "/mb/放款审批合规表企业.xlsx";
+                //fileName = FileUploadUtils.extractFilenameLoanApplicationNumberNoHzm("放款审批合规表企业");
+                fileName = loanApplication.getEnterpriseName() + "-放款审批合规表企业";
+                if ("2".equals(loanApplication.getApplicationType())) {
+                    templatePath = RuoYiConfig.getProfile() + "/mb/放款审批合规表个人个体户.xlsx";
+                    //fileName = FileUploadUtils.extractFilenameLoanApplicationNumberNoHzm("放款审批合规表个人个体户");
+                    fileName = loanApplication.getEnterpriseName() + "-放款审批合规表个人个体户";
+                }
+                fileNameHz = fileName + ".xlsx";
+                fileDir = RuoYiConfig.getProfile() + "/mb/temporarily/" + loanApplicationNumber + "/" + fileNameHz;
+                sheet = ExcelFillUtils.fillOneSheet(templatePath, fileDir, "Sheet1", list);
+                path = path + "/" + fileNameHz;
+                break;
+            case "15":
+                //查询评审人员信息
+                //查询所有人员的投票结果
+                SysUserConference sysUserConference = new SysUserConference();
+                sysUserConference.setLoanApplicationId(loanApplication.getLoanApplicationId());
+                sysUserConference.setConferenceTime(loanApplication.getReviewTime());
+                List<SysUserConference> sysUserConferences = sysUserConferenceMapper.selectSysUserConferenceList(sysUserConference);
+                //拼接姓名
+                StringBuilder sb = new StringBuilder();
+                for (SysUserConference userConference1 : sysUserConferences) {
+                    if (sb.length() > 0) {
+                        sb.append("  ").append(userConference1.getRealName());
+                    } else {
+                        sb.append(userConference1.getRealName());
+                    }
+
+                }
+                //评审会时间
+                params.put("time", loanApplication.getReviewTime());
+                //评审会公司
+                params.put("enterpriseName", loanApplication.getEnterpriseName());
+                //评审会人员
+                params.put("user", sb.toString());
+                //path = path + "/委托担保申请书.doc";
+                templatePath = templatePath + "/mb/评审会通知.docx";
+                fileDir = fileDir + "/mb/temporarily/" + loanApplicationNumber;
+                //fileName = FileUploadUtils.extractFilenameLoanApplicationNumberNoHzm("担保意向函");
+                fileName = loanApplication.getEnterpriseName() + "-评审会通知";
+                fileNameHz = fileName + ".docx";
+                wordPath = WordUtil.createWord(templatePath, fileDir, fileName, params);
+                path = path + "/" + fileName + ".docx";
+                break;
+            case "16":
+                //params.put("enterpriseName", loanApplication.getEnterpriseName());
+                //path = path + "/委托担保申请书.doc";
+                templatePath = RuoYiConfig.getProfile() + "/mb/不可撤销个人连带责任信用反担保合同.docx";
+                fileDir = RuoYiConfig.getProfile() + "/mb/temporarily/" + loanApplicationNumber;
+                //fileName = FileUploadUtils.extractFilenameLoanApplicationNumberNoHzm("委托担保申请书");
+                fileName = loanApplication.getEnterpriseName() + "-不可撤销个人连带责任信用反担保合同";
+                fileNameHz = fileName + ".docx";
+                wordPath = WordUtil.createWord(templatePath, fileDir, fileName, params);
+                path = path + "/" + fileName + ".docx";
+                break;
+            case "17":
+                //params.put("enterpriseName", loanApplication.getEnterpriseName());
+                //path = path + "/委托担保申请书.doc";
+                templatePath = RuoYiConfig.getProfile() + "/mb/委托保证合同(工程履约).docx";
+                fileDir = RuoYiConfig.getProfile() + "/mb/temporarily/" + loanApplicationNumber;
+                //fileName = FileUploadUtils.extractFilenameLoanApplicationNumberNoHzm("委托担保申请书");
+                fileName = loanApplication.getEnterpriseName() + "-委托保证合同(工程履约)";
+                fileNameHz = fileName + ".docx";
+                wordPath = WordUtil.createWord(templatePath, fileDir, fileName, params);
+                path = path + "/" + fileName + ".docx";
+                break;
+            case "18":
+                //params.put("enterpriseName", loanApplication.getEnterpriseName());
+                //path = path + "/委托担保申请书.doc";
+                templatePath = RuoYiConfig.getProfile() + "/mb/企业信用反担保合同.docx";
+                fileDir = RuoYiConfig.getProfile() + "/mb/temporarily/" + loanApplicationNumber;
+                //fileName = FileUploadUtils.extractFilenameLoanApplicationNumberNoHzm("委托担保申请书");
+                fileName = loanApplication.getEnterpriseName() + "-企业信用反担保合同";
+                fileNameHz = fileName + ".docx";
+                wordPath = WordUtil.createWord(templatePath, fileDir, fileName, params);
+                path = path + "/" + fileName + ".docx";
+                break;
+            case "19":
+                //申请人名称
+                excelMap.put("sqr", loanApplication.getEnterpriseName());
+                //申请金额
+                excelMap.put("sqje", loanApplication.getActuallyAmount());
+                //申请期限
+                excelMap.put("sqqx", loanApplication.getUsagePeriod());
+                //申请银行
+                excelMap.put("bank", loanApplication.getApplicationBank());
+                list.add(excelMap);
+                //fileName = FileUploadUtils.extractFilenameLoanApplicationNumberNoHzm("项目评审意见签批表");
+                fileName = loanApplication.getEnterpriseName() + "-t+1保后首次检查报告";
+                fileNameHz = fileName + ".xlsx";
+                templatePath = RuoYiConfig.getProfile() + "/mb/t+1保后首次检查报告.xlsx";
+                fileDir = RuoYiConfig.getProfile() + "/mb/temporarily/" + loanApplicationNumber + "/" + fileNameHz;
+                sheet = ExcelFillUtils.fillOneSheet(templatePath, fileDir, "Sheet1", list);
+
+                path = path + "/" + fileNameHz;
+                break;
+            case "20":
+                //申请人名称
+                excelMap.put("sqr", loanApplication.getEnterpriseName());
+                //申请金额
+                excelMap.put("sqje", loanApplication.getActuallyAmount());
+                //申请期限
+                excelMap.put("sqqx", loanApplication.getUsagePeriod());
+                //申请银行
+                excelMap.put("bank", loanApplication.getApplicationBank());
+                list.add(excelMap);
+                //fileName = FileUploadUtils.extractFilenameLoanApplicationNumberNoHzm("项目评审意见签批表");
+                fileName = loanApplication.getEnterpriseName() + "-T+N保后检查报告";
+                fileNameHz = fileName + ".xlsx";
+                templatePath = RuoYiConfig.getProfile() + "/mb/T+N保后检查报告.xlsx";
+                fileDir = RuoYiConfig.getProfile() + "/mb/temporarily/" + loanApplicationNumber + "/" + fileNameHz;
+                sheet = ExcelFillUtils.fillOneSheet(templatePath, fileDir, "Sheet1", list);
+
+                path = path + "/" + fileNameHz;
+                break;
+            //todo  担保业务备案表
+            case "21":
+
+                //分支行
+                excelMap.put("fzh", "");
+                //总行
+                excelMap.put("zh", "");
+                //起始日期
+                excelMap.put("qsrq", "");
+                //到期日期
+                excelMap.put("dqrq", "");
+                //贷款利率
+                excelMap.put("dklv", "");
+                //所属行业
+                excelMap.put("sshy", "");
+                excelMap.put("zzqje", "");
+
+                //查询借据附件
+                loanApplicationFjTzs.setLoanApplicationId(loanApplication.getLoanApplicationId());
+                loanApplicationFjTzs.setType("jj");
+                List<LoanApplicationFj> loanApplicationFjList = loanApplicationFjMapper.selectLoanApplicationFjList(loanApplicationFjTzs);
+                if (loanApplicationFjList != null && loanApplicationFjList.size() > 0) {
+                    loanApplicationFjTzs = loanApplicationFjList.get(0);
+                }
+
+                if (StringUtils.isNotEmpty(loanApplicationFjTzs.getUrl())) {
+                    // 上传文件路径
+                    String filePath = RuoYiConfig.getUploadPath();
+                    //服务器路径
+                    String urlOnline = filePath + loanApplicationFjTzs.getUrl().replace("/profile/upload", "");
+                    //百度图片识别
+                    Map<String, Object> imgMap = IdCardUtil.accurateBasicCj(urlOnline);
+                    if (map != null || map.size() != 0) {
+
+                        //分支行
+                        excelMap.put("fzh", imgMap.get("dkdw"));
+                        //总行
+                        excelMap.put("zh", imgMap.get("zh"));
+                        //起始日期
+                        excelMap.put("qsrq", imgMap.get("qxr"));
+                        //到期日期
+                        excelMap.put("dqrq", imgMap.get("dqr"));
+                        //贷款利率
+                        excelMap.put("dklv", imgMap.get("dklv"));
+                    }
+                }
+
+                //所属行业
+                excelMap.put("sshy", loanApplication.getCategoryType());
+                //主债权金额
+                //查询最新的一条投票数据
+                userConference = sysUserConferenceMapper.selectSysUserConferenceNew(loanApplication.getLoanApplicationId());
+
+                excelMap.put("zzqje", userConference.getLineGuarantee());
+                //债务人名称
+                excelMap.put("zwrmc", loanApplication.getEnterpriseName());
+                //法定代表人姓名
+                excelMap.put("fddbrxm", loanApplication.getCorporationName());
+                //法定代表人证件号码
+                excelMap.put("fddbrzjhm", loanApplication.getCorporationIdCard());
+
+
+                list.add(excelMap);
+                //fileName = FileUploadUtils.extractFilenameLoanApplicationNumberNoHzm("项目评审意见签批表");
+                fileName = loanApplication.getEnterpriseName() + "-担保业务备案表";
+                fileNameHz = fileName + ".xlsx";
+                templatePath = RuoYiConfig.getProfile() + "/mb/担保业务备案表.xlsx";
+                fileDir = RuoYiConfig.getProfile() + "/mb/temporarily/" + loanApplicationNumber + "/" + fileNameHz;
+                sheet = ExcelFillUtils.fillOneSheet(templatePath, fileDir, "Sheet1", list);
+
+                path = path + "/" + fileNameHz;
+                break;
+            default:
+                break;
+        }
+        //删除二维码
+        File file = new File(imagePath);
+        file.delete();
+
+        LoanApplicationFj applicationFj = new LoanApplicationFj();
+        applicationFj.setLoanApplicationId(loanApplication.getLoanApplicationId());
+        applicationFj.setType(fileType);
+        applicationFj.setBigType(bigType);
+        applicationFj.setLoanApplicationNumber(loanApplication.getLoanApplicationNumber());
+        applicationFj.setName(fileNameHz);
+        applicationFj.setUrl(path);
+        String fileId = IdUtils.fastSimpleUUID();
+        redisCache.setCacheObject(fileId + "info", applicationFj, 2, TimeUnit.HOURS);
+        LoanApplicationFj application = redisCache.getCacheObject(fileId + "info");
+
+        map.put("fileId", fileId);
+        map.put("path", path);
+        map.put("fileName", fileNameHz);
+        return AjaxResult.success(map);
+    }
+
+    private String contrastType(String type) {
+        String fileType = "";
+        switch (type) {
+            case "1":
+                fileType = "wtdbsqs";
+                break;
+            case "2":
+                fileType = "wtdbht";
+                break;
+            case "3":
+                fileType = "dbyxh";
+                break;
+            case "4":
+                fileType = "fktzhsh";
+                break;
+            case "5":
+                fileType = "bzfdbhtfr";
+                break;
+            case "6":
+                fileType = "bzfdbhtzrr";
+                break;
+            case "7":
+                fileType = "dyfdbhtfr";
+                break;
+            case "8":
+                fileType = "dyfdbhtzrr";
+                break;
+            case "9":
+                fileType = "27";
+                break;
+            case "10":
+                fileType = "27";
+                break;
+            case "11":
+                fileType = "gdhyjy";
+                break;
+            case "12":
+                fileType = "psyjqpb";
+                break;
+            case "13":
+                fileType = "clhgb";
+                break;
+            default:
+                fileType = "fkhgb";
+                break;
+        }
+        return fileType;
+    }
+
+    /* public static void main(String[] args) {
+
+     *//*File file = new File("D:\\尽职调查报告4.doc");
+        FileInputStream fis = null;
+        XWPFDocument document = null;
+        XWPFWordExtractor extractor = null;
+        try {
+            fis = new FileInputStream(file);
+            document = new XWPFDocument(fis);
+            extractor = new XWPFWordExtractor(document);
+            System.out.println(extractor.getText());
+        } catch (Exception e) {
+            e.printStackTrace();
+        }*//*
+
+        try {
+            FileInputStream fis = new FileInputStream(new File("D:\\尽职调查报告4.doc"));
+            HWPFDocument document = new HWPFDocument(fis);
+            Range range = document.getRange();
+            String text = range.text();
+            System.out.println("11111");
+            System.out.println(range.text());
+            fis.close();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+    }*/
+
+    /*public static void main(String[] args) {
+        String pdfPath = "D:\\240809182122A151.pdf";
+        System.out.println(Text2PdfUtil.readPDF(pdfPath));
+        *//*Map<String, Object> imgMap = IdCardUtil.accurateBasicCj("D:\\240809182122A151.pdf");
+        System.out.println(imgMap.toString());*//*
+    }*/
+
+
+}

+ 62 - 45
ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java

@@ -1,6 +1,8 @@
 package com.ruoyi.framework.web.service;
 
 import javax.annotation.Resource;
+
+import com.ruoyi.common.utils.AesUtil;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.authentication.AuthenticationManager;
 import org.springframework.security.authentication.BadCredentialsException;
@@ -29,14 +31,15 @@ import com.ruoyi.framework.security.context.AuthenticationContextHolder;
 import com.ruoyi.system.service.ISysConfigService;
 import com.ruoyi.system.service.ISysUserService;
 
+import static com.ruoyi.common.constant.CommonConstants.*;
+
 /**
  * 登录校验方法
- * 
+ *
  * @author ruoyi
  */
 @Component
-public class SysLoginService
-{
+public class SysLoginService {
     @Autowired
     private TokenService tokenService;
 
@@ -45,7 +48,7 @@ public class SysLoginService
 
     @Autowired
     private RedisCache redisCache;
-    
+
     @Autowired
     private ISysUserService userService;
 
@@ -54,43 +57,39 @@ public class SysLoginService
 
     /**
      * 登录验证
-     * 
+     *
      * @param username 用户名
      * @param password 密码
-     * @param code 验证码
-     * @param uuid 唯一标识
+     * @param code     验证码
+     * @param uuid     唯一标识
      * @return 结果
      */
-    public String login(String username, String password, String code, String uuid)
-    {
+    public String login(String username, String password, String code, String uuid, String type) {
         // 验证码校验
         validateCaptcha(username, code, uuid);
+        //登录类型校验 如果是短信验证码登录,校验短信验证码是否正确
+        String passwordResult = validateType(username, type, code);
+        if (StringUtils.isNotEmpty(passwordResult)) {
+            password = AesUtil.decryptCBC(passwordResult, LOGIN_PASSWORD_AES);
+        }
         // 登录前置校验
         loginPreCheck(username, password);
         // 用户验证
         Authentication authentication = null;
-        try
-        {
+        try {
             UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password);
             AuthenticationContextHolder.setContext(authenticationToken);
             // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername
             authentication = authenticationManager.authenticate(authenticationToken);
-        }
-        catch (Exception e)
-        {
-            if (e instanceof BadCredentialsException)
-            {
+        } catch (Exception e) {
+            if (e instanceof BadCredentialsException) {
                 AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
                 throw new UserPasswordNotMatchException();
-            }
-            else
-            {
+            } else {
                 AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, e.getMessage()));
                 throw new ServiceException(e.getMessage());
             }
-        }
-        finally
-        {
+        } finally {
             AuthenticationContextHolder.clearContext();
         }
         AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
@@ -102,27 +101,23 @@ public class SysLoginService
 
     /**
      * 校验验证码
-     * 
+     *
      * @param username 用户名
-     * @param code 验证码
-     * @param uuid 唯一标识
+     * @param code     验证码
+     * @param uuid     唯一标识
      * @return 结果
      */
-    public void validateCaptcha(String username, String code, String uuid)
-    {
+    public void validateCaptcha(String username, String code, String uuid) {
         boolean captchaEnabled = configService.selectCaptchaEnabled();
-        if (captchaEnabled)
-        {
+        if (captchaEnabled) {
             String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.nvl(uuid, "");
             String captcha = redisCache.getCacheObject(verifyKey);
             redisCache.deleteObject(verifyKey);
-            if (captcha == null)
-            {
+            if (captcha == null) {
                 AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire")));
                 throw new CaptchaExpireException();
             }
-            if (!code.equalsIgnoreCase(captcha))
-            {
+            if (!code.equalsIgnoreCase(captcha)) {
                 AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error")));
                 throw new CaptchaException();
             }
@@ -131,35 +126,31 @@ public class SysLoginService
 
     /**
      * 登录前置校验
+     *
      * @param username 用户名
      * @param password 用户密码
      */
-    public void loginPreCheck(String username, String password)
-    {
+    public void loginPreCheck(String username, String password) {
         // 用户名或密码为空 错误
-        if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password))
-        {
+        if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {
             AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("not.null")));
             throw new UserNotExistsException();
         }
         // 密码如果不在指定范围内 错误
         if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
-                || password.length() > UserConstants.PASSWORD_MAX_LENGTH)
-        {
+                || password.length() > UserConstants.PASSWORD_MAX_LENGTH) {
             AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
             throw new UserPasswordNotMatchException();
         }
         // 用户名不在指定范围内 错误
         if (username.length() < UserConstants.USERNAME_MIN_LENGTH
-                || username.length() > UserConstants.USERNAME_MAX_LENGTH)
-        {
+                || username.length() > UserConstants.USERNAME_MAX_LENGTH) {
             AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
             throw new UserPasswordNotMatchException();
         }
         // IP黑名单校验
         String blackStr = configService.selectConfigByKey("sys.login.blackIPList");
-        if (IpUtils.isMatchedIp(blackStr, IpUtils.getIpAddr()))
-        {
+        if (IpUtils.isMatchedIp(blackStr, IpUtils.getIpAddr())) {
             AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("login.blocked")));
             throw new BlackListException();
         }
@@ -170,12 +161,38 @@ public class SysLoginService
      *
      * @param userId 用户ID
      */
-    public void recordLoginInfo(Long userId)
-    {
+    public void recordLoginInfo(Long userId) {
         SysUser sysUser = new SysUser();
         sysUser.setUserId(userId);
         sysUser.setLoginIp(IpUtils.getIpAddr());
         sysUser.setLoginDate(DateUtils.getNowDate());
         userService.updateUserProfile(sysUser);
     }
+
+    /**
+     * 登录类型校验 如果是短信验证码登录,校验短信验证码是否正确,给密码 查询用户信息后赋值
+     *
+     * @param username 用户名
+     * @param type     登录类型
+     * @param code     短信验证码
+     */
+    public String validateType(String username, String type, String code) {
+        String password = null;
+        if (TWO.equals(type)) {
+            //校验短信验证码
+            Object cacheObject = redisCache.getCacheObject(LOGIN_USER_SMS + username);
+            if (code.equals(cacheObject)) {
+                //根据手机号查询用户信息
+                SysUser sysUser = userService.selectUserByPhonenumber(username);
+                if (sysUser == null) {
+                    throw new UserPasswordNotMatchException();
+                }
+                password = sysUser.getPassword();
+                redisCache.deleteObject(LOGIN_USER_SMS + username);
+            } else {
+                throw new CaptchaExpireException();
+            }
+        }
+        return password;
+    }
 }

+ 58 - 45
ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysRegisterService.java

@@ -1,5 +1,7 @@
 package com.ruoyi.framework.web.service;
 
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.exception.user.UserPasswordNotMatchException;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 import com.ruoyi.common.constant.CacheConstants;
@@ -18,14 +20,16 @@ import com.ruoyi.framework.manager.factory.AsyncFactory;
 import com.ruoyi.system.service.ISysConfigService;
 import com.ruoyi.system.service.ISysUserService;
 
+import static com.ruoyi.common.constant.CommonConstants.*;
+import static com.ruoyi.common.constant.CommonConstants.LOGIN_USER_SMS;
+
 /**
  * 注册校验方法
- * 
+ *
  * @author ruoyi
  */
 @Component
-public class SysRegisterService
-{
+public class SysRegisterService {
     @Autowired
     private ISysUserService userService;
 
@@ -38,78 +42,87 @@ public class SysRegisterService
     /**
      * 注册
      */
-    public String register(RegisterBody registerBody)
-    {
+    public String register(RegisterBody registerBody) {
         String msg = "", username = registerBody.getUsername(), password = registerBody.getPassword();
         SysUser sysUser = new SysUser();
+        sysUser.setUserType("01");
         sysUser.setUserName(username);
+        sysUser.setPhonenumber(username);
 
         // 验证码开关
         boolean captchaEnabled = configService.selectCaptchaEnabled();
-        if (captchaEnabled)
-        {
+        if (captchaEnabled) {
             validateCaptcha(username, registerBody.getCode(), registerBody.getUuid());
         }
 
-        if (StringUtils.isEmpty(username))
-        {
+        if (StringUtils.isEmpty(username)) {
             msg = "用户名不能为空";
-        }
-        else if (StringUtils.isEmpty(password))
-        {
+        } else if (StringUtils.isEmpty(password)) {
             msg = "用户密码不能为空";
         }
-        else if (username.length() < UserConstants.USERNAME_MIN_LENGTH
-                || username.length() > UserConstants.USERNAME_MAX_LENGTH)
-        {
+        sysUser.setPassword(password);
+        if (ONE.equals(userService.checkStrongPwd(sysUser))) {
+            msg = "密码必须包含数字、大小写字母、特殊符号且大于8位";
+        } else if (username.length() < UserConstants.USERNAME_MIN_LENGTH
+                || username.length() > UserConstants.USERNAME_MAX_LENGTH) {
             msg = "账户长度必须在2到20个字符之间";
-        }
-        else if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
-                || password.length() > UserConstants.PASSWORD_MAX_LENGTH)
-        {
-            msg = "密码长度必须在5到20个字符之间";
-        }
-        else if (!userService.checkUserNameUnique(sysUser))
-        {
+        } else if (!userService.checkUserNameUnique(sysUser)) {
             msg = "保存用户'" + username + "'失败,注册账号已存在";
-        }
-        else
-        {
-            sysUser.setNickName(username);
-            sysUser.setPassword(SecurityUtils.encryptPassword(password));
-            boolean regFlag = userService.registerUser(sysUser);
-            if (!regFlag)
-            {
-                msg = "注册失败,请联系系统管理人员";
-            }
-            else
-            {
-                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.REGISTER, MessageUtils.message("user.register.success")));
+        } else {
+            if(validateType(username,registerBody.getCode())){
+                sysUser.setNickName(username);
+                sysUser.setPassword(SecurityUtils.encryptPassword(password));
+                boolean regFlag = userService.registerUser(sysUser);
+                if (!regFlag) {
+                    msg = "注册失败,请联系系统管理人员";
+                } else {
+                    AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.REGISTER, MessageUtils.message("user.register.success")));
+                }
+            }else {
+                msg = "注册失败,验证码错误";
             }
+
         }
         return msg;
     }
 
     /**
      * 校验验证码
-     * 
+     *
      * @param username 用户名
-     * @param code 验证码
-     * @param uuid 唯一标识
+     * @param code     验证码
+     * @param uuid     唯一标识
      * @return 结果
      */
-    public void validateCaptcha(String username, String code, String uuid)
-    {
+    public void validateCaptcha(String username, String code, String uuid) {
         String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.nvl(uuid, "");
         String captcha = redisCache.getCacheObject(verifyKey);
         redisCache.deleteObject(verifyKey);
-        if (captcha == null)
-        {
+        if (captcha == null) {
             throw new CaptchaExpireException();
         }
-        if (!code.equalsIgnoreCase(captcha))
-        {
+        if (!code.equalsIgnoreCase(captcha)) {
             throw new CaptchaException();
         }
     }
+
+    /**
+     * 注册短信验证码验证
+     *
+     * @param username 用户名
+     * @param code     短信验证码
+     */
+    public Boolean validateType(String username, String code) {
+        boolean bl = false;
+        //校验短信验证码
+        Object cacheObject = redisCache.getCacheObject(LOGIN_USER_SMS + username);
+        if (code.equals(cacheObject)) {
+            bl = true;
+            redisCache.deleteObject(LOGIN_USER_SMS + username);
+        } else {
+            throw new CaptchaExpireException();
+        }
+
+        return bl;
+    }
 }

+ 4 - 0
ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/TokenService.java

@@ -63,6 +63,10 @@ public class TokenService
     {
         // 获取请求携带的令牌
         String token = getToken(request);
+        String url = request.getRequestURL().toString();
+        if(url.contains("/v3/3rd/") || url.contains("/console/upload")){
+            token = request.getHeader("X-Weboffice-Token");
+        }
         if (StringUtils.isNotEmpty(token))
         {
             try

+ 2 - 2
ruoyi-generator/src/main/java/com/ruoyi/generator/controller/GenController.java

@@ -162,7 +162,7 @@ public class GenController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('tool:gen:edit')")
     @Log(title = "代码生成", businessType = BusinessType.UPDATE)
-    @PutMapping
+    @PostMapping("/put")
     public AjaxResult editSave(@Validated @RequestBody GenTable genTable)
     {
         genTableService.validateEdit(genTable);
@@ -175,7 +175,7 @@ public class GenController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('tool:gen:remove')")
     @Log(title = "代码生成", businessType = BusinessType.DELETE)
-    @DeleteMapping("/{tableIds}")
+    @GetMapping("/delete/{tableIds}")
     public AjaxResult remove(@PathVariable Long[] tableIds)
     {
         genTableService.deleteGenTableByIds(tableIds);

+ 1 - 1
ruoyi-generator/src/main/resources/generator.yml

@@ -1,7 +1,7 @@
 # 代码生成
 gen:
   # 作者
-  author: ruoyi
+  author: boman
   # 默认生成包路径 system 需改成自己的模块名称 如 system monitor tool
   packageName: com.ruoyi.system
   # 自动去除表前缀,默认是false

+ 1 - 0
ruoyi-generator/src/main/resources/vm/xml/mapper.xml.vm

@@ -56,6 +56,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 #end
 #end
         </where>
+        order by create_time
     </select>
     
     <select id="select${ClassName}By${pkColumn.capJavaField}" parameterType="${pkColumn.javaType}" resultMap="#if($table.sub)${ClassName}${subClassName}Result#else${ClassName}Result#end">

+ 4 - 4
ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobController.java

@@ -115,7 +115,7 @@ public class SysJobController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('monitor:job:edit')")
     @Log(title = "定时任务", businessType = BusinessType.UPDATE)
-    @PutMapping
+    @PostMapping("/put")
     public AjaxResult edit(@RequestBody SysJob job) throws SchedulerException, TaskException
     {
         if (!CronUtils.isValid(job.getCronExpression()))
@@ -151,7 +151,7 @@ public class SysJobController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('monitor:job:changeStatus')")
     @Log(title = "定时任务", businessType = BusinessType.UPDATE)
-    @PutMapping("/changeStatus")
+    @PostMapping("/changeStatus/put")
     public AjaxResult changeStatus(@RequestBody SysJob job) throws SchedulerException
     {
         SysJob newJob = jobService.selectJobById(job.getJobId());
@@ -164,7 +164,7 @@ public class SysJobController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('monitor:job:changeStatus')")
     @Log(title = "定时任务", businessType = BusinessType.UPDATE)
-    @PutMapping("/run")
+    @PostMapping("/run/put")
     public AjaxResult run(@RequestBody SysJob job) throws SchedulerException
     {
         boolean result = jobService.run(job);
@@ -176,7 +176,7 @@ public class SysJobController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('monitor:job:remove')")
     @Log(title = "定时任务", businessType = BusinessType.DELETE)
-    @DeleteMapping("/{jobIds}")
+    @GetMapping("/delete/{jobIds}")
     public AjaxResult remove(@PathVariable Long[] jobIds) throws SchedulerException, TaskException
     {
         jobService.deleteJobByIds(jobIds);

+ 2 - 2
ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobLogController.java

@@ -72,7 +72,7 @@ public class SysJobLogController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('monitor:job:remove')")
     @Log(title = "定时任务调度日志", businessType = BusinessType.DELETE)
-    @DeleteMapping("/{jobLogIds}")
+    @GetMapping("/delete/{jobLogIds}")
     public AjaxResult remove(@PathVariable Long[] jobLogIds)
     {
         return toAjax(jobLogService.deleteJobLogByIds(jobLogIds));
@@ -83,7 +83,7 @@ public class SysJobLogController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('monitor:job:remove')")
     @Log(title = "调度日志", businessType = BusinessType.CLEAN)
-    @DeleteMapping("/clean")
+    @GetMapping("/clean/delete")
     public AjaxResult clean()
     {
         jobLogService.cleanJobLog();

+ 32 - 0
ruoyi-system/pom.xml

@@ -23,6 +23,38 @@
             <artifactId>ruoyi-common</artifactId>
         </dependency>
 
+        <dependency>
+            <groupId>javax.persistence</groupId>
+            <artifactId>javax.persistence-api</artifactId>
+            <version>2.2</version>
+        </dependency>
+
+
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <optional>true</optional>
+        </dependency>
+
+        <dependency>
+            <groupId>cn.ljserver.tool</groupId>
+            <artifactId>web-office-v3</artifactId>
+            <version>3.1.0</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.qiniu</groupId>
+            <artifactId>qiniu-java-sdk</artifactId>
+            <version>7.15.0</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-mock</artifactId>
+            <version>2.0.8</version>
+        </dependency>
+
+
     </dependencies>
 
 </project>

Неке датотеке нису приказане због велике количине промена