Преглед на файлове

Merge remote-tracking branch 'origin/master'

liuyc преди 2 години
родител
ревизия
72c2093ce2
променени са 35 файла, в които са добавени 1672 реда и са изтрити 254 реда
  1. 31 20
      .idea/compiler.xml
  2. 34 0
      .idea/encodings.xml
  3. 1 1
      .idea/misc.xml
  4. 2 0
      .idea/modules.xml
  5. 162 0
      blade-common/src/main/java/org/springblade/common/utils/MathUtil.java
  6. 5 4
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/dto/FormData.java
  7. 34 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/dto/SignPfxDeputyDTO.java
  8. 75 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/SignPfxDeputy.java
  9. 4 4
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/SignPfxFile.java
  10. 31 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/RoleSignPfxUserVO.java
  11. 34 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/SignPfxDeputyVO.java
  12. 7 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/SignPfxFileVO.java
  13. 3 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/SingPfxManagementVO.java
  14. 1 1
      blade-service-api/blade-system-api/src/main/java/org/springblade/system/feign/ISysClient.java
  15. 1 1
      blade-service-api/blade-system-api/src/main/java/org/springblade/system/feign/ISysClientFallback.java
  16. 6 0
      blade-service-api/blade-system-api/src/main/java/org/springblade/system/vo/GrantTreeVO.java
  17. 4 1
      blade-service/blade-business/src/main/java/org/springblade/business/controller/BusinessUserOpinionController.java
  18. 1 1
      blade-service/blade-business/src/main/java/org/springblade/business/controller/UserOpinionController.java
  19. 0 9
      blade-service/blade-business/src/main/java/org/springblade/business/controller/UserOpinionFlowController.java
  20. 251 170
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ExcelTabController.java
  21. 1 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ExctabCellController.java
  22. 388 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ExpaileHtml.java
  23. 33 16
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/LinkdataInfoController.java
  24. 127 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/SignPfxDeputyController.java
  25. 211 16
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/SignPfxFileController.java
  26. 29 2
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/ProjectInfoMapper.xml
  27. 9 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/SaveUserInfoByProjectMapper.xml
  28. 42 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/SignPfxDeputyMapper.java
  29. 29 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/SignPfxDeputyMapper.xml
  30. 2 2
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/SignPfxFileMapper.xml
  31. 41 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/ISignPfxDeputyService.java
  32. 28 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/FormulaServiceImpl.java
  33. 41 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/SignPfxDeputyServiceImpl.java
  34. 2 2
      blade-service/blade-system/src/main/java/org/springblade/system/feign/SysClient.java
  35. 2 2
      blade-service/blade-system/src/main/java/org/springblade/system/mapper/MenuMapper.xml

+ 31 - 20
.idea/compiler.xml

@@ -7,38 +7,40 @@
         <sourceOutputDir name="target/generated-sources/annotations" />
         <sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
         <outputRelativeToContentRoot value="true" />
-        <module name="blade-user" />
-        <module name="blade-xxljob" />
-        <module name="blade-manager-api" />
-        <module name="blade-turbine" />
-        <module name="blade-swagger" />
         <module name="blade-admin" />
-        <module name="blade-system" />
+        <module name="blade-auth" />
+        <module name="blade-business" />
+        <module name="blade-business-api" />
         <module name="blade-common" />
-        <module name="blade-manager" />
-        <module name="blade-flow" />
-        <module name="blade-desk-api" />
-        <module name="blade-xxljob-admin" />
         <module name="blade-desk" />
-        <module name="blade-flow-api" />
-        <module name="blade-business" />
         <module name="blade-desk-api" />
-        <module name="blade-report" />
-        <module name="blade-system-api" />
-        <module name="blade-auth" />
-        <module name="blade-scope-api" />
-        <module name="blade-log" />
+        <module name="blade-develop" />
+        <module name="blade-dict-api" />
+        <module name="blade-flow" />
+        <module name="blade-flow-api" />
         <module name="blade-gateway" />
-        <module name="blade-user-api" />
+        <module name="blade-log" />
+        <module name="blade-manager" />
+        <module name="blade-manager-api" />
+        <module name="blade-report" />
         <module name="blade-resource" />
-        <module name="blade-dict-api" />
-        <module name="blade-business-api" />
         <module name="blade-resource-api" />
+        <module name="blade-scope-api" />
+        <module name="blade-swagger" />
+        <module name="blade-system" />
+        <module name="blade-system-api" />
+        <module name="blade-turbine" />
+        <module name="blade-user" />
+        <module name="blade-user-api" />
+        <module name="blade-xxljob" />
+        <module name="blade-xxljob-admin" />
       </profile>
     </annotationProcessing>
     <bytecodeTargetLevel target="8">
       <module name="blade-admin" target="1.8" />
       <module name="blade-auth" target="1.8" />
+      <module name="blade-business" target="1.8" />
+      <module name="blade-business-api" target="1.8" />
       <module name="blade-common" target="1.8" />
       <module name="blade-desk" target="1.8" />
       <module name="blade-desk-api" target="1.8" />
@@ -75,6 +77,8 @@
     <option name="ADDITIONAL_OPTIONS_OVERRIDE">
       <module name="blade-admin" options="-parameters" />
       <module name="blade-auth" options="-parameters" />
+      <module name="blade-business" options="-parameters" />
+      <module name="blade-business-api" options="-parameters" />
       <module name="blade-common" options="-parameters" />
       <module name="blade-desk" options="-parameters" />
       <module name="blade-desk-api" options="-parameters" />
@@ -86,10 +90,16 @@
       <module name="blade-log" options="-parameters" />
       <module name="blade-manager" options="-parameters" />
       <module name="blade-manager-api" options="-parameters" />
+      <module name="blade-ops" options="-parameters" />
+      <module name="blade-ops-api" options="-parameters" />
+      <module name="blade-plugin" options="-parameters" />
+      <module name="blade-plugin-api" options="-parameters" />
       <module name="blade-report" options="-parameters" />
       <module name="blade-resource" options="-parameters" />
       <module name="blade-resource-api" options="-parameters" />
       <module name="blade-scope-api" options="-parameters" />
+      <module name="blade-service" options="-parameters" />
+      <module name="blade-service-api" options="-parameters" />
       <module name="blade-swagger" options="-parameters" />
       <module name="blade-system" options="-parameters" />
       <module name="blade-system-api" options="-parameters" />
@@ -98,6 +108,7 @@
       <module name="blade-user-api" options="-parameters" />
       <module name="blade-xxljob" options="-parameters" />
       <module name="blade-xxljob-admin" options="-parameters" />
+      <module name="bladex" options="-parameters" />
     </option>
   </component>
 </project>

+ 34 - 0
.idea/encodings.xml

@@ -1,46 +1,80 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <project version="4">
   <component name="Encoding">
+    <file url="file://$PROJECT_DIR$" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/blade-auth" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/blade-auth/src/main/java" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/blade-auth/src/main/resources" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/blade-common" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/blade-common/src/main/java" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/blade-common/src/main/resources" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/blade-gateway" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/blade-gateway/src/main/java" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/blade-gateway/src/main/resources" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/blade-ops" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/blade-ops-api" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/blade-ops-api/blade-flow-api" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/blade-ops-api/blade-flow-api/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/blade-ops-api/blade-resource-api" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/blade-ops-api/blade-resource-api/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/blade-ops/blade-admin" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/blade-ops/blade-admin/src/main/java" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/blade-ops/blade-admin/src/main/resources" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/blade-ops/blade-develop" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/blade-ops/blade-develop/src/main/java" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/blade-ops/blade-develop/src/main/resources" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/blade-ops/blade-flow" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/blade-ops/blade-flow/src/main/java" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/blade-ops/blade-flow/src/main/resources" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/blade-ops/blade-log" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/blade-ops/blade-log/src/main/java" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/blade-ops/blade-log/src/main/resources" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/blade-ops/blade-report" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/blade-ops/blade-report/src/main/java" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/blade-ops/blade-report/src/main/resources" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/blade-ops/blade-resource" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/blade-ops/blade-resource/src/main/java" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/blade-ops/blade-resource/src/main/resources" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/blade-ops/blade-swagger" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/blade-ops/blade-swagger/src/main/java" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/blade-ops/blade-swagger/src/main/resources" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/blade-ops/blade-turbine" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/blade-ops/blade-turbine/src/main/java" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/blade-ops/blade-turbine/src/main/resources" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/blade-ops/blade-xxljob" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/blade-ops/blade-xxljob-admin" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/blade-ops/blade-xxljob-admin/src/main/java" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/blade-ops/blade-xxljob-admin/src/main/resources" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/blade-ops/blade-xxljob/src/main/java" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/blade-ops/blade-xxljob/src/main/resources" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/blade-plugin" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/blade-plugin-api" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/blade-service" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/blade-service-api" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/blade-service-api/blade-business-api" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/blade-service-api/blade-desk-api" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/blade-service-api/blade-desk-api/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/blade-service-api/blade-dict-api" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/blade-service-api/blade-dict-api/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/blade-service-api/blade-manager-api" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/blade-service-api/blade-manager-api/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/blade-service-api/blade-scope-api" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/blade-service-api/blade-scope-api/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/blade-service-api/blade-system-api" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/blade-service-api/blade-system-api/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/blade-service-api/blade-user-api" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/blade-service-api/blade-user-api/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/blade-service/blade-business" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/blade-service/blade-desk" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/blade-service/blade-desk/src/main/java" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/blade-service/blade-desk/src/main/resources" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/blade-service/blade-manager" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/blade-service/blade-manager/src/main/java" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/blade-service/blade-manager/src/main/resources" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/blade-service/blade-system" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/blade-service/blade-system/src/main/java" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/blade-service/blade-system/src/main/resources" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/blade-service/blade-user" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/blade-service/blade-user/src/main/java" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/blade-service/blade-user/src/main/resources" charset="UTF-8" />
   </component>

+ 1 - 1
.idea/misc.xml

@@ -9,7 +9,7 @@
       </list>
     </option>
   </component>
-  <component name="ProjectRootManager" version="2" languageLevel="JDK_13" default="false" project-jdk-name="1.8" project-jdk-type="JavaSDK">
+  <component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="false" project-jdk-name="1.8" project-jdk-type="JavaSDK">
     <output url="file://$PROJECT_DIR$/out" />
   </component>
 </project>

+ 2 - 0
.idea/modules.xml

@@ -4,6 +4,8 @@
     <modules>
       <module fileurl="file://$PROJECT_DIR$/blade-ops/blade-admin/blade-admin.iml" filepath="$PROJECT_DIR$/blade-ops/blade-admin/blade-admin.iml" />
       <module fileurl="file://$PROJECT_DIR$/blade-auth/blade-auth.iml" filepath="$PROJECT_DIR$/blade-auth/blade-auth.iml" />
+      <module fileurl="file://$PROJECT_DIR$/blade-service/blade-business/blade-business.iml" filepath="$PROJECT_DIR$/blade-service/blade-business/blade-business.iml" />
+      <module fileurl="file://$PROJECT_DIR$/blade-service-api/blade-business-api/blade-business-api.iml" filepath="$PROJECT_DIR$/blade-service-api/blade-business-api/blade-business-api.iml" />
       <module fileurl="file://$PROJECT_DIR$/blade-common/blade-common.iml" filepath="$PROJECT_DIR$/blade-common/blade-common.iml" />
       <module fileurl="file://$PROJECT_DIR$/blade-service/blade-desk/blade-desk.iml" filepath="$PROJECT_DIR$/blade-service/blade-desk/blade-desk.iml" />
       <module fileurl="file://$PROJECT_DIR$/blade-service-api/blade-desk-api/blade-desk-api.iml" filepath="$PROJECT_DIR$/blade-service-api/blade-desk-api/blade-desk-api.iml" />

+ 162 - 0
blade-common/src/main/java/org/springblade/common/utils/MathUtil.java

@@ -0,0 +1,162 @@
+package org.springblade.common.utils;
+
+import java.util.*;
+
+public class MathUtil {
+
+/*    public static void main(String[] args) {
+        String[] array = new String[] {"1","2","3"};
+        List arrayList = Arrays.asList(array);
+        Set<String> resultSet = new HashSet<>();
+        getCombination(arrayList, resultSet);
+        System.out.println("组合数 = " + resultSet.size());
+        System.out.println("所有组合 : " + resultSet);
+    }*/
+
+
+    /**
+     * 循环递归获取给定数组元素(无重复)的全排列
+     *
+     * @param oriList 原始数组
+     * @param oriLen 原始数组size
+     * @param arrayCombResult 数组排列结果集,可传null或空Set
+     * @param preList 记录排列参数,可传null或空List
+     * @return 排列结果
+     */
+    public static Set<String> getArrange(List oriList, int oriLen, Set<String> arrayCombResult, List preList){
+        if (oriList == null){
+            return arrayCombResult;
+        }
+        if (arrayCombResult == null){
+            arrayCombResult = new HashSet<>();
+        }
+        if (preList == null){
+            preList = new ArrayList();
+        }
+        for (int i = 0; i < oriList.size(); i++){
+            while(preList.size() > 0 && oriList.size() + preList.size() > oriLen){
+                preList.remove(preList.size() - 1);
+            }
+            List arrList = new ArrayList(oriList);
+            preList.add(arrList.get(i));
+            arrList.remove(i);
+            if (arrList.isEmpty()){
+                arrayCombResult.add(getStrFromList(preList));
+            }else {
+                getArrange(arrList, oriLen, arrayCombResult, preList);
+            }
+        }
+        return arrayCombResult;
+    }
+    /**
+     * 循环递归获取给定数组元素(无重复)的所有组合
+     *
+     * @param oriList 原始数组
+     * @param resultSet 元素组合结果,可传null或空set
+     * @return 组合结果
+     */
+    public static Set<String> getCombination(List oriList, Set<String> resultSet) {
+        if (oriList == null) {
+            return resultSet;
+        }
+        if (resultSet == null){
+            resultSet = new HashSet<>();
+        }
+        for (int i = 0; i < oriList.size(); i++) {
+            List copyList = new ArrayList(oriList);
+            resultSet.add(getStrFromList(copyList));
+            List removeIList = new ArrayList();
+            copyList.remove(i);
+            removeIList.addAll(copyList);
+            getCombination(removeIList, resultSet);
+        }
+        return resultSet;
+    }
+    /**
+     * 将数组元素转化为逗号分隔的字符串
+     *
+     * @param oriList 原始数组
+     * @return 字符串
+     */
+    public static String getStrFromList(List oriList){
+        StringBuffer result = new StringBuffer();
+        if (oriList == null){
+            return result.toString();
+        } else {
+            for (int i = 0; i < oriList.size(); i++){
+                result.append(oriList.get(i));
+                if (i != (oriList.size() - 1)){
+
+                }
+            }
+        }
+        return result.toString();
+    }
+
+
+
+    /**
+     * @param args
+     */
+    private static int min(int one, int two, int three) {
+        int min = one;
+        if(two < min) {
+            min = two;
+        }
+        if(three < min) {
+            min = three;
+        }
+        return min;
+    }
+
+    public static int ld(String str1, String str2) {
+        int d[][]; //矩阵
+        int n = str1.length();
+        int m = str2.length();
+        int i; //遍历str1的
+        int j; //遍历str2的
+        char ch1; //str1的
+        char ch2; //str2的
+        int temp; //记录相同字符,在某个矩阵位置值的增量,不是0就是1
+        if(n == 0) {
+            return m;
+        }
+        if(m == 0) {
+            return n;
+        }
+        d = new int[n+1][m+1];
+        for(i=0; i<=n; i++) { //初始化第一列
+            d[i][0] = i;
+        }
+        for(j=0; j<=m; j++) { //初始化第一行
+            d[0][j] = j;
+        }
+        for(i=1; i<=n; i++) { //遍历str1
+            ch1 = str1.charAt(i-1);
+            //去匹配str2
+            for(j=1; j<=m; j++) {
+                ch2 = str2.charAt(j-1);
+                if(ch1 == ch2) {
+                    temp = 0;
+                } else {
+                    temp = 1;
+                }
+                //左边+1,上边+1, 左上角+temp取最小
+                d[i][j] = min(d[i-1][j]+1, d[i][j-1]+1, d[i-1][j-1]+temp);
+            }
+        }
+        return d[n][m];
+    }
+
+    public static double sim(String str1, String str2) {
+        int ld = ld(str1, str2);
+        return 1 - (double) ld / Math.max(str1.length(), str2.length());
+    }
+
+/*   public static void main(String[] args) {
+        double data1 =0.19047619047619047;
+        double data2 =0.33333333333333337;
+       // System.out.println("ld="+ld(str1, str2));
+        System.out.println(data1<data2);
+    }*/
+}

+ 5 - 4
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/dto/FormData.java

@@ -19,7 +19,7 @@ public class FormData {
      */
     private String code;
     /**
-     * 步长
+     * 步长;跟别的元素计算时候,用于一对多
      */
     private Integer step;
     /**
@@ -42,15 +42,16 @@ public class FormData {
      */
     private String eAllowDeviation;
     /**
-     * 内容
+     * 内容:同一个groupId下List<每一页内容>
+     * 用于输出
      */
     private List<List<Object>> values;
     /**
-     * 公式脚本
+     * 公式对象
      */
     private Formula formula;
     /**
-     * 业务组
+     * 业务组:同一个节点,一种表格数据分为多组独立运算
      */
     private  Integer groupId;
 

+ 34 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/dto/SignPfxDeputyDTO.java

@@ -0,0 +1,34 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.manager.dto;
+
+import org.springblade.manager.entity.SignPfxDeputy;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 数据传输对象实体类
+ *
+ * @author BladeX
+ * @since 2022-06-28
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class SignPfxDeputyDTO extends SignPfxDeputy {
+	private static final long serialVersionUID = 1L;
+
+}

+ 75 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/SignPfxDeputy.java

@@ -0,0 +1,75 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.manager.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+
+import java.io.Serializable;
+
+import io.swagger.annotations.ApiModelProperty;
+import org.springblade.core.mp.base.BaseEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 实体类
+ *
+ * @author BladeX
+ * @since 2022-06-28
+ */
+@Data
+@TableName("m_sign_pfx_deputy")
+@EqualsAndHashCode(callSuper = true)
+public class SignPfxDeputy extends BaseEntity {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * sign_pfx_file表主键
+     */
+    private Long signPfxFileId;
+    /**
+     * 项目ID
+     */
+    @ApiModelProperty("项目ID")
+    private Long projectId;
+    /**
+     * 项目名称
+     */
+    @ApiModelProperty("项目名称")
+    private String projectName;
+
+    @ApiModelProperty("合同段ID")
+    private Long contractId;
+    /**
+     * 合同段名称
+     */
+    @ApiModelProperty("合同段名称")
+    private String contractName;
+    /**
+     * 角色ID
+     */
+    @ApiModelProperty("角色ID")
+    private Long roleId;
+    /**
+     * 角色名称
+     */
+    @ApiModelProperty("角色名称")
+    private String roleName;
+
+
+}

+ 4 - 4
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/SignPfxFile.java

@@ -84,10 +84,10 @@ public class SignPfxFile extends BaseEntity {
     @ApiModelProperty("是否注册,0未注册、1已注册")
     private Integer isRegister;
 
-    @ApiModelProperty("项目ID")
-    private Long projectId;
+    @ApiModelProperty("企业统一社会信用代码")
+    private String enterpriseUnifiedCode;
 
-    @ApiModelProperty("合同段ID")
-    private Long contractId;
+    @ApiModelProperty("规则:项目ID-合同段ID-角色ID,项目ID-合同段ID-角色ID")
+    private String projectContractRole;
 
 }

+ 31 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/RoleSignPfxUserVO.java

@@ -0,0 +1,31 @@
+package org.springblade.manager.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.springblade.manager.entity.SignPfxFile;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Data
+public class RoleSignPfxUserVO {
+
+    /**
+     * 角色ID
+     */
+    @ApiModelProperty(value = "角色ID")
+    private Long roleId;
+
+    /**
+     * 角色名
+     */
+    @ApiModelProperty(value = "角色名")
+    private String roleName;
+
+    @ApiModelProperty(value = "子角色集合")
+    private List<RoleSignPfxUserVO> childRoleList = new ArrayList<>();
+
+    @ApiModelProperty(value = "个人签章集合")
+    private List<SignPfxFile> signPfxFileList = new ArrayList<>();
+
+}

+ 34 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/SignPfxDeputyVO.java

@@ -0,0 +1,34 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.manager.vo;
+
+import org.springblade.manager.entity.SignPfxDeputy;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 视图实体类
+ *
+ * @author BladeX
+ * @since 2022-06-28
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class SignPfxDeputyVO extends SignPfxDeputy {
+	private static final long serialVersionUID = 1L;
+
+}

+ 7 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/SignPfxFileVO.java

@@ -17,10 +17,14 @@
 package org.springblade.manager.vo;
 
 import io.swagger.annotations.ApiModelProperty;
+import org.springblade.manager.entity.SignPfxDeputy;
 import org.springblade.manager.entity.SignPfxFile;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * 个人/企业证书信息表视图实体类
  *
@@ -44,4 +48,7 @@ public class SignPfxFileVO extends SignPfxFile {
 	@ApiModelProperty("是否注册,true为已注册")
 	private Boolean isRegisterBoolean;
 
+	@ApiModelProperty("项目合同段信息")
+	private List<SignPfxDeputy> signPfxDeputieList;
+
 }

+ 3 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/SingPfxManagementVO.java

@@ -24,4 +24,7 @@ public class SingPfxManagementVO {
     @ApiModelProperty("当前页总数")
     private Integer size;
 
+    @ApiModelProperty("合同段ID")
+    private Long contractId;
+
 }

+ 1 - 1
blade-service-api/blade-system-api/src/main/java/org/springblade/system/feign/ISysClient.java

@@ -68,7 +68,7 @@ public interface ISysClient {
 	 * 角色信息查询
 	 */
 	@GetMapping(SEARCH)
-	R<List<RoleVO>> search(@RequestParam("roleName")String roleName, @RequestParam("parentId")Long parentId);
+	R<List<RoleVO>> search();
 
 	/**
 	 * 获取菜单

+ 1 - 1
blade-service-api/blade-system-api/src/main/java/org/springblade/system/feign/ISysClientFallback.java

@@ -32,7 +32,7 @@ import java.util.List;
 public class ISysClientFallback implements ISysClient {
 
 	@Override
-	public R<List<RoleVO>> search(String roleName, Long parentId) {
+	public R<List<RoleVO>> search() {
 		return R.fail("获取数据失败");
 	}
 

+ 6 - 0
blade-service-api/blade-system-api/src/main/java/org/springblade/system/vo/GrantTreeVO.java

@@ -31,10 +31,16 @@ import java.util.List;
 public class GrantTreeVO implements Serializable {
 	private static final long serialVersionUID = 1L;
 
+	// 后管
 	private List<TreeNode> menu;
 
+	// 客户端
+	private List<TreeNode> usermenu;
+
+	//
 	private List<TreeNode> dataScope;
 
+	//api
 	private List<TreeNode> apiScope;
 
 }

+ 4 - 1
blade-service/blade-business/src/main/java/org/springblade/business/controller/BusinessUserOpinionController.java

@@ -115,8 +115,11 @@ public class BusinessUserOpinionController {
             @ApiImplicitParam(name = "current", value = "当前页", required = true),
             @ApiImplicitParam(name = "size", value = "当前页显示数量", required = true)
     })
-    public R<IPage<BusinessUserOpinionVO>> queryBusinessUserOpinionList(@RequestBody Query query){
+    public R<IPage<BusinessUserOpinionVO>> queryBusinessUserOpinionList(@RequestParam Integer current, @RequestParam Integer size){
         BladeUser user = AuthUtil.getUser();
+        Query query = new Query();
+        query.setCurrent(current);
+        query.setSize(size);
         //获取推送给当前用户的工单信息
         return R.data(this.userOpinionService.queryBusinessUserOpinionList(String.valueOf(user.getUserId()),query));
     }

+ 1 - 1
blade-service/blade-business/src/main/java/org/springblade/business/controller/UserOpinionController.java

@@ -269,7 +269,7 @@ public class UserOpinionController extends BladeController {
 		//提交成功环节
 		saveFlowList.add(setUserData(new UserOpinionFlow(idKey, 2, 1, 1, "已提交", "已成功提交您的工单信息", manageTime, manageUser, manageUserName, manegeUserPhone)));
 		//分配维护人员环节
-		saveFlowList.add(setUserData(new UserOpinionFlow(idKey, 1, 1, 2, "已分配专属客服", "客服:" + manageUser + "<br>电话:" + manegeUserPhone, manageTime, manageUser, manageUserName, manegeUserPhone)));
+		saveFlowList.add(setUserData(new UserOpinionFlow(idKey, 1, 1, 2, "已分配专属客服", "客服:" + manageUserName + "<br>电话:" + manegeUserPhone, manageTime, manageUser, manageUserName, manegeUserPhone)));
 		//进入人工预处理环节
 		saveFlowList.add(setUserData(new UserOpinionFlow(idKey, 0, 1, 3, "进入人工预处理环节", "预计" + manageTime + "之前完成", manageTime, manageUser, manageUserName, manegeUserPhone)));
 		//问题已解决

+ 0 - 9
blade-service/blade-business/src/main/java/org/springblade/business/controller/UserOpinionFlowController.java

@@ -32,10 +32,6 @@ import org.springblade.core.secure.BladeUser;
 import org.springblade.core.secure.utils.AuthUtil;
 import org.springblade.core.tool.api.R;
 import org.springblade.core.tool.utils.DateUtil;
-import org.springblade.manager.dto.SaveUserInfoByProjectDTO;
-import org.springblade.manager.feign.ProjectAssignmentUserClient;
-import org.springblade.system.user.entity.User;
-import org.springblade.system.user.feign.IUserClient;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springblade.business.entity.UserOpinionFlow;
@@ -45,7 +41,6 @@ import org.springblade.core.boot.ctrl.BladeController;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
-import java.util.Random;
 
 /**
  * 用户意见处理流程表 控制器
@@ -63,10 +58,6 @@ public class UserOpinionFlowController extends BladeController {
 
 	private final IUserOpinionService userOpinionService;
 
-	private final ProjectAssignmentUserClient projectAssignmentUserClient;
-
-	private final IUserClient userClient;
-
 	/**
 	 * 统合接口
 	 * @param oldEndFlow 流程图的最后一个节点ID

+ 251 - 170
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ExcelTabController.java

@@ -28,10 +28,12 @@ import javax.validation.Valid;
 
 import lombok.SneakyThrows;
 
+import org.apache.commons.lang.StringUtils;
 import org.jsoup.Jsoup;
 import org.jsoup.nodes.Document;
 import org.jsoup.nodes.Element;
 import org.jsoup.select.Elements;
+import org.springblade.common.utils.MathUtil;
 import org.springblade.common.utils.SnowFlakeUtil;
 import org.springblade.core.log.exception.ServiceException;
 import org.springblade.core.mp.support.Condition;
@@ -42,8 +44,7 @@ import org.springblade.core.secure.BladeUser;
 import org.springblade.core.secure.utils.AuthUtil;
 import org.springblade.core.tool.api.R;
 import org.springblade.core.tool.constant.BladeConstant;
-import org.springblade.core.tool.utils.Func;
-import org.springblade.core.tool.utils.StringPool;
+import org.springblade.core.tool.utils.*;
 import org.springblade.manager.entity.*;
 import org.springblade.manager.service.*;
 import org.springblade.manager.vo.*;
@@ -246,6 +247,8 @@ public class ExcelTabController extends BladeController {
 		detail.setFileType(3); // 表示为清表信息  1 表示祖节点  2 表示为节点信息 3 表示清表
 		detail.setHtmlUrl(thmlUrl);
 		excelTabService.saveOrUpdate(detail);
+		// 解析html
+		explianHtml(thmlUrl);
 		return R.success("上传成功");
 	}
 
@@ -329,45 +332,6 @@ public class ExcelTabController extends BladeController {
 		return R.success("添加成功!");
 	}
 
-	public static String readfile(String filePath){
-		File file = new File(filePath);
-		InputStream input = null;
-		try {
-			input = new FileInputStream(file);
-		} catch (FileNotFoundException e) {
-			e.printStackTrace();
-		}
-		StringBuffer buffer = new StringBuffer();
-		byte[] bytes = new byte[1024];
-		try {
-			for(int n ; (n = input.read(bytes))!=-1 ; ){
-				buffer.append(new String(bytes,0,n,"UTF-8"));
-			}
-		} catch (IOException e) {
-			e.printStackTrace();
-		}
-		return buffer.toString();
-	}
-
-
-	private static void saveAsFileWriter(String content ,String filePath) {
-		Writer fwriter = null;
-		try {
-			// true表示不覆盖原来的内容,而是加到文件的后面。若要覆盖原来的内容,直接省略这个参数就好
-			fwriter = new BufferedWriter((new OutputStreamWriter(new FileOutputStream(filePath),"UTF-8")));
-			fwriter.write(content);
-		} catch (IOException ex) {
-			ex.printStackTrace();
-		} finally {
-			try {
-				fwriter.flush();
-				fwriter.close();
-			} catch (IOException ex) {
-				ex.printStackTrace();
-			}
-		}
-	}
-
 	/**
 	 * 关联清表树
 	 */
@@ -395,8 +359,6 @@ public class ExcelTabController extends BladeController {
 		WbsTreePrivate wbsTree = new WbsTreePrivate();
 		wbsTree.setPKeyId(tabId);
 		WbsTreePrivate aPrivate = wbsTreePrivateService.getOne(Condition.getQueryWrapper(wbsTree));
-		aPrivate.setIsLinkTable(1); // 已关联
-		aPrivate.setExcelId(exceTabId);
 
 		UpdateWrapper<WbsTreePrivate> updateWrapper = new UpdateWrapper<>();
 		updateWrapper.in("p_key_id",tabId);
@@ -407,56 +369,245 @@ public class ExcelTabController extends BladeController {
 		// 获取excel 基本信息
 		ExcelTab excelTab = excelTabService.getById(exceTabId);
 		// 解析
+		try {
+			getExcelHtml1(excelTab.getHtmlUrl(),aPrivate.getId()+"");
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+		return R.success("关联成功");
+	}
 
-		// 获取元素列表
-		WbsFormElement wbsFormElement = new WbsFormElement();
-		QueryWrapper<WbsFormElement> queryWrapper = new QueryWrapper<>();
-		List<WbsFormElement> detail = wbsFormElementService.selectElementListByFid(aPrivate.getId()+"");
-		// 解析html
-		getExcelHtml1(excelTab.getHtmlUrl());
 
-		return R.success("关联成功");
+
+
+	// 匹配
+	public void getExcelHtml1(String thmlUrl,String  TabId) throws IOException{
+		List<WbsFormElement> dataList = wbsFormElementService.selectElementListByFid(TabId);
+
+		File file1 = ResourceUtil.getFile(thmlUrl);
+		FileInputStream fileInputStream = new FileInputStream(file1);
+		String htmlString =   IoUtil.readToString(fileInputStream);
+		Document doc = Jsoup.parse(htmlString);
+		Element table = doc.select("table").first();
+		Elements trs = table.select("tr");
+
+		// 循环解析
+		// 标题坐标
+		List<Map<String,String>> zikey = new ArrayList<>();
+
+		int index_id = 0;
+		// 循环解析
+		for(int i = 0 ;i < trs.size() ;i++) {
+			Element tr = trs.get(i);
+			boolean index_stat = Boolean.parseBoolean(tr.attr("index_stat"));
+
+			if(index_stat && index_id==0){
+				index_id = 1;
+				zikey = new ArrayList<>();
+			}
+
+			if(!index_stat && index_id==1 && zikey.size()>=1){
+				index_id = 2;
+				zikey = new ArrayList<>();
+			}
+
+			Elements tds = tr.select("td");
+			for (int j = 0; j < tds.size(); j++) {
+				Element data = tds.get(j);
+				String textInfo  = data.text();
+				int x1 = Integer.parseInt( data.attr("x1"));
+				int x2 = Integer.parseInt( data.attr("x2"));
+				int y1 = Integer.parseInt( data.attr("y1"));
+				int y2 = Integer.parseInt( data.attr("y2"));
+
+
+				if(!textInfo.isEmpty() && !textInfo.equals("/")){
+					Map<String,String> dataInfo =new HashMap<String,String>();
+					dataInfo.put("name",textInfo);
+					dataInfo.put("x1",data.attr("x1"));
+					dataInfo.put("x2",data.attr("x2"));
+					dataInfo.put("y1",data.attr("y1"));
+					dataInfo.put("y2",data.attr("y2"));
+					zikey.add(dataInfo);
+				}else if(data.html().indexOf("input")>=0){
+
+					List arrayList = new ArrayList<>();
+
+
+					for(int k=zikey.size()-1;k>=0 ;k--){
+						String name = zikey.get(k).get("name").replaceAll("[^\u4E00-\u9FA5]", "");
+						int xx1 = Integer.parseInt( zikey.get(k).get("x1"));
+						int xx2 = Integer.parseInt( zikey.get(k).get("x2"));
+						int yy1 = Integer.parseInt( zikey.get(k).get("y1"));
+						int yy2 = Integer.parseInt( zikey.get(k).get("y2"));
+
+						// 左匹配
+						if( yy1<=y1 && yy2>=y2 && xx2<x1 && StringUtils.isNotEmpty(name)){
+							arrayList.add(name);
+							if(!index_stat){
+								break;
+							}
+						}
+
+						//向 上 匹配
+						if(index_stat){
+							if( xx1<=x1 && xx2 >=x2 && yy2<y1 ){
+								arrayList.add(name);
+							}
+						}
+					}
+
+					Set<String> resultSet = new HashSet<>();
+					MathUtil.getCombination(arrayList, resultSet);
+					double maxInfo = 0;
+					if(!resultSet.isEmpty()){
+
+						for(WbsFormElement wbsFormElement : dataList){
+							for(String bx : resultSet){
+								double dataxx =  MathUtil.sim(bx,wbsFormElement.getEName().replaceAll("[^\u4E00-\u9FA5]", ""));
+								if(maxInfo < dataxx){
+									System.out.println("x1-x2="+x1+","+x2+"y1-y2="+y1+","+y2+bx+"="+dataxx+"_jieh="+resultSet);
+									data.empty().text(bx);
+									maxInfo = dataxx;
+								}
+							}
+						}
+					}
+					System.out.println(maxInfo);
+				}
+			}
+		}
+
+
+		//
+		// for (Map<String,String> d:zikey){
+		// System.out.println(d.get("name")+"x1"+d.get("x1"));
+		//  }
+
+		fileInputStream.close();
+
+		File writefile = new File(thmlUrl);
+		FileUtil.writeToFile(writefile, doc.html(), Boolean.parseBoolean("UTF-8"));
+		System.out.println("完成");
+
 	}
 
 
-	public void getExcelHtml1(String thmlUrl) {
 
-		String htmlString =  readfile(thmlUrl);
-		Map<String ,String > styleMap = new HashMap<>();
+	/**
+	 * 清表生成html
+	 */
+	@GetMapping("/get-excel-html")
+	@ApiOperationSupport(order = 15)
+	@ApiOperation(value = "清表生成html", notes = "清表生成html")
+	@ApiImplicitParams(value = {
+			@ApiImplicitParam(name = "excelId", value = "excelId", required = true)
+	})
+	public R getExcelHtml(Long excelId) throws IOException {
+		ExcelTab excelTab = excelTabService.getById(excelId);
+		if(excelTab ==null ){
+			return R.fail("该数据下无此节点!");
+		}
+		if(excelTab.getHtmlUrl()==null){
+			return R.fail("请上传清表!");
+		}
 
+		File file1 = ResourceUtil.getFile(excelTab.getHtmlUrl());
+		FileInputStream fileInputStream = new FileInputStream(file1);
+		String htmlString =   IoUtil.readToString(fileInputStream);
+		// 解析 style
+		Document doc = Jsoup.parse(htmlString);
+		Element table = doc.select("table").first();
+		doc.select("Col").remove();
+		fileInputStream.close();
+		return R.data(table+"");
+	}
+
+
+
+	public static void explianHtml(String htmlURl) throws IOException {
+
+		File file1 = ResourceUtil.getFile(htmlURl);
+		FileInputStream inputStream = new FileInputStream(file1);
+
+		// 测试
+		String htmlString =  IoUtil.readToString(inputStream);
+
+		// 样式集合
+		Map<String ,String > styleMap = new HashMap<>();
 		// 解析 style
 		Document doc = Jsoup.parse(htmlString);
 		Element style = doc.select("style").first();
+
 		Matcher cssMatcher = Pattern.compile("(\\w+)\\s*[{]([^}]+)[}]").matcher(style.html());
 		while (cssMatcher.find()) {
 			styleMap.put(cssMatcher.group(1),cssMatcher.group(2));
 		}
 		// 解析 总行和总列
-		// 解析
 		Element table = doc.select("table").first();
 		Elements trs = table.select("tr");
 
 		// 获取总行列数
 		int maxCol = doc.select("Col").size();
-
-		List<Map<String,String>> textlist = new ArrayList<>() ;
-
 		String [] rowData = new String[trs.size()+1];
 
 		int s_index = 0;
+		boolean index_stat = false;
 		// 横向计算
 		for(int i = 0 ;i < trs.size() ;i++) {
 			Element tr = trs.get(i);
 			Elements tds = tr.select("td");
+
+			int x_width = 0 ;
+			int y_width = 0 ;
+			//区域计算
+			for (int j = 0; j < tds.size(); j++) {
+				Element data = tds.get(j);
+				String keyId = data.attr("class");
+
+				int colspan = data.attr("COLSPAN").equals("") ? 1 : Integer.parseInt(data.attr("COLSPAN"));
+				String classInfo = styleMap.get(keyId);
+				data.removeAttr("class");
+				data.attr("style",styleMap.get(keyId).replaceAll("break-word","inherit"));
+				// 第一列
+				if(j==0 && classInfo.indexOf("border-left-style")>=0 && classInfo.indexOf("border-top-style")>=0 && classInfo.indexOf("border-bottom-style")>=0 && !index_stat){
+					x_width +=colspan;
+				}else if(j == tds.size()-1 && classInfo.indexOf("border-right-style")>=0 && classInfo.indexOf("border-top-style")>=0 && classInfo.indexOf("border-bottom-style")>=0 && !index_stat && j>=1){
+					x_width +=colspan;
+				}else if(classInfo.indexOf("border-top-style")>=0 && classInfo.indexOf("border-bottom-style")>=0 && !index_stat && j>=1){
+					x_width +=colspan;
+				}
+
+				// 计算退出
+				if(j==0 && classInfo.indexOf("border-left-style")<0 && classInfo.indexOf("border-top-style")>=0 && classInfo.indexOf("border-bottom-style")<0 && index_stat && classInfo.indexOf("border-right-style")<0){
+					y_width +=colspan;
+				}else if(j == tds.size()-1 && classInfo.indexOf("border-right-style")<0 && classInfo.indexOf("border-top-style")>=0 && classInfo.indexOf("border-bottom-style")<0 && index_stat && j>=1){
+					y_width +=colspan;
+				}else if(classInfo.indexOf("border-top-style")>=0 && classInfo.indexOf("border-bottom-style")<0 &&index_stat && j>=1){
+					y_width +=colspan;
+				}
+			}
+
+			if(x_width == maxCol && !index_stat && s_index==0){
+				s_index = i + 1;
+				index_stat = true ;
+			}
+
+			if(y_width == maxCol && index_stat && s_index>0){
+				s_index = i + 1;
+				index_stat = false ;
+			}
+
+			tr.attr("index_stat",index_stat+"");
+
 			int x= 0;
 			for (int j = 0; j < tds.size(); j++) {
-				ExctabCell cell = new ExctabCell();
 				Element data = tds.get(j);
+
 				int colspan = data.attr("COLSPAN").equals("") ? 0 : Integer.parseInt(data.attr("COLSPAN"));
 				int rowspan = data.attr("ROWSPAN").equals("") ? 0 : Integer.parseInt(data.attr("ROWSPAN"));
-				Map<String, String> textObject = new HashMap<>();
-
 
+				Map<String, String> textObject = new HashMap<>();
 				// 计算
 				int x1 =0;
 				int x2 =0;
@@ -473,10 +624,9 @@ public class ExcelTabController extends BladeController {
 					x2 = x+colspan;
 					x = x+colspan;
 				}
-
 				String textInfo = data.text().trim();
+
 				// y 坐标
-				textObject.put("text",textInfo);
 				y1=i+1;
 				if(rowspan==0){
 					y2 = i+1;
@@ -525,128 +675,59 @@ public class ExcelTabController extends BladeController {
 				}
 
 
-				String keyId = data.attr("class");
-				if(!keyId.isEmpty()){
-					data.removeAttr("class");
-					data.attr("style",styleMap.get(keyId));
+				// System.out.println(StringUtil.trimAllWhitespace(textInfo)+""+StringUtil.trimAllWhitespace(textInfo).length());
+				data.text(textInfo.replaceAll(" ",""));
 
-					// 封版
-					if(styleMap.get(keyId).indexOf("border-top-style")>=0 && styleMap.get(keyId).indexOf("border-bottom-style")>=0){
-						s_index = y1;
-					}
-					if(styleMap.get(keyId).indexOf("border-top-style")>=0 && styleMap.get(keyId).indexOf("border-bottom-style")<0){
-						s_index = y1;
-					}
-				}
 
-				LinkdataInfo linkdataInfo = new LinkdataInfo();
-				linkdataInfo.setTrIndex(i);
-				linkdataInfo.setTdIndex(j);
-				linkdataInfo.setTabId(Long.parseLong("123456789"));
-				boolean isadd = false;
-				// 组装 html 数据
-				boolean istopVal =false;
-				boolean isleftVal =false;
-				int inputType = 1;  //1 输入框  2 时间
-				if(textInfo.equals("/")|| textInfo.isEmpty() || textInfo.equals("—")){
-					if(i== 0 && j==0 && maxCol==colspan ){ // 第一行为空
-						isadd = false;
-					}else{
-						// 得到 当前位置 获取值
-						for(int k=textlist.size()-1;k>=0;k--){
-							Map<String,String> m = textlist.get(k);
-							int xx1 = Integer.parseInt(m.get("x1"));
-							int xx2 = Integer.parseInt(m.get("x2"));
-							int yy1 = Integer.parseInt(m.get("y1"));
-							int yy2 = Integer.parseInt(m.get("y2"));
-							String kekval = m.get("text");
-
-							if(xx1<=x1 && xx2>=x2 && yy2<y1 && !istopVal && y1>=s_index){ // 向上取值
-								if(!kekval.isEmpty() && !kekval.equals("/") && kekval.indexOf("检验单")<0 && kekval.indexOf("表")<0 && kekval.indexOf("—")<0){
-									if(kekval.indexOf("日期")>=0){
-										inputType=2;
-									}
-									linkdataInfo.setColName(kekval);
-									istopVal = true ;
-									System.out.println(x1 +"-"+x2 +":"+y1+"-"+y2 + "--"+s_index +"val:"+kekval);
-								}
-							}
-							if(yy1<=y1 && yy2>=y2 && xx2<x1 && !isleftVal && y1>=s_index){ // 向左取
-								if(!kekval.isEmpty() && !kekval.equals("/") && kekval.indexOf("检验单")<0 && kekval.indexOf("表")<0&& kekval.indexOf("—")<0){
-									isleftVal = true ;
-									if(kekval.indexOf("日期")>=0){
-										inputType=2;
-									}
-									linkdataInfo.setColName(kekval);
-								//	System.out.println(x1 +"-"+x2 +":"+y1+"-"+y2 + "--"+s_index +"val:"+kekval);
-								}
-							}
-							if(isleftVal || istopVal){
-								isadd = true ;
-							}
-							if (istopVal&&isleftVal){
-								break;
-							}
-						}
-					}
-				}else{
-					isadd = false;
-				}
 
+				// 设置td 属性
+				data.attr("trIndex",i+"");
+				data.attr("tdIndex",j+"");
+				data.attr("x1",x1+"");
+				data.attr("x2",x2+"");
+				data.attr("y1",y1+"");
+				data.attr("y2",y2+"");
+				String parm = i+","+j+","+x1+","+x2+","+y1+","+y2;
+				// 设置文本信息
 				if(textInfo.indexOf("年")>=0 && textInfo.indexOf("月")>=0&& textInfo.indexOf("日")>=0){
-					data.empty().append("<el-date-picker style='width:100%;height:100%'   type='date' format='yyyy 年 MM 月 dd 日' placeholder='请选择时间'> </el-date-picker>");
+					data.empty().append("<el-date-picker style='width:100%;height:100%' trIndex="+i+" tdIndex="+j+"  x1="+x1+" x2="+x2+" y1="+y1+" y2="+y2+"  type='date' format='yyyy 年 MM 月 dd 日' placeholder='请选择时间'> </el-date-picker>");
 				}
 
-				if(isadd){
-
-					if(inputType==2){
-						data.empty().append("<el-date-picker  type='date' style='width:100%;height:100%' > </el-date-picker>");
-					}else{
+				if(textInfo.isEmpty() || textInfo.equals("/") || textInfo.equals("-")){
+					if(index_stat){
 						if(rowspan>=1){
-							data.empty().append("<el-input type='textarea' style='width:100%;height:100%'   :rows="+rowspan*2+" placeholder=''> </el-input>");
+							data.empty().append("<el-input type='textarea' @contextmenu.prevent.native='RightClick("+parm+")' trIndex="+i+" tdIndex="+j+"  x1="+x1+" x2="+x2+" y1="+y1+" y2="+y2+" style='width:100%;height:100%'   :rows="+rowspan*2+" placeholder=''> </el-input>");
 						}else{
-							data.empty().append("<el-input type='text' style='width:100%;height:100%' placeholder=''> </el-input>");
+							data.empty().append("<el-input type='text' @contextmenu.prevent.native='RightClick("+parm+")' trIndex="+i+" tdIndex="+j+"  x1="+x1+" x2="+x2+" y1="+y1+" y2="+y2+" style='width:100%;height:100%' placeholder=''> </el-input>");
+						}
+					}else{
+						if(j==0 ){
+							if(colspan ==maxCol && i>=1 && i<=2){
+								if(rowspan>=1){
+									data.empty().append("<el-input type='textarea' @contextmenu.prevent.native='RightClick("+parm+")' trIndex="+i+" tdIndex="+j+"  x1="+x1+" x2="+x2+" y1="+y1+" y2="+y2+" style='width:100%;height:100%'   :rows="+rowspan*2+" placeholder=''> </el-input>");
+								}else{
+									data.empty().append("<el-input type='text' @contextmenu.prevent.native='RightClick("+parm+")' trIndex="+i+" tdIndex="+j+"  x1="+x1+" x2="+x2+" y1="+y1+" y2="+y2+" style='width:100%;height:100%' placeholder=''> </el-input>");
+								}
+							}
+						}else{
+							Element bforData = tds.get(j-1);
+							if(!bforData.text().isEmpty()){
+								if(rowspan>=1){
+									data.empty().append("<el-input type='textarea' @contextmenu.prevent.native='RightClick("+parm+")' trIndex="+i+" tdIndex="+j+"  x1="+x1+" x2="+x2+" y1="+y1+" y2="+y2+" style='width:100%;height:100%'   :rows="+rowspan*2+" placeholder=''> </el-input>");
+								}else{
+									data.empty().append("<el-input type='text' @contextmenu.prevent.native='RightClick("+parm+")' trIndex="+i+" tdIndex="+j+"  x1="+x1+" x2="+x2+" y1="+y1+" y2="+y2+" style='width:100%;height:100%' placeholder=''> </el-input>");
+								}
+							}
 						}
 					}
-					//linkdataInfoService.save(linkdataInfo);
 				}
-
-				textObject.put("x1",x1+"");
-				textObject.put("x2",x2+"");
-				textObject.put("y1",y1+"");
-				textObject.put("y2",y2+"");
-				textObject.put("rowSpan",rowspan+"");
-				textlist.add(textObject);
 			}
 		}
-		saveAsFileWriter(doc+"",thmlUrl);
-	}
-
 
+		// 写入
 
-	/**
-	 * 清表生成html
-	 */
-	@GetMapping("/get-excel-html")
-	@ApiOperationSupport(order = 15)
-	@ApiOperation(value = "清表生成html", notes = "清表生成html")
-	@ApiImplicitParams(value = {
-			@ApiImplicitParam(name = "excelId", value = "excelId", required = true)
-	})
-	public R getExcelHtml(Long excelId) {
-		ExcelTab excelTab = excelTabService.getById(excelId);
-		if(excelTab ==null ){
-			return R.fail("该数据下无此节点!");
-		}
-
-		if(excelTab.getHtmlUrl()==null){
-			return R.fail("请上传清表!");
-		}
-
-		String htmlString =  readfile(excelTab.getHtmlUrl());
-		// 解析 style
-		Document doc = Jsoup.parse(htmlString);
-		Element table = doc.select("table").first();
-		return R.data(table+"");
+		FileUtil.writeToFile(file1, doc.html(), Boolean.parseBoolean("UTF-8"));
+		inputStream.close();
+		System.out.println("完成");
 	}
 }

+ 1 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ExctabCellController.java

@@ -92,6 +92,7 @@ public class ExctabCellController extends BladeController {
 		return R.status(exctabCellService.save(exctabCell));
 	}
 
+
 	/**
 	 * 修改 Excel 结构信息表
 	 */

+ 388 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ExpaileHtml.java

@@ -0,0 +1,388 @@
+package org.springblade.manager.controller;
+
+import com.spire.xls.Workbook;
+import com.spire.xls.Worksheet;
+import org.apache.commons.lang.StringUtils;
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Document;
+import org.jsoup.nodes.Element;
+import org.jsoup.select.Elements;
+import org.springblade.common.utils.MathUtil;
+import org.springblade.core.tool.utils.FileUtil;
+import org.springblade.core.tool.utils.IoUtil;
+import org.springblade.core.tool.utils.ResourceUtil;
+import org.springblade.manager.entity.WbsFormElement;
+
+import java.io.*;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+public class ExpaileHtml {
+/*
+    public static void main(String[] args) throws IOException {
+        getHtmlInfo();
+        try {
+            Thread.sleep(500);
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+        //String inHtmlUrl = "/Users/hongchuangyanfa/Desktop/123654.html";
+       getjiexiInfo();
+    }
+*/
+
+
+
+
+
+
+    public static void getjiexiInfo() throws IOException {
+        String inHtmlUrl = "/Users/hongchuangyanfa/Desktop/123654.html";
+        File file = ResourceUtil.getFile(inHtmlUrl);
+        FileInputStream inputStream = new FileInputStream(file);
+        String htmlString =   IoUtil.readToString(inputStream);
+
+        // 获取比对数据
+        List<WbsFormElement> dataList = getWbsInfo();
+
+        String dataInfox = dataList.stream().map(WbsFormElement::getEName).collect(Collectors.joining(","));
+
+        System.out.println(dataInfox);
+        Document doc = Jsoup.parse(htmlString);
+        Element table = doc.select("table").first();
+        Elements trs = table.select("tr");
+
+
+        // 标题坐标
+        List<Map<String,String>> zikey = new ArrayList<>();
+
+        int index_id = 0;
+        // 循环解析
+        for(int i = 0 ;i < trs.size() ;i++) {
+            Element tr = trs.get(i);
+            boolean index_stat = Boolean.parseBoolean(tr.attr("index_stat"));
+
+            if(index_stat && index_id==0){
+                index_id = 1;
+                zikey = new ArrayList<>();
+            }
+
+            if(!index_stat && index_id==1 && zikey.size()>=1){
+                index_id = 2;
+                zikey = new ArrayList<>();
+            }
+
+            Elements tds = tr.select("td");
+            for (int j = 0; j < tds.size(); j++) {
+                Element data = tds.get(j);
+                String textInfo  = data.text();
+                int x1 = Integer.parseInt( data.attr("x1"));
+                int x2 = Integer.parseInt( data.attr("x2"));
+                int y1 = Integer.parseInt( data.attr("y1"));
+                int y2 = Integer.parseInt( data.attr("y2"));
+
+
+                if(!textInfo.isEmpty() && !textInfo.equals("/")){
+                    Map<String,String> dataInfo =new HashMap<String,String>();
+                    dataInfo.put("name",textInfo);
+                    dataInfo.put("x1",data.attr("x1"));
+                    dataInfo.put("x2",data.attr("x2"));
+                    dataInfo.put("y1",data.attr("y1"));
+                    dataInfo.put("y2",data.attr("y2"));
+                    zikey.add(dataInfo);
+                }else if(data.html().indexOf("input")>=0){
+
+                    List arrayList = new ArrayList<>();
+
+
+                    for(int k=zikey.size()-1;k>=0 ;k--){
+                        String name = zikey.get(k).get("name").replaceAll("[^\u4E00-\u9FA5]", "");
+                        int xx1 = Integer.parseInt( zikey.get(k).get("x1"));
+                        int xx2 = Integer.parseInt( zikey.get(k).get("x2"));
+                        int yy1 = Integer.parseInt( zikey.get(k).get("y1"));
+                        int yy2 = Integer.parseInt( zikey.get(k).get("y2"));
+
+                        // 左匹配
+                        if( yy1<=y1 && yy2>=y2 && xx2<x1 && StringUtils.isNotEmpty(name)){
+                             arrayList.add(name);
+                            if(!index_stat){
+                                break;
+                            }
+                        }
+
+                        //向 上 匹配
+                        if(index_stat){
+                            if( xx1<=x1 && xx2 >=x2 && yy2<y1 ){
+                                arrayList.add(name);
+                            }
+                        }
+                    }
+
+                    Set<String> resultSet = new HashSet<>();
+                    System.out.println(dataInfox+"==="+arrayList.size());
+                    MathUtil.getCombination(arrayList, resultSet);
+                    double maxInfo = 0;
+                    if(!resultSet.isEmpty()){
+
+                        for(WbsFormElement wbsFormElement : dataList){
+                            for(String bx : resultSet){
+                                double dataxx =  MathUtil.sim(bx,wbsFormElement.getEName());
+                                if(maxInfo < dataxx){
+                                    System.out.println("x1-x2="+x1+","+x2+"y1-y2="+y1+","+y2+bx+"="+dataxx+"_jieh="+resultSet);
+                                    data.empty().text(bx);
+                                    maxInfo = dataxx;
+                                }
+                            }
+                        }
+                    }
+                    System.out.println(maxInfo);
+                }
+            }
+        }
+
+
+        //
+       // for (Map<String,String> d:zikey){
+           // System.out.println(d.get("name")+"x1"+d.get("x1"));
+      //  }
+
+        inputStream.close();
+
+        File writefile = new File(inHtmlUrl);
+        FileUtil.writeToFile(writefile, doc.html(), Boolean.parseBoolean("UTF-8"));
+        System.out.println("完成");
+    }
+
+
+    public static List<WbsFormElement> getWbsInfo(){
+        List<WbsFormElement> elementList = new ArrayList<>();
+        WbsFormElement info = new WbsFormElement();
+        info.setEName("承包单位");
+
+        WbsFormElement info1 = new WbsFormElement();
+        info1.setEName("工程名称");
+
+        WbsFormElement info2 = new WbsFormElement();
+        info2.setEName("年月日");
+
+        WbsFormElement info3 = new WbsFormElement();
+        info3.setEName("隧道净高实测");
+
+        WbsFormElement info4 = new WbsFormElement();
+        info3.setEName("基坑尺寸设计值");
+
+
+        elementList.add(info);
+        elementList.add(info1);
+        elementList.add(info2);
+        elementList.add(info3);
+
+        return elementList;
+    }
+
+    public static void getHtmlInfo() throws IOException {
+        String thmlUrl = "/Users/hongchuangyanfa/Desktop/1539066383856304128.html";
+
+        File file = new File("/Users/hongchuangyanfa/Desktop/test001231.xlsx");
+
+        FileInputStream inputStream = new FileInputStream(file);
+        // 解析excel
+        Workbook wb = new Workbook();
+        wb.loadFromMHtml(inputStream);
+        //获取工作表
+        Worksheet sheet = wb.getWorksheets().get(0);
+        sheet.saveToHtml(thmlUrl);
+
+        // 测试
+        File file1 = ResourceUtil.getFile(thmlUrl);
+        String htmlString =  IoUtil.readToString(new FileInputStream(file1));
+
+        // 样式集合
+        Map<String ,String > styleMap = new HashMap<>();
+        // 解析 style
+        Document doc = Jsoup.parse(htmlString);
+        Element style = doc.select("style").first();
+
+        Matcher cssMatcher = Pattern.compile("(\\w+)\\s*[{]([^}]+)[}]").matcher(style.html());
+        while (cssMatcher.find()) {
+            styleMap.put(cssMatcher.group(1),cssMatcher.group(2));
+        }
+        // 解析 总行和总列
+        Element table = doc.select("table").first();
+        Elements trs = table.select("tr");
+
+        // 获取总行列数
+        int maxCol = doc.select("Col").size();
+        String [] rowData = new String[trs.size()+1];
+
+        int s_index = 0;
+        boolean index_stat = false;
+        // 横向计算
+        for(int i = 0 ;i < trs.size() ;i++) {
+            Element tr = trs.get(i);
+            Elements tds = tr.select("td");
+
+            int x_width = 0 ;
+            int y_width = 0 ;
+            //区域计算
+            for (int j = 0; j < tds.size(); j++) {
+                Element data = tds.get(j);
+                String keyId = data.attr("class");
+
+                int colspan = data.attr("COLSPAN").equals("") ? 1 : Integer.parseInt(data.attr("COLSPAN"));
+                String classInfo = styleMap.get(keyId);
+                data.removeAttr("class");
+                data.attr("style",styleMap.get(keyId).replaceAll("break-word","inherit"));
+                // 第一列
+                if(j==0 && classInfo.indexOf("border-left-style")>=0 && classInfo.indexOf("border-top-style")>=0 && classInfo.indexOf("border-bottom-style")>=0 && !index_stat){
+                    x_width +=colspan;
+                }else if(j == tds.size()-1 && classInfo.indexOf("border-right-style")>=0 && classInfo.indexOf("border-top-style")>=0 && classInfo.indexOf("border-bottom-style")>=0 && !index_stat && j>=1){
+                    x_width +=colspan;
+                }else if(classInfo.indexOf("border-top-style")>=0 && classInfo.indexOf("border-bottom-style")>=0 && !index_stat && j>=1){
+                    x_width +=colspan;
+                }
+
+                // 计算退出
+                if(j==0 && classInfo.indexOf("border-left-style")<0 && classInfo.indexOf("border-top-style")>=0 && classInfo.indexOf("border-bottom-style")<0 && index_stat && classInfo.indexOf("border-right-style")<0){
+                    y_width +=colspan;
+                }else if(j == tds.size()-1 && classInfo.indexOf("border-right-style")<0 && classInfo.indexOf("border-top-style")>=0 && classInfo.indexOf("border-bottom-style")<0 && index_stat && j>=1){
+                    y_width +=colspan;
+                }else if(classInfo.indexOf("border-top-style")>=0 && classInfo.indexOf("border-bottom-style")<0 &&index_stat && j>=1){
+                    y_width +=colspan;
+                }
+            }
+
+            if(x_width == maxCol && !index_stat && s_index==0){
+                s_index = i + 1;
+                index_stat = true ;
+            }
+
+            if(y_width == maxCol && index_stat && s_index>0){
+                s_index = i + 1;
+                index_stat = false ;
+            }
+            tr.attr("index_stat",index_stat+"");
+
+            int x= 0;
+            for (int j = 0; j < tds.size(); j++) {
+                Element data = tds.get(j);
+
+                int colspan = data.attr("COLSPAN").equals("") ? 0 : Integer.parseInt(data.attr("COLSPAN"));
+                int rowspan = data.attr("ROWSPAN").equals("") ? 0 : Integer.parseInt(data.attr("ROWSPAN"));
+
+                Map<String, String> textObject = new HashMap<>();
+                // 计算
+                int x1 =0;
+                int x2 =0;
+                int y1 =0;
+                int y2 =0;
+                //x
+                // X 坐标
+                if(colspan==0){
+                    x1 = x+1;
+                    x2 = x+1;
+                    x= x +1;
+                }else{
+                    x1 = x+1;
+                    x2 = x+colspan;
+                    x = x+colspan;
+                }
+                String textInfo = data.text().trim();
+
+                // y 坐标
+                y1=i+1;
+                if(rowspan==0){
+                    y2 = i+1;
+                }else{
+                    y2 = i+rowspan;
+                    for(int k=0;k<rowspan-1;k++){
+                        String dataInfo = rowData[k+2+i];
+                        if(dataInfo==null){
+                            dataInfo = x1+":"+x2;
+                        }else{
+                            String [] dataInfo2 = dataInfo.split(",");
+                            String dataInfo3 = dataInfo2[dataInfo2.length-1];
+                            int mx1 = Integer.parseInt(dataInfo3.split(":")[0]);
+                            int mx2 = Integer.parseInt(dataInfo3.split(":")[1]);
+                            if(mx2+1==x1){
+                                dataInfo = dataInfo+","+mx1+":"+x2;
+                            }else{
+                                dataInfo = dataInfo+","+x1+":"+x2;
+                            }
+                        }
+                        rowData[k+2+i] = dataInfo;
+                    }
+                }
+
+                String getRowInfo = rowData[y1];
+                if(getRowInfo!=null){
+                    String [] dataInfo2 = getRowInfo.split(",");
+                    if(getRowInfo.indexOf("1")>=0 && j==0){
+                        for(int m =0;m<dataInfo2.length ;m++){
+                            int mx1 = Integer.parseInt(dataInfo2[m].split(":")[0]);
+                            int mx2 = Integer.parseInt(dataInfo2[m].split(":")[1]);
+                            x = mx2;
+                        }
+                        x1 = x+x1;
+                        x2 = x+x2;
+                        x = x+1 ; //计算自己
+                    }else{
+                        for(int m =0;m<dataInfo2.length ;m++){
+                            int mx1 = Integer.parseInt(dataInfo2[m].split(":")[0]);
+                            int mx2 = Integer.parseInt(dataInfo2[m].split(":")[1]);
+                            if(x2+1 == mx1){
+                                x = mx2 ;
+                            }
+                        }
+                    }
+                }
+
+
+               // System.out.println(StringUtil.trimAllWhitespace(textInfo)+""+StringUtil.trimAllWhitespace(textInfo).length());
+                data.text(textInfo.replaceAll(" ",""));
+
+
+                // 设置td 属性
+                data.attr("trIndex",i+"");
+                data.attr("tdIndex",j+"");
+                data.attr("x1",x1+"");
+                data.attr("x2",x2+"");
+                data.attr("y1",y1+"");
+                data.attr("y2",y2+"");
+
+
+
+                // 设置文本信息
+               /* if(textInfo.indexOf("年")>=0 && textInfo.indexOf("月")>=0&& textInfo.indexOf("日")>=0){
+                    data.empty().append("<input type='time' style='width:100%;height:100%' placeholder=''> </input>");
+                }*/
+                if(textInfo.isEmpty() || textInfo.equals("/") || textInfo.equals("—") || textInfo.equals("—") || textInfo.equals("-")){
+                    if(index_stat){
+                        data.empty().append("<input type='text' style='width:100%;height:100%' placeholder=''> </input>");
+                    }else{
+                        if(j==0 ){
+                            if(colspan ==maxCol && i>=1 && i<=2){
+                                data.empty().append("<input type='text' style='width:100%;height:100%' placeholder=''> </input>");
+                            }
+                        }else{
+                            Element bforData = tds.get(j-1);
+                            if(!bforData.text().isEmpty()){
+                                data.empty().append("<input type='text' style='width:100%;height:100%' placeholder=''> </input>");
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        // 写入
+        inputStream.close();
+        String inHtmlUrl = "/Users/hongchuangyanfa/Desktop/123654.html";
+        //saveAsFileWriter(doc.html(),inHtmlUrl);
+        File writefile = new File(inHtmlUrl);
+        FileUtil.writeToFile(writefile, doc.html(), Boolean.parseBoolean("UTF-8"));
+    }
+}

+ 33 - 16
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/LinkdataInfoController.java

@@ -27,6 +27,7 @@ import org.springblade.core.mp.support.Condition;
 import org.springblade.core.mp.support.Query;
 import org.springblade.core.tool.api.R;
 import org.springblade.core.tool.utils.Func;
+import org.springblade.manager.service.IWbsFormElementService;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.bind.annotation.RequestParam;
 import com.baomidou.mybatisplus.core.metadata.IPage;
@@ -49,10 +50,11 @@ public class LinkdataInfoController extends BladeController {
 
 	private final ILinkdataInfoService linkdataInfoService;
 
+	private final IWbsFormElementService wbsFormElementService;
 	/**
 	 * 详情
 	 */
-/*	@GetMapping("/detail")
+	@GetMapping("/detail")
 	@ApiOperationSupport(order = 1)
 	@ApiOperation(value = "详情", notes = "传入linkdataInfo")
 	public R<LinkdataInfo> detail(LinkdataInfo linkdataInfo) {
@@ -60,6 +62,8 @@ public class LinkdataInfoController extends BladeController {
 		return R.data(detail);
 	}
 
+
+/*
 	*//**
 	 * 分页 清表解析字段信息
 	 *//*
@@ -80,11 +84,11 @@ public class LinkdataInfoController extends BladeController {
 	public R<IPage<LinkdataInfoVO>> page(LinkdataInfoVO linkdataInfo, Query query) {
 		IPage<LinkdataInfoVO> pages = linkdataInfoService.selectLinkdataInfoPage(Condition.getPage(query), linkdataInfo);
 		return R.data(pages);
-	}
+	}*/
 
-	*//**
+	/**
 	 * 新增 清表解析字段信息
-	 *//*
+	 */
 	@PostMapping("/save")
 	@ApiOperationSupport(order = 4)
 	@ApiOperation(value = "新增", notes = "传入linkdataInfo")
@@ -92,9 +96,9 @@ public class LinkdataInfoController extends BladeController {
 		return R.status(linkdataInfoService.save(linkdataInfo));
 	}
 
-	*//**
+	/**
 	 * 修改 清表解析字段信息
-	 *//*
+	 */
 	@PostMapping("/update")
 	@ApiOperationSupport(order = 5)
 	@ApiOperation(value = "修改", notes = "传入linkdataInfo")
@@ -102,35 +106,48 @@ public class LinkdataInfoController extends BladeController {
 		return R.status(linkdataInfoService.updateById(linkdataInfo));
 	}
 
-	*//**
+	/**
 	 * 新增或修改 清表解析字段信息
-	 *//*
+	 */
 	@PostMapping("/submit")
 	@ApiOperationSupport(order = 6)
 	@ApiOperation(value = "新增或修改", notes = "传入linkdataInfo")
 	public R submit(@Valid @RequestBody LinkdataInfo linkdataInfo) {
+
 		return R.status(linkdataInfoService.saveOrUpdate(linkdataInfo));
-	}*/
+	}
 
 	
 	/**
 	 * 删除 清表解析字段信息
 	 */
-/*	@PostMapping("/remove")
+	@PostMapping("/remove")
 	@ApiOperationSupport(order = 7)
 	@ApiOperation(value = "逻辑删除", notes = "传入ids")
 	public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {
-		return R.status(linkdataInfoService.deleteLogic(Func.toLongList(ids)));
-	}*/
+		linkdataInfoService.removeByIds(Func.toLongList(ids));
+		return R.success("成功!");
+	}
 
 	/**
-	 *  获取字段信息 下拉框
+	 *  获取excel字段信息 下拉框
 	 */
 	@GetMapping("/getColByTabId")
-	@ApiOperationSupport(order = 7)
-	@ApiOperation(value = "获取字段信息", notes = "传入ids")
-	public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String tabId) {
+	@ApiOperationSupport(order = 8)
+	@ApiOperation(value = "获取excel字段信息", notes = "传入ids")
+	public R getColByTabId(@ApiParam(value = "主键集合", required = true) @RequestParam String tabId) {
 		return R.data(linkdataInfoService.getColSelect(tabId));
 	}
 
+
+	/**
+	 *  获取元素信息通过tableId 下拉框
+	 */
+	@GetMapping("/getElementInfoByTabId")
+	@ApiOperationSupport(order = 8)
+	@ApiOperation(value = "获取excel字段信息", notes = "传入ids")
+	public R getElementInfo(@ApiParam(value = "主键集合", required = true) @RequestParam String tabId) {
+		return R.data(wbsFormElementService.selectElementListByFid(tabId));
+	}
+
 }

+ 127 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/SignPfxDeputyController.java

@@ -0,0 +1,127 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.manager.controller;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import lombok.AllArgsConstructor;
+import javax.validation.Valid;
+
+import org.springblade.core.mp.support.Condition;
+import org.springblade.core.mp.support.Query;
+import org.springblade.core.tool.api.R;
+import org.springblade.core.tool.utils.Func;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.bind.annotation.RequestParam;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import org.springblade.manager.entity.SignPfxDeputy;
+import org.springblade.manager.vo.SignPfxDeputyVO;
+import org.springblade.manager.service.ISignPfxDeputyService;
+import org.springblade.core.boot.ctrl.BladeController;
+
+/**
+ *  控制器
+ *
+ * @author BladeX
+ * @since 2022-06-28
+ */
+@RestController
+@AllArgsConstructor
+@RequestMapping("/signpfxdeputy")
+@Api(value = "", tags = "接口")
+public class SignPfxDeputyController extends BladeController {
+
+	private final ISignPfxDeputyService signPfxDeputyService;
+
+	/**
+	 * 详情
+	 */
+	@GetMapping("/detail")
+	@ApiOperationSupport(order = 1)
+	@ApiOperation(value = "详情", notes = "传入signPfxDeputy")
+	public R<SignPfxDeputy> detail(SignPfxDeputy signPfxDeputy) {
+		SignPfxDeputy detail = signPfxDeputyService.getOne(Condition.getQueryWrapper(signPfxDeputy));
+		return R.data(detail);
+	}
+
+	/**
+	 * 分页 
+	 */
+	@GetMapping("/list")
+	@ApiOperationSupport(order = 2)
+	@ApiOperation(value = "分页", notes = "传入signPfxDeputy")
+	public R<IPage<SignPfxDeputy>> list(SignPfxDeputy signPfxDeputy, Query query) {
+		IPage<SignPfxDeputy> pages = signPfxDeputyService.page(Condition.getPage(query), Condition.getQueryWrapper(signPfxDeputy));
+		return R.data(pages);
+	}
+
+	/**
+	 * 自定义分页 
+	 */
+	@GetMapping("/page")
+	@ApiOperationSupport(order = 3)
+	@ApiOperation(value = "分页", notes = "传入signPfxDeputy")
+	public R<IPage<SignPfxDeputyVO>> page(SignPfxDeputyVO signPfxDeputy, Query query) {
+		IPage<SignPfxDeputyVO> pages = signPfxDeputyService.selectSignPfxDeputyPage(Condition.getPage(query), signPfxDeputy);
+		return R.data(pages);
+	}
+
+	/**
+	 * 新增 
+	 */
+	@PostMapping("/save")
+	@ApiOperationSupport(order = 4)
+	@ApiOperation(value = "新增", notes = "传入signPfxDeputy")
+	public R save(@Valid @RequestBody SignPfxDeputy signPfxDeputy) {
+		return R.status(signPfxDeputyService.save(signPfxDeputy));
+	}
+
+	/**
+	 * 修改 
+	 */
+	@PostMapping("/update")
+	@ApiOperationSupport(order = 5)
+	@ApiOperation(value = "修改", notes = "传入signPfxDeputy")
+	public R update(@Valid @RequestBody SignPfxDeputy signPfxDeputy) {
+		return R.status(signPfxDeputyService.updateById(signPfxDeputy));
+	}
+
+	/**
+	 * 新增或修改 
+	 */
+	@PostMapping("/submit")
+	@ApiOperationSupport(order = 6)
+	@ApiOperation(value = "新增或修改", notes = "传入signPfxDeputy")
+	public R submit(@Valid @RequestBody SignPfxDeputy signPfxDeputy) {
+		return R.status(signPfxDeputyService.saveOrUpdate(signPfxDeputy));
+	}
+
+	
+	/**
+	 * 删除 
+	 */
+	@PostMapping("/remove")
+	@ApiOperationSupport(order = 7)
+	@ApiOperation(value = "逻辑删除", notes = "传入ids")
+	public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {
+		return R.status(signPfxDeputyService.deleteLogic(Func.toLongList(ids)));
+	}
+
+	
+}

+ 211 - 16
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/SignPfxFileController.java

@@ -16,30 +16,39 @@
  */
 package org.springblade.manager.controller;
 
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import io.swagger.annotations.*;
 import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
 import lombok.AllArgsConstructor;
 import javax.validation.Valid;
 
+import org.springblade.common.utils.SnowFlakeUtil;
 import org.springblade.core.mp.support.Condition;
 import org.springblade.core.mp.support.Query;
 import org.springblade.core.tool.api.R;
 import org.springblade.core.tool.utils.Func;
+import org.springblade.manager.dto.SaveUserInfoByProjectDTO;
+import org.springblade.manager.entity.ContractInfo;
 import org.springblade.manager.entity.ProjectInfo;
-import org.springblade.manager.service.IProjectInfoService;
-import org.springblade.manager.vo.SingPfxManagementVO;
+import org.springblade.manager.entity.SignPfxDeputy;
+import org.springblade.manager.service.*;
+import org.springblade.manager.vo.*;
+import org.springblade.system.entity.Role;
 import org.springblade.system.feign.ISysClient;
+import org.springblade.system.user.entity.User;
 import org.springblade.system.vo.RoleVO;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.bind.annotation.RequestParam;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import org.springblade.manager.entity.SignPfxFile;
-import org.springblade.manager.vo.SignPfxFileVO;
-import org.springblade.manager.service.ISignPfxFileService;
 import org.springblade.core.boot.ctrl.BladeController;
 
+import java.util.ArrayList;
+import java.util.Iterator;
 import java.util.List;
+import java.util.stream.Collectors;
 
 /**
  * 个人/企业证书信息表 控制器
@@ -50,23 +59,151 @@ import java.util.List;
 @RestController
 @AllArgsConstructor
 @RequestMapping("/signPfxFile")
-@Api(value = "个人/企业证书信息表", tags = "个人/企业证书信息表接口")
+@Api(value = "个人、企业证书信息表", tags = "个人、企业证书信息表接口")
 public class SignPfxFileController extends BladeController {
 
 	private final ISignPfxFileService signPfxFileService;
 
 	private final IProjectInfoService projectInfoService;
 
+	private final IContractInfoService contractInfoService;
+
+	private final SaveUserInfoByProjectService saveUserInfoByProjectService;
+
 	private final ISysClient sysClient;
 
+	private final ISignPfxDeputyService signPfxDeputyService;
+
+	/**
+	 * 获取当前系统下分配的一级角色
+	 * @return 结果
+	 */
+	@GetMapping("/queryRole")
+	@ApiOperationSupport(order = 12)
+	@ApiOperation(value = "获取当前系统下分配的一级角色")
+	public R<List<RoleVO>> queryRole(){
+		 return R.data(this.sysClient.search().getData());
+	}
+
+	/**
+	 * 获取当前系统下所有用户
+	 * @return 结果
+	 */
+	@GetMapping("/findUserByName")
+	@ApiOperationSupport(order = 11)
+	@ApiOperation(value = "获取当前系统下所有用户")
+	public R<List<User>> findUserByName(){
+		return R.data(this.contractInfoService.findUserByName(""));
+	}
+
+
+	/**
+	 * 获取当前项目及其所有合同段
+	 * @return 项目及合同段列表
+	 */
+	@GetMapping("/queryProjectAndContract")
+	@ApiOperationSupport(order = 10)
+	@ApiOperation(value = "获取当前项目及其所有合同段")
+	public R<List<ProjectInfoVO>> queryProjectAndContract(){
+		//结果集合
+		List<ProjectInfoVO> result = new ArrayList<>();
+
+		//获取项目列表
+		List<ProjectInfo> projectResult = this.projectInfoService.list(Wrappers.<ProjectInfo>lambdaQuery().eq(ProjectInfo::getIsDeleted, 0));
+		if(projectResult != null && projectResult.size() > 0){
+			String projectIds = String.join(",", JSONArray.parseArray(JSONObject.toJSONString(projectResult.stream().map(ProjectInfo::getId).distinct().collect(Collectors.toList())), String.class));
+			//获取合同段
+			List<ContractInfo> contractInfos = this.contractInfoService.findContractInProject(projectIds);
+			if(contractInfos != null && contractInfos.size() > 0){
+				//转换实体
+				result = JSONArray.parseArray(JSONObject.toJSONString(projectResult), ProjectInfoVO.class);
+				List<ContractInfoVO> contractInfoVOS = JSONArray.parseArray(JSONObject.toJSONString(contractInfos), ContractInfoVO.class);
+				//设置合同段信息
+				result.forEach(project -> {
+					project.setName(project.getProjectName());
+					//获取合同段
+					Iterator<ContractInfoVO> iterator = contractInfoVOS.iterator();
+					while (iterator.hasNext()){
+						ContractInfoVO next = iterator.next();
+						next.setName(next.getContractName());
+						if(project.getId().toString().equals(next.getPId())){
+							project.getContractInfoList().add(next);
+							iterator.remove();
+						}
+					}
+				});
+			}
+		}
+
+		return R.data(result);
+	}
+
 	/**
 	 * 获取系统所有角色划分
 	 */
 	@GetMapping("/queryAllRoleList")
 	@ApiOperationSupport(order = 9)
 	@ApiOperation(value = "获取系统所有角色划分")
-	public R<List<RoleVO>> queryAllRoleList(){
-		return this.sysClient.search(null, null);
+	public R<List<RoleSignPfxUserVO>> queryAllRoleList(@RequestParam String contractId){
+		//获取当前系统配置的角色划分
+		List<RoleVO> roleVOS = this.sysClient.search().getData();
+		//获取项目人员
+		List<SaveUserInfoByProjectDTO> contractUserList = this.saveUserInfoByProjectService.list(Wrappers.<SaveUserInfoByProjectDTO>lambdaQuery().eq(SaveUserInfoByProjectDTO::getContractId, contractId).eq(SaveUserInfoByProjectDTO::getIsDeleted, 0));
+
+		//返回结果
+		List<RoleSignPfxUserVO> result = new ArrayList<>();
+		//企业章
+//		RoleSignPfxUserVO pfxUnitVo = new RoleSignPfxUserVO();
+//		pfxUnitVo.setRoleId(1L);
+//		pfxUnitVo.setRoleName("单位证书");
+//		List<SignPfxFile> unitPfxList = this.signPfxFileService.list(Wrappers.<SignPfxFile>lambdaQuery().eq(SignPfxFile::getContractId, contractId).eq(SignPfxFile::getIsDeleted, 0));
+//		if(unitPfxList != null && unitPfxList.size() > 0){
+//			pfxUnitVo.setSignPfxFileList(unitPfxList);
+//		}
+//		result.add(pfxUnitVo);
+
+		//循环角色,对项目人员进行分组
+		for(RoleVO vo : roleVOS){
+			//设置实体
+			RoleSignPfxUserVO pfxUserVo = new RoleSignPfxUserVO();
+			pfxUserVo.setRoleId(vo.getId());
+			pfxUserVo.setRoleName(vo.getRoleName());
+
+			//处理子节点
+			List<RoleVO> childRoles =  vo.getChildren();
+			if(childRoles != null && childRoles.size() > 0){
+				for(RoleVO childVo : childRoles){
+					//设置实体
+					RoleSignPfxUserVO childPfxUserVo = new RoleSignPfxUserVO();
+					childPfxUserVo.setRoleId(childVo.getId());
+					childPfxUserVo.setRoleName(childVo.getRoleName());
+
+					//循环项目人员,获取个人证书,如果没有个人证书则删除
+					Iterator<SaveUserInfoByProjectDTO> iterator = contractUserList.iterator();
+					while (iterator.hasNext()){
+						SaveUserInfoByProjectDTO next = iterator.next();
+
+						if(next.getRoleId().equals(childVo.getId().toString())){
+							//角色相符
+							SignPfxFile userSignPfx = this.signPfxFileService.getOne(Wrappers.<SignPfxFile>lambdaQuery().eq(SignPfxFile::getCertificateUserId, next.getUserId()));
+							if(userSignPfx == null){
+								iterator.remove();
+								continue;
+							}
+							//存在证书则设置进结果对象的证书集合中
+							childPfxUserVo.getSignPfxFileList().add(userSignPfx);
+						}
+					}
+					//设置子集
+					pfxUserVo.getChildRoleList().add(childPfxUserVo);
+				}
+			}
+
+			//设置结果
+			result.add(pfxUserVo);
+		}
+
+		return R.data(result);
 	}
 
 	/**
@@ -82,11 +219,16 @@ public class SignPfxFileController extends BladeController {
 	/**
 	 * 证书管理分页
 	 */
-	@PostMapping("/singPfxManagementPage")
+	@GetMapping("/singPfxManagementPage")
 	@ApiOperationSupport(order = 7)
 	@ApiOperation(value = "证书管理分页")
 	@ApiImplicitParam(name = "vo", value = "必传current、size, 选传projectId")
-	public R<IPage<SingPfxManagementVO>> singPfxManagementPage(SingPfxManagementVO vo){
+	public R<IPage<SingPfxManagementVO>> singPfxManagementPage(@RequestParam Integer current, @RequestParam Integer size, @RequestParam Long contractId){
+		SingPfxManagementVO vo = new SingPfxManagementVO();
+		vo.setCurrent(current);
+		vo.setSize(size);
+		vo.setContractId(contractId);
+
 		Query query = new Query();
 		query.setSize(vo.getSize());
 		query.setCurrent(vo.getCurrent());
@@ -101,8 +243,15 @@ public class SignPfxFileController extends BladeController {
 	@ApiOperationSupport(order = 6)
 	@ApiOperation(value = "获取详情数据")
 	@ApiImplicitParam(name = "id", value = "列表数据主键ID", required = true)
-	public R<SignPfxFile> getById(Long id){
-		return R.data(this.signPfxFileService.getById(id));
+	public R<SignPfxFileVO> getById(Long id){
+		//查询数据
+		SignPfxFile data = this.signPfxFileService.getById(id);
+		//实体转换
+		SignPfxFileVO vo = JSONObject.parseObject(JSONObject.toJSONString(data), SignPfxFileVO.class);
+		List<SignPfxDeputy> deputies = this.signPfxDeputyService.list(Wrappers.<SignPfxDeputy>lambdaQuery().eq(SignPfxDeputy::getSignPfxFileId, id).eq(SignPfxDeputy::getIsDeleted, 0));
+		vo.setSignPfxDeputieList(deputies);
+
+		return R.data(vo);
 	}
 
 	/**
@@ -142,8 +291,13 @@ public class SignPfxFileController extends BladeController {
 	@PostMapping("/save")
 	@ApiOperationSupport(order = 2)
 	@ApiOperation(value = "新增", notes = "传入signPfxFile")
-	public R save(@Valid @RequestBody SignPfxFile signPfxFile) {
-		return R.status(this.signPfxFileService.save(signPfxFile));
+	public R save(@Valid @RequestBody SignPfxFileVO vo) {
+
+		if(new Integer("2").equals(vo.getCertificateType())){
+			this.saveSignPfxDeputy(vo);
+		}
+
+		return R.status(this.signPfxFileService.save(vo));
 	}
 
 	/**
@@ -152,10 +306,51 @@ public class SignPfxFileController extends BladeController {
 	@PostMapping("/update")
 	@ApiOperationSupport(order = 3)
 	@ApiOperation(value = "修改", notes = "传入signPfxFile")
-	public R update(@Valid @RequestBody SignPfxFile signPfxFile) {
-		return R.status(this.signPfxFileService.updateById(signPfxFile));
+	public R update(@Valid @RequestBody SignPfxFileVO vo) {
+		if(new Integer("2").equals(vo.getCertificateType())){
+			//查询旧数据
+			SignPfxFile oldData = this.signPfxFileService.getById(vo.getId());
+			if(!vo.getProjectContractRole().trim().equals(oldData.getProjectContractRole().trim())){
+				//如果不匹配,先删除
+				this.signPfxDeputyService.update(Wrappers.<SignPfxDeputy>lambdaUpdate().set(SignPfxDeputy::getIsDeleted, 1).eq(SignPfxDeputy::getSignPfxFileId, vo.getId()));
+				//再重新生成
+				this.saveSignPfxDeputy(vo);
+			}
+		}
+		return R.status(this.signPfxFileService.updateById(vo));
 	}
-	
+
+	private void saveSignPfxDeputy(SignPfxFileVO vo){
+		String[] projectContractRoles = vo.getProjectContractRole().trim().split(",");
+		//从表数据
+		List<SignPfxDeputy> insertList = new ArrayList<>();
+		vo.setId(SnowFlakeUtil.getId());
+		for(String projectContractRole : projectContractRoles){
+			String[] array = projectContractRole.split("-");
+			//查询项目信息
+			ProjectInfo projectInfo = this.projectInfoService.getById(array[0]);
+			//获取合同段ID
+			ContractInfo contractInfo = this.contractInfoService.getById(array[1]);
+			//获取角色
+			Role role = this.sysClient.getRole(Long.parseLong(array[2])).getData();
+
+			//新增从表数据
+			SignPfxDeputy signPfxDeputy = new SignPfxDeputy();
+			signPfxDeputy.setSignPfxFileId(vo.getId());
+			signPfxDeputy.setProjectId(projectInfo.getId());
+			signPfxDeputy.setProjectName(projectInfo.getProjectName());
+			signPfxDeputy.setContractId(contractInfo.getId());
+			signPfxDeputy.setContractName(contractInfo.getContractName());
+			signPfxDeputy.setRoleId(role.getId());
+			signPfxDeputy.setRoleName(role.getRoleName());
+
+			insertList.add(signPfxDeputy);
+		}
+		if(insertList.size() > 0){
+			this.signPfxDeputyService.saveBatch(insertList);
+		}
+	}
+
 	/**
 	 * 删除 个人/企业证书信息表
 	 */

+ 29 - 2
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/ProjectInfoMapper.xml

@@ -38,14 +38,41 @@
         <result column="project_name" property="projectName"/>
         <result column="personalCount" property="personalCount"/>
         <result column="project_name" property="projectName"/>
+        <result column="contractId" property="contractId"/>
     </resultMap>
 
     <select id="singPfxManagementPage" resultMap="singPfxManagementResultMap">
         select
             pi.id,
             pi.project_name,
-            count(select id from m_sign_pfx_file where is_deleted = 0 and project_id = pi.id and certificate_type = 1) AS personalCount,
-            count(select id from m_sign_pfx_file where is_deleted = 0 and project_id = pi.id and certificate_type = 2) AS enterpriseCount
+            count(
+              (
+                select
+                  spf.id
+                from
+                  m_sign_pfx_file AS spf
+                left join m_project_assignment_user AS pau on spf.certificate_user_id = pau.user_id
+                where
+                  spf.is_deleted = 0
+                and pau.is_deleted = 0
+                and pau.project_id = pi.id
+                and spf.certificate_type = 1
+              )
+            ) AS personalCount,
+            count(
+              (
+                select
+                  spf.id
+                from m_sign_pfx_file AS spf
+                left join m_sign_pfx_deputy AS spd ON spf.id = spd.sign_pfx_file_id
+                where
+                  spf.is_deleted = 0
+                and spd.is_deleted = 0
+                and spd.project_id = pi.id
+                and spf.certificate_type = 2
+              )
+            ) AS enterpriseCount,
+            (select id from m_contract_info where is_deleted = 0 and p_id = pi.id limit 1) AS contractId
         from m_project_info AS pi where pi.is_deleted = 0
         <if test="vo.projectId != null">
             and pi.id = #{vo.projectId}

+ 9 - 1
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/SaveUserInfoByProjectMapper.xml

@@ -26,7 +26,15 @@
     </select>
 
     <select id="queryProjectBusinessUser" resultMap="contractInfoResultMap">
-        select * from m_project_assignment_user where is_deleted = 0 and project_id = #{projectId} and contract_id is NULL
+        select
+          pau.*
+        from m_project_assignment_user AS pau
+        LEFT JOIN blade_role AS br ON pau.role_id = br.id
+        where
+          pau.is_deleted = 0
+        and pau.project_id = #{projectId}
+        and pau.contract_id = #{contractId}
+        AND br.id is null
     </select>
 
 </mapper>

+ 42 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/SignPfxDeputyMapper.java

@@ -0,0 +1,42 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.manager.mapper;
+
+import org.springblade.manager.entity.SignPfxDeputy;
+import org.springblade.manager.vo.SignPfxDeputyVO;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import java.util.List;
+
+/**
+ *  Mapper 接口
+ *
+ * @author BladeX
+ * @since 2022-06-28
+ */
+public interface SignPfxDeputyMapper extends BaseMapper<SignPfxDeputy> {
+
+	/**
+	 * 自定义分页
+	 *
+	 * @param page
+	 * @param signPfxDeputy
+	 * @return
+	 */
+	List<SignPfxDeputyVO> selectSignPfxDeputyPage(IPage page, SignPfxDeputyVO signPfxDeputy);
+
+}

+ 29 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/SignPfxDeputyMapper.xml

@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="org.springblade.manager.mapper.SignPfxDeputyMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="signPfxDeputyResultMap" type="org.springblade.manager.entity.SignPfxDeputy">
+        <result column="id" property="id"/>
+        <result column="create_user" property="createUser"/>
+        <result column="create_dept" property="createDept"/>
+        <result column="create_time" property="createTime"/>
+        <result column="update_user" property="updateUser"/>
+        <result column="update_time" property="updateTime"/>
+        <result column="status" property="status"/>
+        <result column="is_deleted" property="isDeleted"/>
+        <result column="sign_pfx_file_id" property="signPfxFileId"/>
+        <result column="project_id" property="projectId"/>
+        <result column="project_name" property="projectName"/>
+        <result column="contract_id" property="contractId"/>
+        <result column="contract_name" property="contractName"/>
+        <result column="role_id" property="roleId"/>
+        <result column="role_name" property="roleName"/>
+    </resultMap>
+
+
+    <select id="selectSignPfxDeputyPage" resultMap="signPfxDeputyResultMap">
+        select * from m_sign_pfx_deputy where is_deleted = 0
+    </select>
+
+</mapper>

+ 2 - 2
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/SignPfxFileMapper.xml

@@ -18,11 +18,11 @@
         <result column="certificate_number" property="certificateNumber"/>
         <result column="certificate_password" property="certificatePassword"/>
         <result column="certificate_file_url" property="certificateFileUrl"/>
+        <result column="enterprise_unified_code" property="enterpriseUnifiedCode"/>
         <result column="signature_file_url" property="signatureFileUrl"/>
         <result column="certificate_type" property="certificateType"/>
         <result column="is_register" property="isRegister"/>
-        <result column="project_id" property="projectId"/>
-        <result column="contract_id" property="contractId"/>
+        <result column="project_contract_role" property="projectContractRole"/>
     </resultMap>
 
     <select id="countSignPfxFile" resultType="java.lang.Integer">

+ 41 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/service/ISignPfxDeputyService.java

@@ -0,0 +1,41 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.manager.service;
+
+import org.springblade.manager.entity.SignPfxDeputy;
+import org.springblade.manager.vo.SignPfxDeputyVO;
+import org.springblade.core.mp.base.BaseService;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+
+/**
+ *  服务类
+ *
+ * @author BladeX
+ * @since 2022-06-28
+ */
+public interface ISignPfxDeputyService extends BaseService<SignPfxDeputy> {
+
+	/**
+	 * 自定义分页
+	 *
+	 * @param page
+	 * @param signPfxDeputy
+	 * @return
+	 */
+	IPage<SignPfxDeputyVO> selectSignPfxDeputyPage(IPage<SignPfxDeputyVO> page, SignPfxDeputyVO signPfxDeputy);
+
+}

+ 28 - 1
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/FormulaServiceImpl.java

@@ -128,7 +128,34 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
                     }
                 }
             }
-        System.out.println();
+        System.out.println("执行结束");
+    }
+
+
+    public static void slice(Map<String,Object> variables,String formula){
+            int min =0;
+        Map<String,Object> currentMap = new HashMap<>();
+        Map<String,List<Object>> massMap = new HashMap<>();
+        for(Map.Entry<String,Object> entry:variables.entrySet()){
+                if(entry.getValue() instanceof  List){
+                    List<Object> tmp = (List<Object>) entry.getValue();
+                    if(min==0){
+                        min=tmp.size();
+                    }else{
+                        min= Math.min(min,tmp.size());
+                    }
+                    massMap.put(entry.getKey(),tmp);
+                }else{
+                    currentMap.put(entry.getKey(),entry.getValue());
+                }
+        }
+        for(int i=0;i<min;i++){
+                for(Map.Entry<String,List<Object>> e:massMap.entrySet()){
+                    currentMap.put(e.getKey(),e.getValue().get(i));
+                }
+            Object data  = Expression.parse(formula).calculate(currentMap);
+
+        }
     }
 
     public static final String WP_REG= "(?<=P\\[)[^]]+(?=\\])";

+ 41 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/SignPfxDeputyServiceImpl.java

@@ -0,0 +1,41 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.manager.service.impl;
+
+import org.springblade.manager.entity.SignPfxDeputy;
+import org.springblade.manager.vo.SignPfxDeputyVO;
+import org.springblade.manager.mapper.SignPfxDeputyMapper;
+import org.springblade.manager.service.ISignPfxDeputyService;
+import org.springblade.core.mp.base.BaseServiceImpl;
+import org.springframework.stereotype.Service;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+
+/**
+ *  服务实现类
+ *
+ * @author BladeX
+ * @since 2022-06-28
+ */
+@Service
+public class SignPfxDeputyServiceImpl extends BaseServiceImpl<SignPfxDeputyMapper, SignPfxDeputy> implements ISignPfxDeputyService {
+
+	@Override
+	public IPage<SignPfxDeputyVO> selectSignPfxDeputyPage(IPage<SignPfxDeputyVO> page, SignPfxDeputyVO signPfxDeputy) {
+		return page.setRecords(baseMapper.selectSignPfxDeputyPage(page, signPfxDeputy));
+	}
+
+}

+ 2 - 2
blade-service/blade-system/src/main/java/org/springblade/system/feign/SysClient.java

@@ -56,8 +56,8 @@ public class SysClient implements ISysClient {
 	private final IRegionService regionService;
 
 	@Override
-	public R<List<RoleVO>> search(String roleName, Long parentId) {
-		return R.data(this.roleService.search(roleName, parentId));
+	public R<List<RoleVO>> search() {
+		return R.data(this.roleService.search(null, null));
 	}
 
 	@Override

+ 2 - 2
blade-service/blade-system/src/main/java/org/springblade/system/mapper/MenuMapper.xml

@@ -250,7 +250,7 @@
         is_deleted = 0 and id IN (
         SELECT parent_id FROM blade_menu
         WHERE ( category = 2 AND id IN ( SELECT menu_id FROM blade_role_menu WHERE role_id IN
-        <foreach collection="list" index="index" item="item" open="(" separator="," close=")">
+        <foreach collection="param1" index="index" item="item" open="(" separator="," close=")">
             #{item}
         </foreach>
         ) ) )
@@ -272,7 +272,7 @@
         blade_menu
         WHERE
         is_deleted = 0 and  category = 2 AND id IN ( SELECT menu_id FROM blade_role_menu WHERE role_id IN
-        <foreach collection="list" index="index" item="item" open="(" separator="," close=")">
+        <foreach collection="param1" index="index" item="item" open="(" separator="," close=")">
             #{item}
         </foreach>)
         and sys_id =(SELECT id from blade_client where client_id=#{param2})