浏览代码

Merge branch 'lvy' into test-merge

# Conflicts:
#	blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ArchivesAutoServiceImpl.java
#	blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsTreeContractMapper.java
lvy 3 周之前
父节点
当前提交
76dd5f6a26
共有 42 个文件被更改,包括 775 次插入186 次删除
  1. 10 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/ParameterElement.java
  2. 3 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/WbsTreeContract.java
  3. 2 2
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/feign/TableFileClient.java
  4. 4 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/feign/WbsParamClient.java
  5. 1 1
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/TextdictInfoVO.java
  6. 0 1
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ArchivesAutoServiceImpl.java
  7. 19 38
      blade-service/blade-business/src/main/java/org/springblade/business/controller/InformationWriteQueryController.java
  8. 2 2
      blade-service/blade-business/src/main/java/org/springblade/business/controller/MessageWarningController.java
  9. 2 2
      blade-service/blade-business/src/main/java/org/springblade/business/controller/StandardInfoController.java
  10. 2 0
      blade-service/blade-business/src/main/java/org/springblade/business/controller/TrialDetectionController.java
  11. 2 0
      blade-service/blade-business/src/main/java/org/springblade/business/controller/TrialMaterialController.java
  12. 1 1
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/InformationQueryMapper.xml
  13. 1 1
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/StandardInfoMapper.java
  14. 5 4
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/StandardInfoMapper.xml
  15. 1 0
      blade-service/blade-business/src/main/java/org/springblade/business/service/ITrialSelfInspectionRecordService.java
  16. 1 1
      blade-service/blade-business/src/main/java/org/springblade/business/service/StandardInfoService.java
  17. 1 1
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/ArchiveFileServiceImpl.java
  18. 15 5
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TaskServiceImpl.java
  19. 22 1
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TrialMaterialMobilizationServiceImpl.java
  20. 8 9
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TrialSelfInspectionRecordServiceImpl.java
  21. 2 2
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/UStandardInfoServiceImpl.java
  22. 11 1
      blade-service/blade-business/src/main/java/org/springblade/business/utils/PDFUtil.java
  23. 1 1
      blade-service/blade-e-visa/src/main/java/org/springblade/evisa/service/impl/EVDataServiceImpl.java
  24. 22 2
      blade-service/blade-e-visa/src/main/java/org/springblade/evisa/utils/PDFUtils.java
  25. 9 8
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ExcelTabController.java
  26. 2 2
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/NodeBaseInfoController.java
  27. 2 2
      blade-service/blade-manager/src/main/java/org/springblade/manager/feign/TableFileClientImpl.java
  28. 7 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/feign/WbsParamClientImpl.java
  29. 2 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/TextdictInfoMapper.java
  30. 3 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/TextdictInfoMapper.xml
  31. 1 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/INodeBaseInfoService.java
  32. 6 4
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ArchiveTreeContractServiceImpl.java
  33. 55 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ExcelTabServiceImpl.java
  34. 106 26
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/NodeBaseInfoServiceImpl.java
  35. 1 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/SignConfigServiceImpl.java
  36. 1 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/TableInfoServiceImpl.java
  37. 103 20
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/TextdictInfoServiceImpl.java
  38. 8 2
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsFormElementServiceImpl.java
  39. 3 21
      blade-service/blade-manager/src/main/java/org/springblade/manager/utils/PdfAddContextUtils.java
  40. 2 2
      blade-service/blade-meter/src/main/java/org/springblade/meter/controller/TaskController.java
  41. 268 6
      blade-service/blade-repair/src/main/java/org/springblade/repair/controller/CheckAndRepairController.java
  42. 58 15
      blade-service/blade-user/src/main/java/org/springblade/system/user/service/impl/UserServiceImpl.java

+ 10 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/ParameterElement.java

@@ -58,6 +58,16 @@ public class ParameterElement extends BaseEntity {
 	*/
 		private String contractId;
 
+	private String nodeId;
 
+	/**
+	 * 参数类型
+	 */
+	private String paramType;
+
+	/**
+	 * 参数
+	 */
+	private String parameter;
 
 }

+ 3 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/WbsTreeContract.java

@@ -216,6 +216,9 @@ public class WbsTreeContract extends BaseEntity {
     @ApiModelProperty(value = "原id,如果当前字段有数据则说明这条数据是复制节点")
     private String oldId;
 
+    @ApiModelProperty(value = "被复制节点p_key_id")
+    private String copyPkId;
+
     /**
      * 表单是否上传附件1否
      */

+ 2 - 2
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/feign/TableFileClient.java

@@ -29,7 +29,7 @@ public interface TableFileClient {
     @PostMapping(API_PREFIX + "/saveBatch")
     boolean saveBatch(@RequestBody List<TableFile> newFiles);
 
-    @GetMapping(API_PREFIX + "/getTabFilesByTabIds")
-    List<TableFile> getTabFilesByTabIds(@RequestParam String tabFileIds);
+    @PostMapping(API_PREFIX + "/getTabFilesByTabIds")
+    List<TableFile> getTabFilesByTabIds(@RequestBody List<String> tabFileIds);
 
 }

+ 4 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/feign/WbsParamClient.java

@@ -9,6 +9,8 @@ import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestParam;
 
+import java.util.List;
+
 import static org.springblade.core.launch.constant.AppConstant.APPLICATION_NAME_PREFIX;
 
 @FeignClient(value = APPLICATION_NAME_PREFIX + "manager")
@@ -24,6 +26,8 @@ public interface WbsParamClient {
     @GetMapping(API_PREFIX + "/getWbsParam")
     WbsParam getWbsParam(@RequestParam Long nodeId);
 
+    @PostMapping(API_PREFIX + "/saveWbsParams")
+    void saveWbsParams(@RequestBody List<WbsParam> wbsParamList);
     @PostMapping(API_PREFIX + "/createFileTitle")
     String createFileTitle(@RequestBody WbsTreeContract contract);
 }

+ 1 - 1
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/TextdictInfoVO.java

@@ -36,6 +36,6 @@ public class TextdictInfoVO extends TextdictInfo {
     //1.电签配置 2.系统识别
     private Integer showType;
 
-    @ApiModelProperty("是否引用系统级电签配置,1 系统级,0 项目级")
+    @ApiModelProperty("本表配置 绿色0,电签库 蓝色1,项目匹配 橙色2")
     private Integer isSystem = 0;
 }

+ 0 - 1
blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ArchivesAutoServiceImpl.java

@@ -83,7 +83,6 @@ import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import org.springframework.transaction.annotation.Transactional;
-import org.springframework.util.CollectionUtils;
 import org.springframework.web.multipart.MultipartFile;
 
 import javax.servlet.http.HttpServletResponse;

+ 19 - 38
blade-service/blade-business/src/main/java/org/springblade/business/controller/InformationWriteQueryController.java

@@ -1839,7 +1839,7 @@ public R<Boolean> copyContractTreeNode(@RequestBody CopyContractTreeNodeVO vo) {
                         .collect(Collectors.toList());
                 //表名集合转逗号拼接的字符串
                 String inClausePlaceholders = String.join(",", Collections.nCopies(tabNames.size(), "?"));
-                String sql = "SELECT table_name AS queryType, GROUP_CONCAT(COLUMN_name) AS ancestors " +
+                String sql = "SELECT table_name AS queryType, GROUP_CONCAT(distinct COLUMN_name) AS ancestors " +
                         "FROM information_schema.COLUMNS WHERE table_name IN (" + inClausePlaceholders + ") " +
                         "GROUP BY table_name";
                 Object[] params = tabNames.toArray();
@@ -2009,20 +2009,13 @@ public R<Boolean> copyContractTreeNode(@RequestBody CopyContractTreeNodeVO vo) {
             }
 
             //TODO 20250414-lhb-新增 添加祖级字段 ancestorsPId
-            //因为复制选中节点,所以要查询出选中节点的父节点信息 来组装祖级节点
-            if(needCopyNode != null){
-                Long parentPKeyId = null;
-                String ancestorsPId = null;
-                if(needCopyNode.getPId() == 0L){
-                    ancestorsPId = "0";
-                    parentPKeyId = 0L;
-                }else{
-                    WbsTreeContract parentNode = this.wbsTreeContractClient.getContractNodeByPrimaryKeyId(String.valueOf(needCopyNode.getPId()));
-                    ancestorsPId = parentNode.getAncestorsPId();
-                    parentPKeyId = parentNode.getPKeyId();
-                }
-                attachNodesToTarget(saveList,parentPKeyId,ancestorsPId);
-            }
+            List<WbsTreeContract> contractWbsTreeByContractId = wbsTreeContractClient.getContractWbsTreeByContractId(Long.valueOf(needCopyNode.getContractId()));
+            contractWbsTreeByContractId.addAll(saveList);
+            Map<Long, WbsTreeContract> collect = contractWbsTreeByContractId.stream().collect(Collectors.toMap(WbsTreeContract::getPKeyId, Function.identity()));
+            saveList.forEach(node -> {
+                String correctAncestors = createAncestorsPId(node,collect);;
+                node.setAncestorsPId(correctAncestors);
+            });
         }
         needCopyNode.setNodeName(vo.getNeedCopyNodeName());
 
@@ -2190,26 +2183,6 @@ public R<Boolean> copyContractTreeNode(@RequestBody CopyContractTreeNodeVO vo) {
                                     this.addCopyTabData(needCopyNode, toCopyNode, tabOwner, resultTablesData, addTabList, vo.getIsCopyData(), addNewFileTabs);
                                 }
                             }
-
-
-                            /*重构祖级id*/
-                            List<WbsTreeContract> resultAll = new ArrayList<>();
-                            resultAll.addAll(addNodeList);
-                            resultAll.addAll(addTabList);
-                            //因为复制选中节点,所以要查询出选中节点的父节点信息 来组装祖级节点
-                            if(needCopyNode != null && CollectionUtil.isNotEmpty(resultAll)){
-                                Long parentPKeyId = null;
-                                String ancestorsPId = null;
-                                if(needCopyNode.getPId() == 0L){
-                                    ancestorsPId = "0";
-                                    parentPKeyId = 0L;
-                                }else{
-                                    WbsTreeContract parentNode = this.wbsTreeContractClient.getContractNodeByPrimaryKeyId(String.valueOf(toCopyVO.getPrimaryKeyId()));
-                                    ancestorsPId = parentNode.getAncestorsPId();
-                                    parentPKeyId = parentNode.getPKeyId();
-                                }
-                                attachNodesToTarget(resultAll,parentPKeyId,ancestorsPId);
-                            }
                         }
                     }
                 }
@@ -2219,6 +2192,14 @@ public R<Boolean> copyContractTreeNode(@RequestBody CopyContractTreeNodeVO vo) {
                 resultAll.addAll(addNodeList);
                 resultAll.addAll(addTabList);
 
+                //TODO 20250414-lhb-新增
+                List<WbsTreeContract> contractWbsTreeByContractId = wbsTreeContractClient.getContractWbsTreeByContractId(Long.valueOf(contractId));
+                contractWbsTreeByContractId.addAll(resultAll);
+                Map<Long, WbsTreeContract> collect = contractWbsTreeByContractId.stream().collect(Collectors.toMap(WbsTreeContract::getPKeyId, Function.identity()));
+                resultAll.forEach(node -> {
+                    String correctAncestors = createAncestorsPId(node,collect);;
+                    node.setAncestorsPId(correctAncestors);
+                });
 
                 List<WbsTreeContract> allData = this.reBuildAncestors(resultAll);
                 List<WbsTreeContract> nodes = allData.stream().filter(f -> f.getType().equals(1)).collect(Collectors.toList());
@@ -2551,8 +2532,8 @@ private List<WbsTreeContract> reBuildAncestors(List<WbsTreeContract> list) {
 public void addCopyTabFile(Set<WbsTreeContract> addChildNodesTables,
                            Set<WbsTreeContract> addChildNodesTablesOld) {
     //获取所有数据源附件文件
-    List<Long> tabFileIds = addChildNodesTablesOld.stream().distinct().map(WbsTreeContract::getPKeyId).collect(Collectors.toList());
-    Map<String, List<TableFile>> tableFileOldMap = tableFileClient.getTabFilesByTabIds(StringUtils.join(tabFileIds, ",")).stream().collect(Collectors.groupingBy(TableFile::getTabId));
+    List<String> tabFileIds = addChildNodesTablesOld.stream().distinct().map(item -> item.getPKeyId() + "").collect(Collectors.toList());
+    Map<String, List<TableFile>> tableFileOldMap = tableFileClient.getTabFilesByTabIds(tabFileIds).stream().collect(Collectors.groupingBy(TableFile::getTabId));
     if (tableFileOldMap != null && tableFileOldMap.size() > 0) {
         List<TableFile> resultFileData = new ArrayList<>();
         Set<Long> updatePKeyIds = new HashSet<>();
@@ -2876,7 +2857,7 @@ private void addCopyNodesAndTabsBuildData(List<WbsTreeContract> addNodeList, Lis
         List<String> initTabNames = needTabs.stream().map(WbsTreeContract::getInitTableName).distinct().filter(ObjectUtil::isNotEmpty).collect(Collectors.toList());
         String joined = StringUtils.join(initTabNames, ",");
         joined = "'" + joined.replaceAll(",", "','") + "'";
-        Map<String, QueryProcessDataVO> tabColsAllByTabNameMaps = jdbcTemplate.query("SELECT table_name as queryType, GROUP_CONCAT(COLUMN_name) as ancestors from information_schema.COLUMNS where table_name in (" + joined + ") GROUP BY table_name", new BeanPropertyRowMapper<>(QueryProcessDataVO.class)).stream().collect(Collectors.toMap(QueryProcessDataVO::getQueryType, Function.identity()));
+        Map<String, QueryProcessDataVO> tabColsAllByTabNameMaps = jdbcTemplate.query("SELECT table_name as queryType, GROUP_CONCAT(DISTINCT COLUMN_name) as ancestors from information_schema.COLUMNS where table_name in (" + joined + ") GROUP BY table_name", new BeanPropertyRowMapper<>(QueryProcessDataVO.class)).stream().collect(Collectors.toMap(QueryProcessDataVO::getQueryType, Function.identity()));
         for (WbsTreeContract node : needNodes) {
             Long oldId = node.getId();
             //新节点

+ 2 - 2
blade-service/blade-business/src/main/java/org/springblade/business/controller/MessageWarningController.java

@@ -192,9 +192,9 @@ public class MessageWarningController extends BladeController {
             iPage.getRecords().forEach(reVO -> {
                 if (reVO.getType() != null && reVO.getType() == 3) {
                     if (reVO.getContent() != null && reVO.getContent().contains("驳回了")) {
-                        reVO.setTypeValue("驳回通知");
+                        reVO.setRepealType("驳回通知");
                     } else if (reVO.getContent() != null && reVO.getContent().contains("废除了")) {
-                        reVO.setTypeValue("废除通知");
+                        reVO.setRepealType("废除通知");
                     }
                     return;
                 }

+ 2 - 2
blade-service/blade-business/src/main/java/org/springblade/business/controller/StandardInfoController.java

@@ -47,8 +47,8 @@ public class StandardInfoController {
      */
     @GetMapping("page")
     @ApiOperation(value = "分页查询所有数据", notes = "传入分页对象和高级查询对象")
-    public R<IPage<StandardInfoDTO>> selectAll(Query query, StandardInfo standardInfo) {
-        IPage<StandardInfoDTO> page = this.uStandardInfoService.selectMyPage(query, standardInfo);
+    public R<IPage<StandardInfoDtoVo>> selectAll(Query query, StandardInfo standardInfo) {
+        IPage<StandardInfoDtoVo> page = this.uStandardInfoService.selectMyPage(query, standardInfo);
         return R.data(page);
     }
 

+ 2 - 0
blade-service/blade-business/src/main/java/org/springblade/business/controller/TrialDetectionController.java

@@ -179,6 +179,8 @@ public class TrialDetectionController extends BladeController {
         jdbcTemplate.execute(sql5);
         String sql6 = "delete from u_information_query where wbs_id in(" + ids + ") and type = 2";
         jdbcTemplate.execute(sql6);
+        String sql7="update u_trial_auto_number set is_deleted=0 where form_data_id in ("+ids+")";
+        jdbcTemplate.execute(sql7);
         return R.status(true);
     }
 

+ 2 - 0
blade-service/blade-business/src/main/java/org/springblade/business/controller/TrialMaterialController.java

@@ -153,8 +153,10 @@ public class TrialMaterialController extends BladeController {
         if(b){
             //删除关联表中的额数据
             String sqlForDelTrailSampleRecord = "delete from u_trial_sampling_record where sample_info_id in ("+ids+")";
+            String update="update u_trial_auto_number set is_deleted=1 where form_data_id in ("+ids+")";
             try {
                 jdbcTemplate.execute(sqlForDelTrailSampleRecord);
+                jdbcTemplate.update(update);
             } catch (DataAccessException e) {
                 log.error("删除关联表中的额数据失败", e);
                 throw new RuntimeException(e);

+ 1 - 1
blade-service/blade-business/src/main/java/org/springblade/business/mapper/InformationQueryMapper.xml

@@ -923,7 +923,7 @@
 
     <!--获取当前节点下,所有表单的字段数据-->
     <select id="getNodeChildTabColsAllByTabName" resultMap="queryProcessDataMap">
-        SELECT table_name as queryType, GROUP_CONCAT(COLUMN_name) as ancestors
+        SELECT table_name as queryType, GROUP_CONCAT(distinct COLUMN_name) as ancestors
         from information_schema.COLUMNS
         where table_name
                   in (#{tabName})

+ 1 - 1
blade-service/blade-business/src/main/java/org/springblade/business/mapper/StandardInfoMapper.java

@@ -20,7 +20,7 @@ import java.util.List;
  */
 public interface StandardInfoMapper extends BaseMapper<StandardInfo> {
 
-    IPage<StandardInfoDTO> selectMyPage(Page<StandardInfoDTO> page, @Param("query") StandardInfo standardInfo);
+    IPage<StandardInfoDtoVo> selectMyPage(Page<StandardInfoDtoVo> page, @Param("query") StandardInfo standardInfo);
 
     StandardInfoDTO selectMyOne(@Param("id") Long id);
 

+ 5 - 4
blade-service/blade-business/src/main/java/org/springblade/business/mapper/StandardInfoMapper.xml

@@ -16,7 +16,7 @@
         <result property="updateTime" column="update_time"/>
         <result property="updateUser" column="update_user"/>
     </resultMap>
-    <resultMap id="BaseResultPageMap" type="org.springblade.business.dto.StandardInfoDTO">
+    <resultMap id="BaseResultPageMap" type="org.springblade.business.vo.StandardInfoDtoVo">
         <id property="id" column="id"/>
         <result property="name" column="name"/>
         <result property="symbol" column="symbol"/>
@@ -28,6 +28,7 @@
         <result property="createUser" column="create_user"/>
         <result property="updateTime" column="update_time"/>
         <result property="updateUser" column="update_user"/>
+        <result property="symbolName" column="symbolName"/>
         <collection property="info" ofType="org.springblade.business.entity.StandardInfo" select="findByParentId" column="{parentId=id}">
         </collection>
     </resultMap>
@@ -39,7 +40,7 @@
     </sql>
     <select id="selectMyPage" resultMap="BaseResultPageMap">
         SELECT
-            <include refid="Base_Column_List"/>
+            <include refid="Base_Column_List"/>,concat(symbol,name) symbolName
         FROM
             u_standard_info
         <where>
@@ -62,7 +63,7 @@
     </select>
     <select id="selectMyOne" resultMap="BaseResultPageMap">
         SELECT
-            <include refid="Base_Column_List"/>
+            <include refid="Base_Column_List"/>,concat(symbol,name) symbolName
         FROM
             u_standard_info
         WHERE
@@ -169,7 +170,7 @@
     </select>
     <select id="findRightByJoinLeftId" resultType="org.springblade.business.entity.StandardInfo">
         SELECT
-            <include refid="Base_Column_Join_List"/>
+            <include refid="Base_Column_Join_List"/>, c.name parentName
         FROM
             u_standard_info a
             INNER JOIN u_standard_info_join b ON a.id = b.standard_info_right_id AND a.is_deleted = b.is_deleted

+ 1 - 0
blade-service/blade-business/src/main/java/org/springblade/business/service/ITrialSelfInspectionRecordService.java

@@ -5,6 +5,7 @@ import org.springblade.business.dto.*;
 import org.springblade.business.entity.TrialSelfInspectionRecord;
 import org.springblade.business.vo.*;
 import org.springblade.core.mp.base.BaseService;
+import org.springblade.core.secure.BladeUser;
 import org.springblade.core.tool.api.R;
 import org.springframework.web.multipart.MultipartFile;
 

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

@@ -18,7 +18,7 @@ import java.util.List;
  */
 public interface StandardInfoService extends IService<StandardInfo> {
 
-    IPage<StandardInfoDTO> selectMyPage(Query query, StandardInfo standardInfo);
+    IPage<StandardInfoDtoVo> selectMyPage(Query query, StandardInfo standardInfo);
 
     StandardInfoDTO selectOne(Long id);
 

+ 1 - 1
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/ArchiveFileServiceImpl.java

@@ -42,7 +42,7 @@ public class ArchiveFileServiceImpl extends BaseServiceImpl<ArchiveFileMapper, A
 
     private ExecutorService executorService;
     private final ArchiveInspectionInfoClient archiveInspectionInfoClient;
-    private final JdbcTemplate   jdbcTemplate;
+    private final JdbcTemplate  jdbcTemplate;
 
 
     @Override

+ 15 - 5
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TaskServiceImpl.java

@@ -38,6 +38,7 @@ import org.springblade.core.tool.utils.Func;
 import org.springblade.core.tool.utils.ObjectUtil;
 import org.springblade.core.tool.utils.ResourceUtil;
 import org.springblade.evisa.feign.EVisaClient;
+import org.springblade.evisa.redissionUtil.DistributedRedisLock;
 import org.springblade.evisa.vo.EVisaTaskApprovalVO;
 import org.springblade.flow.core.constant.ProcessConstant;
 import org.springblade.flow.core.feign.IFlowClient;
@@ -1569,11 +1570,20 @@ public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implement
             //这里发起的默认为普通流程
             task.setType(1);
             task.setStatus(1);
-            //保存附表信息
-            this.taskParallelService.saveBatch(taskParallelArray);
-
-            //保存主表数据
-            this.save(task);
+            try {
+                if (DistributedRedisLock.acquire("TaskService_StartApproval_" + task.getFormDataId(), 5)) {
+                    long count = this.count(Wrappers.<Task>lambdaQuery().eq(Task::getFormDataId, task.getFormDataId()).ne(Task::getStatus, 3));
+                    if (count > 0) {
+                        return false;
+                    }
+                    //保存附表信息
+                    this.taskParallelService.saveBatch(taskParallelArray);
+                    //保存主表数据
+                    this.save(task);
+                }
+            } finally {
+                DistributedRedisLock.release("TaskService_StartApproval_" + task.getFormDataId());
+            }
         }
         return true;
     }

+ 22 - 1
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TrialMaterialMobilizationServiceImpl.java

@@ -158,7 +158,24 @@ public class TrialMaterialMobilizationServiceImpl extends BaseServiceImpl<TrialM
 
         IPage<TrialMaterialMobilizationVO> trialMaterialMobilizationVOIPage = TrialMaterialMobilizationWarpper.build().pageVO(pages);
         List<TrialMaterialMobilizationVO> records = trialMaterialMobilizationVOIPage.getRecords();
-        Map<String, String> fileMaps = jdbcTemplate.query("select link,original_name from blade_attach", new BeanPropertyRowMapper<>(Attach.class)).stream().collect(Collectors.toMap(Attach::getLink, Attach::getOriginalName, (key1, key2) -> key2));
+        StringBuilder links = new StringBuilder();
+        records.forEach(record -> {
+            if (StringUtil.hasText(record.getOtherAccessories())) {
+                links.append("'").append(record.getOtherAccessories()).append("',");
+            }
+            if (StringUtil.hasText(record.getProductionCertificate())) {
+                links.append("'").append(record.getProductionCertificate()).append("',");
+            }
+            if (StringUtil.hasText(record.getQualityInspectionReport())) {
+                links.append("'").append(record.getQualityInspectionReport()).append("',");
+            }
+        });
+        Map<String, String> fileMaps = new HashMap<>();
+        if (links.length() > 1) {
+            links.deleteCharAt(links.length() - 1);
+            fileMaps = jdbcTemplate.query("select link,original_name from blade_attach where link in (" + links + ")", new BeanPropertyRowMapper<>(Attach.class))
+                    .stream().collect(Collectors.toMap(Attach::getLink, Attach::getOriginalName, (key1, key2) -> key2));
+        }
         for (TrialMaterialMobilizationVO record : records) {
             for (User user : userList) {
                 if (user.getId().equals(record.getUserId())) {
@@ -504,6 +521,10 @@ public class TrialMaterialMobilizationServiceImpl extends BaseServiceImpl<TrialM
             return R.fail("所选数据均存在取样记录,不允许删除");
         }
         boolean b = super.deleteLogic(newIdList);
+        if(b){
+          String update="update u_trial_auto_number set is_deleted=1 where form_data_id in ("+ids+")";
+          jdbcTemplate.update(update);
+        }
         return  b?R.success("删除成功"):R.fail("删除失败");
     }
 }

+ 8 - 9
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TrialSelfInspectionRecordServiceImpl.java

@@ -1137,21 +1137,21 @@ public class TrialSelfInspectionRecordServiceImpl extends BaseServiceImpl<TrialS
         //------初始当前填报的表pKeyIds------
         this.initTrialTabIds(dto);
 
-        if(!this.judgingParameters(dto)){
-            //------初始编号信息------
-            this.initBuildNumber(dto);
-        }
+//        if(!this.judgingParameters(dto)){
+//            //------初始编号信息------
+//            this.initBuildNumber(dto);
+//        }
         this.saveOrUpdate(dto);
+
         if (ObjectUtil.isNotEmpty(dto.getId())) {
             //------获取最新试验记录------
             TrialSelfInspectionRecord obj = baseMapper.selectById(dto.getId());
             //如果传递了编号就修改对应记录的值 以第一张表的数据为准
             this.updateRecordNoOrReportNo(obj, dto);
             //------编辑时记录表编号或报告单编号为Null的重新生成------
-            if(!this.judgingParameters(dto)){
-                this.reBuildNumber(obj, dto);
-            }
-
+//            if(!this.judgingParameters(dto)){
+//                this.reBuildNumber(obj, dto);
+//            }
             //------保存实体表数据、试验记录信息、生成PDF------
             this.submitTrialData(obj, dto);
 
@@ -1164,7 +1164,6 @@ public class TrialSelfInspectionRecordServiceImpl extends BaseServiceImpl<TrialS
             //------关联新增设备使用记录信息------
             this.trialDeviceUseService.addDeviceUseInfo(dto, obj.getId());
         }
-
         // ---- 修改样品单号信息 --------
         if(dto!=null && Func.isNotEmpty(dto.getEntrustId())){
             //修改项目节点基础信息

+ 2 - 2
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/UStandardInfoServiceImpl.java

@@ -55,8 +55,8 @@ public class UStandardInfoServiceImpl extends ServiceImpl<StandardInfoMapper, St
 
 
     @Override
-    public IPage<StandardInfoDTO> selectMyPage(Query query, StandardInfo standardInfo) {
-        return baseMapper.selectMyPage(new Page<StandardInfoDTO>(query.getCurrent(), query.getSize()), standardInfo);
+    public IPage<StandardInfoDtoVo> selectMyPage(Query query, StandardInfo standardInfo) {
+        return baseMapper.selectMyPage(new Page<StandardInfoDtoVo>(query.getCurrent(), query.getSize()), standardInfo);
     }
 
     @Override

+ 11 - 1
blade-service/blade-business/src/main/java/org/springblade/business/utils/PDFUtil.java

@@ -135,6 +135,11 @@ public class PDFUtil {
                 // 特殊处理
                 if(textStr.indexOf("1")>=0){
                     String txt = textStr.substring(textStr.indexOf("1"));
+                    for (int i = 0; i < txt.length(); i++) {
+                        if (!Character.isDigit(txt.charAt(i))) {
+                            txt=txt.substring(0,i);
+                        }
+                    }
                     if (txt.length() >= 15 && Func.isNumeric(txt)||(Func.isNumeric(txt)&&txt.length()==8&&txt.startsWith("123"))) {
                         System.out.println(txt);
                         eVisaConfigList.add(txt);
@@ -169,7 +174,12 @@ public class PDFUtil {
                         }
                     }
                     if(textString.startsWith("1")){
-                        if (textString.length() >= 15 && Func.isNumeric(textString)) {
+                        for (int i = 0; i < textString.length(); i++) {
+                            if (!Character.isDigit(textString.charAt(i))) {
+                                textString=textString.substring(0,i);
+                            }
+                        }
+                        if (textString.length() >= 15 && Func.isNumeric(textString)||(Func.isNumeric(textString)&&textString.length()==8&&textString.startsWith("123"))) {
                             eVisaConfigList.add("✹" + textString);
                         }
                     }

+ 1 - 1
blade-service/blade-e-visa/src/main/java/org/springblade/evisa/service/impl/EVDataServiceImpl.java

@@ -570,7 +570,7 @@ public class EVDataServiceImpl implements EVDataService {
                     List<Map<String, Object>> maps3 = jdbcTemplate.queryForList(sql);
                     System.out.println("东方中讯--签字--key =" + sql);
                     if (!maps3.isEmpty()) {
-                        Map<String, List<Map<String, Object>>> peopleByAge = maps2.stream()
+                        Map<String, List<Map<String, Object>>> peopleByAge = maps3.stream()
                                 .collect(Collectors.groupingBy(hada -> (Func.toStr(hada.get("keyWord")))));
                         for (String keyId : peopleByAge.keySet()) {
                             List<Map<String, Object>> keyList = peopleByAge.get(keyId);

+ 22 - 2
blade-service/blade-e-visa/src/main/java/org/springblade/evisa/utils/PDFUtils.java

@@ -67,6 +67,11 @@ public class PDFUtils {
                 // 特殊处理
                 if(textStr.indexOf("1")>=0){
                     String txt = textStr.substring(textStr.indexOf("1"));
+                    for (int i = 0; i < txt.length(); i++) {
+                        if (!Character.isDigit(txt.charAt(i))) {
+                            txt=txt.substring(0,i);
+                        }
+                    }
                     if (txt.length() >= 15 && Func.isNumeric(txt)||(Func.isNumeric(txt)&&txt.length()==8&&txt.startsWith("123"))) {
                         System.out.println(txt);
                         eVisaConfigList.add(txt);
@@ -101,7 +106,12 @@ public class PDFUtils {
                         }
                     }
                     if(textString.startsWith("1")){
-                        if (textString.length() >= 15 && Func.isNumeric(textString)) {
+                        for (int i = 0; i < textString.length(); i++) {
+                            if (!Character.isDigit(textString.charAt(i))) {
+                                textString=textString.substring(0,i);
+                            }
+                        }
+                        if (textString.length() >= 15 && Func.isNumeric(textString)||(Func.isNumeric(textString)&&textString.length()==8&&textString.startsWith("123"))) {
                             eVisaConfigList.add("✹" + textString);
                         }
                     }
@@ -165,6 +175,11 @@ public class PDFUtils {
                 // 特殊处理
                 if(textStr.indexOf("1")>=0){
                     String txt = textStr.substring(textStr.indexOf("1"));
+                    for (int i = 0; i < txt.length(); i++) {
+                        if (!Character.isDigit(txt.charAt(i))) {
+                            txt=txt.substring(0,i);
+                        }
+                    }
                     if (txt.length() >= 15 && Func.isNumeric(txt)||(Func.isNumeric(txt)&&txt.length()==8&&txt.startsWith("123"))) {
                         System.out.println(txt);
                         eVisaConfigList.add(txt);
@@ -199,7 +214,12 @@ public class PDFUtils {
                         }
                     }
                     if(textString.startsWith("1")){
-                        if (textString.length() >= 15 && Func.isNumeric(textString)) {
+                        for (int i = 0; i < textString.length(); i++) {
+                            if (!Character.isDigit(textString.charAt(i))) {
+                                textString=textString.substring(0,i);
+                            }
+                        }
+                        if (textString.length() >= 15 && Func.isNumeric(textString)||(Func.isNumeric(textString)&&textString.length()==8&&textString.startsWith("123"))) {
                             eVisaConfigList.add("✹" + textString);
                         }
                     }

+ 9 - 8
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ExcelTabController.java

@@ -1270,10 +1270,10 @@ public class ExcelTabController extends BladeController {
                                         if (x1 - xx2 <= 1 && y1 == yy2) {
                                             inputText = name;
                                         } else {
-                                            inputText += name + "_" +name;
+                                            inputText += name + "_";
                                         }
                                     } else {
-                                        inputText += "_" +name;
+                                        inputText += name + "_";
                                     }
                                 } else {
                                     if (x1 - xx2 <= 1 && y1 == yy2) {
@@ -1292,14 +1292,14 @@ public class ExcelTabController extends BladeController {
                                 int yy1 = Integer.parseInt(top.get(k).get("y1"));
                                 int yy2 = Integer.parseInt(top.get(k).get("y2"));
                                 if (!StringUtil.isNumeric(name) && name.length() <= 20) {
-                                    inputText += "_" + name;
+                                    inputText += name + "_";
                                 }
                             }
                         }
-                        //这段代码含义未知
-//                        if (inputText != null && inputText != "" && inputText.indexOf("_") >= 0) {
-//                            inputText = inputText.substring(0, inputText.lastIndexOf("_"));
-//                        }
+
+                        if (inputText != null && inputText != "" && inputText.indexOf("_") >= 0) {
+                            inputText = inputText.substring(0, inputText.lastIndexOf("_"));
+                        }
 
                         // 质检表特殊处理匹配
 
@@ -1679,8 +1679,9 @@ public class ExcelTabController extends BladeController {
         wbsTreeContract.setPKeyId(newPkId);
         wbsTreeContract.setCreateTime(new Date());
         wbsTreeContract.setTabGroupId(tabGroupId);
+        wbsTreeContract.setCopyPkId(wbsInfo.getCopyPkId() == null ? pkeyId + "" : wbsInfo.getCopyPkId());
         String nodeName;
-        nodeName = wbsTreeContractList2.get(wbsTreeContractList2.size() - 1).getNodeName();
+        nodeName = wbsTreeContractList2.isEmpty() ? wbsInfo.getNodeName() :wbsTreeContractList2.get(wbsTreeContractList2.size() - 1).getNodeName();
         if (nodeName.indexOf("__") >= 0) {
             String[] oldName = nodeName.split("__");
             nodeName = oldName[0] + "__" + (Integer.parseInt(oldName[1]) + 1);

+ 2 - 2
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/NodeBaseInfoController.java

@@ -247,8 +247,8 @@ public class NodeBaseInfoController extends BladeController {
     @GetMapping("/getNodeBaseInfoByPkeyId")
     @ApiOperationSupport(order = 9)
     @ApiOperation(value = "设置自动获取", notes = "pkeyId表单Id,nodeId节点Id")
-    public R getNodeBaseInfoByPkeyId(@RequestParam Long pkeyId, @RequestParam Long nodeId, @RequestParam String autoType,@RequestParam(required = false) BigDecimal min,@RequestParam(required = false)BigDecimal max){
-        return R.data(nodeBaseInfoService.getNodeBaseInfoByPkeyId(pkeyId,nodeId,autoType,min,max));
+    public R getNodeBaseInfoByPkeyId(@RequestParam Long pkeyId, @RequestParam Long nodeId, @RequestParam String autoType, @RequestParam(required = false) String paramName,@RequestParam(required = false) BigDecimal min,@RequestParam(required = false)BigDecimal max){
+        return R.data(nodeBaseInfoService.getNodeBaseInfoByPkeyId(pkeyId,nodeId,autoType, paramName,min,max));
     }
 
 	@GetMapping("/getAllNodeBaseInfoByPkeyId")

+ 2 - 2
blade-service/blade-manager/src/main/java/org/springblade/manager/feign/TableFileClientImpl.java

@@ -36,9 +36,9 @@ public class TableFileClientImpl implements TableFileClient {
     }
 
     @Override
-    public List<TableFile> getTabFilesByTabIds(String tabFileIds) {
+    public List<TableFile> getTabFilesByTabIds(List<String> tabFileIds) {
         return tableFileService.getBaseMapper().selectList(Wrappers.<TableFile>lambdaQuery()
-                .in(TableFile::getTabId, Func.toLongList(tabFileIds))
+                .in(TableFile::getTabId, tabFileIds)
                 .ne(TableFile::getType, 1) //排除源文件
                 .isNotNull(TableFile::getTabId)
         );

+ 7 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/feign/WbsParamClientImpl.java

@@ -7,6 +7,8 @@ import org.springblade.manager.entity.WbsTreeContract;
 import org.springblade.manager.service.IWbsParamService;
 import org.springframework.web.bind.annotation.RestController;
 
+import java.util.List;
+
 @RestController
 @AllArgsConstructor
 public class WbsParamClientImpl implements WbsParamClient{
@@ -23,6 +25,11 @@ public class WbsParamClientImpl implements WbsParamClient{
         return iWbsParamService.getBaseMapper().selectOne(Wrappers.lambdaQuery(WbsParam.class).eq(WbsParam::getNodeId, nodeId).eq(WbsParam::getType, 200).eq(WbsParam::getIsDeleted, 0).eq(WbsParam::getK,"FILE_TITLE"));
     }
 
+    @Override
+    public void saveWbsParams(List<WbsParam> wbsParamList) {
+        iWbsParamService.saveBatch(wbsParamList);
+    }
+
     @Override
     public String createFileTitle(WbsTreeContract contract) {
         return iWbsParamService.createFileTitle(contract);

+ 2 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/TextdictInfoMapper.java

@@ -17,6 +17,7 @@
 package org.springblade.manager.mapper;
 
 import org.springblade.manager.entity.TextdictInfo;
+import org.springblade.manager.entity.WbsTreePrivate;
 import org.springblade.manager.injector.EasyBaseMapper;
 import org.springblade.manager.vo.TextdictInfoVO;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
@@ -50,4 +51,5 @@ public interface TextdictInfoMapper extends EasyBaseMapper<TextdictInfo> {
 
     TextdictInfo selectTextdictInfoOne(@Param("id") String id,@Param("sigRoleId") String sigRoleId,@Param("projectId") String projectId);
 
+    void updateHtmlUrl(@Param("htmlUrl") String htmlUrl,@Param("projectId") String projectId, @Param("excelId") Long pKeyId);
 }

+ 3 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/TextdictInfoMapper.xml

@@ -65,4 +65,7 @@
             and sig_role_id = #{sigRoleId}
             and project_id= #{projectId}
     </select>
+    <update id="updateHtmlUrl">
+        update m_wbs_tree_contract set html_url = #{htmlUrl} where type = 2 and project_id = #{projectId} and is_type_private_pid = #{pKeyId};
+    </update>
 </mapper>

+ 1 - 1
blade-service/blade-manager/src/main/java/org/springblade/manager/service/INodeBaseInfoService.java

@@ -43,7 +43,7 @@ public interface INodeBaseInfoService extends BaseService<NodeBaseInfo> {
 
     NodeBaseInfo getOrSaveNodeBaseInfo(Long pKeyId);
 
-    Object getNodeBaseInfoByPkeyId(Long pkeyId, Long nodeId, String autoType, BigDecimal min,BigDecimal max);
+    Object getNodeBaseInfoByPkeyId(Long pkeyId, Long nodeId, String autoType, String paramName, BigDecimal min, BigDecimal max);
 
 	Map<String,Object> getAllNodeBaseInfoByPkeyId(Long pkeyId,Long nodeId) throws Exception;
 }

+ 6 - 4
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ArchiveTreeContractServiceImpl.java

@@ -656,10 +656,12 @@ public class ArchiveTreeContractServiceImpl extends BaseServiceImpl<ArchiveTreeC
 							|| dstScopeTree.getId().equals(contractNode.getParentId())) {
 
 						ArchiveTreeVO2 tmpSubTree = srcTree;
+						ArchiveTreeContractVO2 temp = contractNode;
 						Long dstNodeId = dstNode.getId();
-						if (dstNode.getParentId() == 0 ||  dstScopeTree.getId().equals(contractNode.getParentId()) ) {
+						if ((dstNode.getParentId() == 0 ||  dstScopeTree.getId().equals(contractNode.getParentId())) && !contractNode.getId().equals(dstNode.getId())) {
 							tmpSubTree = ForestNodeMergerEx.getSubTree(srcTree,ar.getFromId());
-							dstNodeId = contractNode.getId();
+							dstNodeId = ar.getId();
+							temp = ar;
 						}
 						if (tmpSubTree == null) {
 							continue;
@@ -668,12 +670,12 @@ public class ArchiveTreeContractServiceImpl extends BaseServiceImpl<ArchiveTreeC
 						//getNormalSaveList 接口除了同步新增节点,还会同步已有节点的属性。
 						//因为关联工序的位置是固定的,先不考虑新增一个关联工序节点,且一次同步完成情况
 						tmpSaveList = archiveTreeContractSync.getNormalSaveListEx(tmpSubTree.getId(),
-								tmpSubTree,dstNodeId,contractNode);
+								tmpSubTree,dstNodeId,temp);
 						saveList.addAll(tmpSaveList);
 
 						//获取工序节点
 						List<ArchiveTreeContract> extSaveList = archiveTreeContractSync.getExtSaveList(dstNodeId,
-								contractNode,dstNode.getProjectId(),classify);
+								temp,dstNode.getProjectId(),classify);
 						saveList.addAll(extSaveList);
 
 

+ 55 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ExcelTabServiceImpl.java

@@ -1232,6 +1232,9 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
                     String delSql = "delete from " + tabName + " where p_key_id=" + tableInfo.getPkeyId();
                     String sqlInfo = "";
                     LinkedHashMap<String, String> dataMap2 = tableInfo.getDataMap();
+                    if (!updateFieldLength(tabName, dataMap2)) {
+                        throw new ServiceException("字段长度超出限制, 系统无法进行自增,请前往后台管理系统手动设置");
+                    }
                     /*检查发现有p_key_id缺失的情况,导致表单数据丢失,所以强制覆盖*/
                     dataMap2.put("p_key_id", tableInfo.getPkeyId());
                     //统计保存的字段
@@ -1341,6 +1344,58 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
        // return R.success(fileName1);
     }
 
+    public boolean updateFieldLength(String tableName, Map<String, String> fieldNameAndLengthMap) {
+        if (fieldNameAndLengthMap == null || fieldNameAndLengthMap.isEmpty()) {
+            return true;
+        }
+        fieldNameAndLengthMap.remove("id");
+        fieldNameAndLengthMap.remove("p_key_id");
+        fieldNameAndLengthMap.remove("group_id");
+        if (fieldNameAndLengthMap.isEmpty()) {
+            return true;
+        }
+        String fields = fieldNameAndLengthMap.keySet().stream().map(key -> "'" + key + "'").collect(Collectors.joining(","));
+        List<Map<String, Object>> fieldMap = jdbcTemplate.queryForList("select distinct COLUMN_NAME as fieldName, CHARACTER_MAXIMUM_LENGTH as fieldLength from information_schema.COLUMNS where  TABLE_NAME = '" + tableName +
+                "' and COLUMN_NAME in (" + fields + ")");
+        Map<String, Integer> map = fieldMap.stream().collect(toMap(k -> k.get("fieldName") + "", v -> {
+            if (v.get("fieldLength") == null) {
+                return 0;
+            }
+            return Integer.parseInt(v.get("fieldLength") + "");
+        }, Math::max));
+
+        List<WbsFormElement> elementList = jdbcTemplate.query("SELECT id,e_key,e_length from m_wbs_form_element WHERE f_id = (SELECT id from m_table_info WHERE tab_en_name = '" + tableName
+                        +"' and is_deleted = 0  limit 1) and is_deleted = 0 and e_key in ( " +  fields + ")", new BeanPropertyRowMapper<>(WbsFormElement.class));
+        StringBuilder sql = new StringBuilder();
+        sql.append("alter table ").append(tableName);
+        elementList.forEach(element -> {
+            String data = fieldNameAndLengthMap.get(element.getEKey());
+            if (data != null && element.getELength() != null && data.length() > element.getELength()) {
+                int length = data.length();
+                // 取整
+                length = (length / 10 + 1) * 10;
+                Integer fieldLength = map.get(element.getEKey());
+                if (fieldLength != null && fieldLength < element.getELength()) {
+                    element.setELength(length);
+                    sql.append(" modify column ").append(element.getEKey()).append(" ").append("varchar").append("(").append(length).append("),");
+                }
+            }
+        });
+        if (sql.indexOf("modify") > 0) {
+            TransactionStatus transactionStatus = this.beginTransaction(transactionManager1);
+            try {
+                jdbcTemplate.batchUpdate("update m_wbs_form_element set e_length = ? where id = ?", elementList.stream().map(element -> new Object[]{element.getELength(), element.getId()}).collect(Collectors.toList()));
+                jdbcTemplate.execute(sql.toString());
+                transactionManager1.commit(transactionStatus);
+            } catch (Exception e) {
+                transactionManager1.rollback(transactionStatus);
+                log.error("更新字段长度失败, error: " + e.getMessage());
+                return false;
+            }
+        }
+        return true;
+    }
+
     public String reason(String log) {
         /*保存的时候错误提示例如:字段过短提示 yangyj*/
         StringBuilder sb = new StringBuilder();

+ 106 - 26
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/NodeBaseInfoServiceImpl.java

@@ -16,28 +16,30 @@
  */
 package org.springblade.manager.service.impl;
 
+import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import org.jsoup.Jsoup;
 import org.jsoup.nodes.Document;
 import org.jsoup.nodes.Element;
 import org.jsoup.select.Elements;
 import org.springblade.common.utils.SnowFlakeUtil;
 import org.springblade.core.log.exception.ServiceException;
+import org.springblade.core.secure.utils.AuthUtil;
 import org.springblade.core.tool.utils.IoUtil;
-import org.springblade.core.tool.utils.ObjectUtil;
 import org.springblade.core.tool.utils.StringUtil;
 import org.springblade.manager.entity.NodeBaseInfo;
 import org.springblade.manager.entity.Parameter;
 import org.springblade.manager.entity.ParameterElement;
 import org.springblade.manager.entity.WbsTreeContract;
+import org.springblade.manager.service.IParameterElementService;
 import org.springblade.manager.service.IWbsTreeContractService;
 import org.springblade.manager.utils.FileUtils;
 import org.springblade.manager.vo.NodeBaseInfoVO;
 import org.springblade.manager.mapper.NodeBaseInfoMapper;
 import org.springblade.manager.service.INodeBaseInfoService;
 import org.springblade.core.mp.base.BaseServiceImpl;
-import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.jdbc.core.BeanPropertyRowMapper;
 import org.springframework.jdbc.core.JdbcTemplate;
@@ -49,7 +51,6 @@ import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.util.*;
 import java.util.stream.Collectors;
-import java.util.stream.Stream;
 
 /**
  *  服务实现类
@@ -64,6 +65,8 @@ public class NodeBaseInfoServiceImpl extends BaseServiceImpl<NodeBaseInfoMapper,
     private  IWbsTreeContractService iWbsTreeContractService;
     @Autowired
     private  JdbcTemplate jdbcTemplate;
+    @Autowired
+    private IParameterElementService parameterElementService;
 	@Override
 	public IPage<NodeBaseInfoVO> selectNodeBaseInfoPage(IPage<NodeBaseInfoVO> page, NodeBaseInfoVO nodeBaseInfo) {
 		return page.setRecords(baseMapper.selectNodeBaseInfoPage(page, nodeBaseInfo));
@@ -162,7 +165,7 @@ public class NodeBaseInfoServiceImpl extends BaseServiceImpl<NodeBaseInfoMapper,
 
 
     @Override
-    public Object getNodeBaseInfoByPkeyId(Long pkeyId, Long nodeId, String autoType, BigDecimal min, BigDecimal max) {
+    public Object getNodeBaseInfoByPkeyId(Long pkeyId, Long nodeId, String autoType, String paramName, BigDecimal min, BigDecimal max) {
         String result="";
         String[] strings = autoType.split(",");
         List<String> types = Arrays.asList(strings);
@@ -195,6 +198,7 @@ public class NodeBaseInfoServiceImpl extends BaseServiceImpl<NodeBaseInfoMapper,
                 }
             }
         }
+        String parameter = null;
         if(types.size()==1&&types.contains("8")) {
             if (min.compareTo(max) >= 0) {
                 throw new IllegalArgumentException("max must be greater than min");
@@ -209,6 +213,41 @@ public class NodeBaseInfoServiceImpl extends BaseServiceImpl<NodeBaseInfoMapper,
 
             // 设置精度和舍入模式 保留两位小数
             result= randomValue.setScale(2, RoundingMode.HALF_UP).toString();
+            Map<String, BigDecimal> map = new HashMap<>();
+            map.put("min", min);
+            map.put("max", max);
+            parameter = JSONObject.toJSONString( map);
+        }
+        if (paramName != null && !paramName.isEmpty()) {
+            try {
+                WbsTreeContract wbsTreeContract = iWbsTreeContractService.getBaseMapper().selectOne(new QueryWrapper<WbsTreeContract>().eq("p_key_id", pkeyId));
+                if (wbsTreeContract.getCopyPkId() ==  null) {
+                    wbsTreeContract.setCopyPkId(wbsTreeContract.getPKeyId() + "");
+                    iWbsTreeContractService.update(Wrappers.<WbsTreeContract>lambdaUpdate().set(WbsTreeContract::getCopyPkId, wbsTreeContract.getPKeyId()).eq(WbsTreeContract::getPKeyId, wbsTreeContract.getPKeyId()));
+                }
+                ParameterElement element = parameterElementService.getOne(Wrappers.<ParameterElement>lambdaQuery().eq(ParameterElement::getProjectId, wbsTreeContract.getProjectId())
+                        .eq(ParameterElement::getContractId, wbsTreeContract.getContractId()).eq(ParameterElement::getType, 3)
+                        .eq(ParameterElement::getElementName, paramName).eq(ParameterElement::getNodeId, wbsTreeContract.getCopyPkId()));
+                if (element == null) {
+                    element = new ParameterElement();
+                    element.setProjectId(Long.valueOf(wbsTreeContract.getProjectId()));
+                    element.setContractId(wbsTreeContract.getContractId());
+                    element.setNodeId(wbsTreeContract.getCopyPkId() == null ? wbsTreeContract.getPKeyId() + "" : wbsTreeContract.getCopyPkId());
+                    element.setType(3);
+                    element.setElementName(paramName);
+                    element.setParameter(parameter);
+                    element.setParamType(autoType);
+                    element.setCreateUser(AuthUtil.getUserId());
+                    element.setCreateDept(Long.valueOf(AuthUtil.getDeptId()));
+                    parameterElementService.save(element);
+                } else {
+                    element.setParameter(parameter);
+                    element.setParamType(autoType);
+                    parameterElementService.updateById(element);
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
         }
         return result;
     }
@@ -228,9 +267,19 @@ public class NodeBaseInfoServiceImpl extends BaseServiceImpl<NodeBaseInfoMapper,
             htmlString = htmlString.replaceAll("placeholder", "placeholderxx");
             Document doc = Jsoup.parse(htmlString);
             //拿到参数库所有元素与参数库的元素比较
-            String sql="select * from m_parameter_element where is_deleted =0";
+            // 全局参数
+            String sql="select * from m_parameter_element where is_deleted =0 and type = 1";
             List<ParameterElement> ParameterElementList = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(ParameterElement.class));
-
+            // 私有参数
+            List<ParameterElement> parameterElements = parameterElementService.list(Wrappers.<ParameterElement>lambdaQuery().eq(ParameterElement::getProjectId, wbsTreeContract.getProjectId())
+                    .eq(ParameterElement::getType, 3).eq(ParameterElement::getContractId, wbsTreeContract.getContractId())
+                    .eq(ParameterElement::getNodeId, wbsTreeContract.getCopyPkId() == null ? wbsTreeContract.getPKeyId() : wbsTreeContract.getCopyPkId()));
+            if (!parameterElements.isEmpty()) {
+                // 去重
+                Set<String> set = parameterElements.stream().map(ParameterElement::getElementName).collect(Collectors.toSet());
+                ParameterElementList.removeIf(parameterElement -> set.contains(parameterElement.getElementName()));
+            }
+            ParameterElementList.addAll(parameterElements);
             String nodeSql="Select * from m_node_base_info where node_id="+nodeId+" and is_deleted=0 limit 1";
             NodeBaseInfo nodeBaseInfo;
             try {
@@ -240,33 +289,48 @@ public class NodeBaseInfoServiceImpl extends BaseServiceImpl<NodeBaseInfoMapper,
             }
             List<WbsTreeContract> ancestorsNodes = iWbsTreeContractService.getBaseMapper().selectList(new QueryWrapper<WbsTreeContract>().in("p_key_id", Arrays.stream(wbsTreeContractNode.getAncestors().split(",")).toArray()).eq("contract_id", wbsTreeContractNode.getContractId()));
             for (ParameterElement parameterElement : ParameterElementList) {
-                Elements selects = doc.select("[placeholderxx='" + parameterElement.getElementName() + "']");
+                Elements selects;
+                if (parameterElement.getType() == 3) {
+                    selects = doc.getElementsByAttributeValue("keyname",parameterElement.getElementName());
+                } else {
+                    selects = doc.select("[placeholderxx='" + parameterElement.getElementName() + "']");
+                }
                 //元素库里存在表单的元素
                 if(selects.size()>0){
-                    //用元素查出参数库
-                    String sql1="Select * from m_parameter where id="+parameterElement.getParameterId();
-                    Parameter parameter = jdbcTemplate.queryForObject(sql1, new BeanPropertyRowMapper<>(Parameter.class));
-                    //不需要获取的情况
-                    //如果参数要区分项目
-                    if(parameter.getType()==1){
-                        //并且元素不是全局参数
-                        if(parameterElement.getType()!=1){
-                            //并且元素对应的项目ID不等于表单的项目ID
-                            if(parameterElement.getProjectId()!=null&&!wbsTreeContract.getProjectId().equals(parameterElement.getProjectId().toString())){
-                                System.out.println(parameter.getParamName()+" 参数库的"+parameterElement.getElementName()+"元素不是全局参数,并且项目Id对应不上");
-                                continue;
-                            }else {
-                                if(parameterElement.getContractId()!=null&&!wbsTreeContract.getContractId().equals(parameterElement.getContractId())){
-                                    System.out.println(parameter.getParamName()+" 参数库的"+parameterElement.getElementName()+"元素不是全局参数,项目ID能对应上但是合同段Id对应不上");
+                    String[] paramTypes;
+                    if (parameterElement.getParameterId() != null) {
+                        //用元素查出参数库
+                        String sql1="Select * from m_parameter where id="+parameterElement.getParameterId();
+                        Parameter parameter = jdbcTemplate.queryForObject(sql1, new BeanPropertyRowMapper<>(Parameter.class));
+                        //不需要获取的情况
+                        //如果参数要区分项目
+                        if(parameter.getType()==1){
+                            //并且元素不是全局参数
+                            if(parameterElement.getType()!=1){
+                                //并且元素对应的项目ID不等于表单的项目ID
+                                if(parameterElement.getProjectId()!=null&&!wbsTreeContract.getProjectId().equals(parameterElement.getProjectId().toString())){
+                                    System.out.println(parameter.getParamName()+" 参数库的"+parameterElement.getElementName()+"元素不是全局参数,并且项目Id对应不上");
                                     continue;
+                                }else {
+                                    if(parameterElement.getContractId()!=null&&!wbsTreeContract.getContractId().equals(parameterElement.getContractId())){
+                                        System.out.println(parameter.getParamName()+" 参数库的"+parameterElement.getElementName()+"元素不是全局参数,项目ID能对应上但是合同段Id对应不上");
+                                        continue;
+                                    }
                                 }
                             }
                         }
+                        //需要获取的情况
+                        //拿到参数库的类型
+                        String paramType = parameter.getParamType();
+                        paramTypes = paramType.split(",");
+                    } else {
+                        String paramType = parameterElement.getParamType();
+                        if (paramType == null || paramType.isEmpty()) {
+                            continue;
+                        }
+                        paramTypes = paramType.split(",");
                     }
-                    //需要获取的情况
-                    //拿到参数库的类型
-                    String paramType = parameter.getParamType();
-                    String[] paramTypes = paramType.split(",");
+
                     //根据参数的类型值,来获取不同的值 1-7是获取单位工程名称这些 8是获取划分编号 9是获取范围随机数
                     for (Element select : selects) {
                         StringBuilder result=new StringBuilder();
@@ -362,6 +426,22 @@ public class NodeBaseInfoServiceImpl extends BaseServiceImpl<NodeBaseInfoMapper,
                                     s=s+wbsTreeContract.getPartitionCode();
                                 }
                                 result.append(s);
+                            }else if(type.equals("9")) {
+                                String parameter = parameterElement.getParameter();
+                                if (parameter != null) {
+                                    JSONObject json = JSONObject.parseObject(parameter);
+                                    BigDecimal min = json.getBigDecimal("min");
+                                    BigDecimal max = json.getBigDecimal("max");
+                                    // 计算区间范围
+                                    BigDecimal range = max.subtract(min);
+
+                                    // 生成随机数并调整范围
+                                    BigDecimal randomFactor = new BigDecimal(Math.random());
+                                    BigDecimal randomValue = min.add(range.multiply(randomFactor));
+
+                                    // 设置精度和舍入模式 保留两位小数
+                                    result.append(randomValue.setScale(2, RoundingMode.HALF_UP));
+                                }
                             }
                         }
                         map.put(select.attr("keyname"),result.toString());

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

@@ -304,7 +304,7 @@ public class SignConfigServiceImpl extends BaseServiceImpl<SignConfigMapper, Sig
             return textdictInfoVOS;
         }
         List<WbsFormElement> list = this.wbsFormElementMapper.selectList(Wrappers.<WbsFormElement>lambdaQuery().select(WbsFormElement::getEName, WbsFormElement::getEKey)
-                .eq(WbsFormElement::getFId, tableInfos.get(0).getId()).in(WbsFormElement::getEKey, keyMap.keySet()));
+                .eq(WbsFormElement::getFId, tableInfos.get(0).getId()).eq(WbsFormElement::getEType, 6).in(WbsFormElement::getEKey, keyMap.keySet()));
         if (list == null || list.isEmpty()) {
             return textdictInfoVOS;
         }

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

@@ -56,7 +56,7 @@ public class TableInfoServiceImpl extends BaseServiceImpl<TableInfoMapper, Table
      * 十分钟执行一次
      * 替换动态表中的阿里云地址
      */
-    @Scheduled(cron = "0 */10 * * * ?")
+    //@Scheduled(cron = "0 */10 * * * ?")
 //    @Scheduled(fixedDelay = 60000)
     public void aliyunUrlReplace() {
         System.out.println("执行阿里云地址替换-----------------------------开始");

+ 103 - 20
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/TextdictInfoServiceImpl.java

@@ -16,20 +16,23 @@
  */
 package org.springblade.manager.service.impl;
 
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+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.constant.CommonConstant;
 import org.springblade.common.utils.CommonUtil;
-import org.springblade.core.tool.utils.FileUtil;
-import org.springblade.core.tool.utils.Func;
-import org.springblade.core.tool.utils.IoUtil;
-import org.springblade.core.tool.utils.ResourceUtil;
+import org.springblade.common.utils.SnowFlakeUtil;
+import org.springblade.common.utils.SystemUtils;
+import org.springblade.core.tool.utils.*;
 import org.springblade.manager.entity.TextdictInfo;
+import org.springblade.manager.entity.WbsTreeContract;
 import org.springblade.manager.entity.WbsTreePrivate;
 import org.springblade.manager.mapper.TextdictInfoMapper;
 import org.springblade.manager.mapper.WbsTreePrivateMapper;
@@ -39,16 +42,13 @@ import org.springblade.manager.utils.FileUtils;
 import org.springblade.manager.vo.TextdictBy345VO;
 import org.springblade.manager.vo.TextdictInfoVO;
 import org.springblade.system.cache.ParamCache;
-import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import javax.annotation.Resource;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.InputStream;
+import java.io.*;
 import java.util.*;
+import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.stream.Collectors;
 
 /**
@@ -79,11 +79,11 @@ public class TextdictInfoServiceImpl extends ServiceImpl<TextdictInfoMapper, Tex
                 List<String> keys = new ArrayList<>();
                 for(Element ek:table){
                     dqid.addAll(Func.toStrList("\\|\\|",ek.attr("dqid")));
-                    Elements keyNames = ek.getElementsByAttribute("keyname");
-                    if(Func.isNotEmpty(keyNames)){
-                        for(Element keyName:keyNames){
-                            keys.addAll(Func.toStrList("\\|\\|",keyName.attr("keyname")));
-                        }
+                }
+                Elements keyNames = doc.getElementsByAttribute("keyname");
+                if(Func.isNotEmpty(keyNames)){
+                    for(Element keyName:keyNames){
+                        keys.add(keyName.attr("keyname"));
                     }
                 }
                 if(Func.isNotEmpty(textdictInfo.getShowType()) && textdictInfo.getShowType() == 1){
@@ -92,8 +92,30 @@ public class TextdictInfoServiceImpl extends ServiceImpl<TextdictInfoMapper, Tex
                     }else {
                         textdict = new ArrayList<>();
                     }
+                    List<TextdictInfoVO> textdictList= baseMapper.selectTextdictInfoByExcelId(page, textdictInfo);
+                    if (textdict == null || textdict.isEmpty()) {
+                        textdict = textdictList;
+                        if (textdict != null) {
+                            textdict.forEach(textdictInfoVO -> textdictInfoVO.setIsSystem(2));
+                        }
+                        addSign(textdict, doc, privateInfo, dqid, textdict);
+                    } else if (textdictList != null && !textdictList.isEmpty()) {
+                        Map<String, Map<String, TextdictInfoVO>> map = textdict.stream().filter(vo -> vo.getColKey() != null && vo.getColKey().contains("__")).collect(Collectors.groupingBy(vo -> vo.getColKey().split("__")[1], Collectors.toMap(TextdictInfoVO::getSigRoleId, v -> v, (v1, v2) -> v1)));
+                        List<TextdictInfoVO> collect = textdictList.stream().filter(textdictInfoVO -> {
+                            if (textdictInfoVO.getColKey() == null || !textdictInfoVO.getColKey().contains("__")) {
+                                return true;
+                            }
+                            Map<String, TextdictInfoVO> voMap = map.get(textdictInfoVO.getColKey().split("__")[1]);
+                            textdictInfoVO.setIsSystem(2);
+                            if (voMap != null && !voMap.isEmpty() ) {
+                                return voMap.get(textdictInfoVO.getSigRoleId()) == null;
+                            }
+                            return true;
+                        }).collect(Collectors.toList());
+                        textdict.addAll(collect);
+                        addSign(collect, doc, privateInfo, dqid,textdict);
+                    }
                     if (!keys.isEmpty()) {
-                        // 查询系统级电签配置
                         TextdictInfoVO temp = null;
                         if (textdict != null && !textdict.isEmpty()) {
                             temp = textdict.get(0);
@@ -105,13 +127,17 @@ public class TextdictInfoServiceImpl extends ServiceImpl<TextdictInfoMapper, Tex
                             temp.setTabId(privateInfo.getPKeyId() + "");
                             temp.setType(2);
                         }
-                        List<TextdictInfoVO> textdictList = iSignConfigService.hasSignConfig(privateInfo.getInitTableName(), keys, temp);
+                        // 查询电签库配置
+                        List<TextdictInfoVO> textdictConfigList = iSignConfigService.hasSignConfig(privateInfo.getInitTableName(), keys, temp);
                         if (textdict == null || textdict.isEmpty()) {
-                            textdict = textdictList;
+                            textdict = textdictConfigList;
                         } else {
-                            Map<String, Map<String, TextdictInfoVO>> map = textdict.stream().collect(Collectors.groupingBy(TextdictInfoVO::getColKey, Collectors.toMap(TextdictInfoVO::getSigRoleId, v -> v, (v1, v2) -> v1)));
-                            List<TextdictInfoVO> collect = textdictList.stream().filter(textdictInfoVO -> {
-                                Map<String, TextdictInfoVO> voMap = map.get(textdictInfoVO.getColKey());
+                            Map<String, Map<String, TextdictInfoVO>> map = textdict.stream().filter(vo -> vo.getColKey() != null && vo.getColKey().contains("__")).collect(Collectors.groupingBy(vo -> vo.getColKey().split("__")[1], Collectors.toMap(TextdictInfoVO::getSigRoleId, v -> v, (v1, v2) -> v1)));
+                            List<TextdictInfoVO> collect = textdictConfigList.stream().filter(textdictInfoVO -> {
+                                if (textdictInfoVO.getColKey() == null || !textdictInfoVO.getColKey().contains("__")) {
+                                    return true;
+                                }
+                                Map<String, TextdictInfoVO> voMap = map.get(textdictInfoVO.getColKey().split("__")[1]);
                                 if (voMap != null && !voMap.isEmpty() ) {
                                     return voMap.get(textdictInfoVO.getSigRoleId()) == null;
                                 }
@@ -131,6 +157,63 @@ public class TextdictInfoServiceImpl extends ServiceImpl<TextdictInfoMapper, Tex
         }
         return page.setRecords(textdict);
     }
+    private void addSign(List<TextdictInfoVO> collect, Document doc, WbsTreePrivate privateInfo, List<String> dqid,List<TextdictInfoVO> allTextdict) {
+        if (collect == null || collect.isEmpty()) {
+            return;
+        }
+        if (dqid != null && !dqid.isEmpty()) {
+            collect = collect.stream().filter(textdictInfoVO -> !dqid.contains(textdictInfoVO.getId() + "")).collect(Collectors.toList());
+            if (collect.isEmpty()) {
+                return;
+            }
+        }
+        //解析
+        Element table = doc.select("table").first();
+        Elements trs = table.select("tr");
+        AtomicBoolean isUpdate = new AtomicBoolean(false);
+        Map<String, List<TextdictInfoVO>> colKeyMap = allTextdict.stream().collect(Collectors.groupingBy(TextdictInfoVO::getColKey));
+        colKeyMap.forEach((colKey, textdictInfoVOs) -> {
+            if (StringUtil.hasText(colKey)) {
+                try {
+                    String[] trtd = colKey.split("__")[1].split("_");
+                    Element element = trs.get(Integer.parseInt(trtd[0])).select("td").get(Integer.parseInt(trtd[1]));
+                    String dqIds = textdictInfoVOs.stream().map(vo -> vo.getId() + "").distinct().collect(Collectors.joining("||"));
+                    if (StringUtil.hasText(dqIds)) {
+                        element.removeAttr("dqId");
+                        element.attr("dqId", dqIds);
+                        if (textdictInfoVOs.get(0).getType() == 2) { //个人签字 不能用户输入
+                            if (element.html().contains("el-tooltip")) {
+                                element.children().get(0).children().get(0).attr(":readonly", "true");
+                            } else {
+                                element.children().get(0).attr(":readonly", "true");
+                            }
+                        }
+                        isUpdate.set(true);
+                    }
+                } catch (Exception e) {
+                    log.error("解析失败: ", e);
+                }
+            }
+        });
+        if (!isUpdate.get() || !SystemUtils.isLinux()) {
+            return;
+        }
+        try {
+            String thmlUrl = privateInfo.getHtmlUrl().replace("Desktop//privateUrl", "Desktop/privateUrl");
+            thmlUrl = thmlUrl.replace("\\", "\\\\");
+            File file_out = ResourceUtil.getFile(thmlUrl);
+            if(!file_out.exists()){
+                FileUtils.ensureFileExists(thmlUrl);
+            }
+            File writefile = new File(thmlUrl);
+            FileUtil.writeToFile(writefile, doc.html(), Boolean.parseBoolean("UTF-8"));
+            wbsTreePrivateMapper.update(null,Wrappers.<WbsTreePrivate>lambdaUpdate().eq(WbsTreePrivate::getPKeyId, privateInfo.getPKeyId()).set(WbsTreePrivate::getHtmlUrl, thmlUrl));
+            privateInfo.setHtmlUrl(thmlUrl);
+            baseMapper.updateHtmlUrl(thmlUrl, privateInfo.getProjectId(), privateInfo.getPKeyId());
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
 
     @Override
     public TextdictInfoVO selectTextdictInfoById(TextdictInfo textdictInfo) {

+ 8 - 2
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsFormElementServiceImpl.java

@@ -322,7 +322,8 @@ public class WbsFormElementServiceImpl extends BaseServiceImpl<WbsFormElementMap
         //当前设置的字段总长度
         Integer nowTotalLength = 0;
         for (WbsFormElement wbsFormElement : wbsFormElementList) {
-            nowTotalLength += wbsFormElement.getELength();
+            // + 10 预留字段长度,用来保存在excel中的位置信息,比如:xx_^_12_12, 不适合一个字段存储多个位置
+            nowTotalLength += wbsFormElement.getELength() + 10;
         }
         //当前表总字段长度
         int sumLength = baseMapper.selectSumColumnLength(jdbcTemplate.queryForObject("SELECT DATABASE()", String.class), initTableName);
@@ -375,8 +376,13 @@ public class WbsFormElementServiceImpl extends BaseServiceImpl<WbsFormElementMap
                 int row1 = wbsTreeMapper.isThereAField(initTableName, eKey);
                 if (row1 > 0) {
                     try {
-                        baseMapper.updateFiledType(initTableName, eKey, "varchar", eLength);
+                        // + 10 预留字段长度,用来保存在excel中的位置信息,比如:xx_^_12_12, 不适合一个字段存储多个位置
+                        baseMapper.updateFiledType(initTableName, eKey, "varchar", eLength + 10);
                     } catch (Exception e) {
+                        // 数据库字段长度大于修改长度,则忽略
+                        if (e.getMessage().contains("Data truncated for column '" + eKey + "' at row 1")) {
+                            continue;
+                        }
                         e.printStackTrace();
                         this.updateBatchById(beforeUpdateWbsFormElements);
                         throw new RuntimeException("字段长度范围超出总最大限制,请尝试缩小当前字段长度或其他字段长度");

+ 3 - 21
blade-service/blade-manager/src/main/java/org/springblade/manager/utils/PdfAddContextUtils.java

@@ -13,11 +13,11 @@ import com.itextpdf.text.pdf.parser.PdfReaderContentParser;
 import com.itextpdf.text.pdf.parser.RenderListener;
 import com.itextpdf.text.pdf.parser.TextRenderInfo;
 import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellType;
 import org.apache.poi.ss.usermodel.Row;
 import  org.apache.poi.ss.usermodel.Sheet;
 
-import java.io.File;
-import java.io.FileInputStream;
+
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.util.ArrayList;
@@ -27,23 +27,6 @@ public class PdfAddContextUtils {
 
     public static void addContextByTitle(String src, String dest, String title, String context,  int fontSize) throws IOException, DocumentException {
 
-        File pdfFile = new File(src);
-        byte[] pdfData = new byte[(int) pdfFile.length()];
-        FileInputStream inputStream = null;
-        try {
-            inputStream = new FileInputStream(pdfFile);
-            inputStream.read(pdfData);
-        } catch (IOException e) {
-            throw e;
-        } finally {
-            if (inputStream != null) {
-                try {
-                    inputStream.close();
-                } catch (IOException e) {
-                    inputStream.close();
-                }
-            }
-        }
         // 读取PDF文件
         PdfReader reader = new PdfReader(src);
         PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
@@ -66,14 +49,13 @@ public class PdfAddContextUtils {
     public static String getExcelFullTitle(org.apache.poi.ss.usermodel.Workbook workbook, String title) {
         Sheet sheet = workbook.getSheetAt(0);
         sheet.setForceFormulaRecalculation(true);
-        int rowNum = sheet.getLastRowNum();
         for (int i = 0; i < 6; i++) {
             Row row = sheet.getRow(i);
             if (row != null) {
                 short cellNum = row.getLastCellNum();
                 for (int j = 0; j < cellNum; j++) {
                     Cell cell = row.getCell(j);
-                    if (cell != null) {
+                    if (cell != null && cell.getCellTypeEnum() == CellType.STRING) {
                         String cellValue = cell.getStringCellValue();
                         if (cellValue != null && !cellValue.isEmpty()) {
                             if (containsAllCharactersInOrder(cellValue, title)) {

+ 2 - 2
blade-service/blade-meter/src/main/java/org/springblade/meter/controller/TaskController.java

@@ -4013,7 +4013,7 @@ public class TaskController extends BladeController {
 
                 //同时删除映射task表数据
                 deleteMapTask1 = "DELETE from s_material_meter_form_task where task_id = "+task.getId();
-                String upData = "UPDATE s_material_start_statement c set approve_status=0,raw_url='',file_url_list='' where meter_period_id='"+periodId+"'";
+                String upData = "UPDATE s_material_start_statement c set approve_status=0,raw_url='',file_url_list='', pre_pdf_url='' where meter_period_id='"+periodId+"'";
                 jdbcTemplate.execute(upData);
             }
             if (type == 2) {//2开工
@@ -4021,7 +4021,7 @@ public class TaskController extends BladeController {
                 jdbcTemplate.execute(uptPeriod);
                 String uptMeter = "update s_start_pay_meter_form  set approve_status =0 where meter_period_id ='" + periodId + "'";
                 jdbcTemplate.execute(uptMeter);
-                String upData = "UPDATE s_material_start_statement c set approve_status=0,raw_url='',file_url_list='' where meter_period_id='"+periodId+"'";
+                String upData = "UPDATE s_material_start_statement c set approve_status=0,raw_url='',file_url_list='', pre_pdf_url='' where meter_period_id='"+periodId+"'";
                 jdbcTemplate.execute(upData);
             }
             if (type == 3){

+ 268 - 6
blade-service/blade-repair/src/main/java/org/springblade/repair/controller/CheckAndRepairController.java

@@ -6,14 +6,19 @@ import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import lombok.AllArgsConstructor;
 import org.apache.commons.lang.SystemUtils;
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Document;
+import org.jsoup.nodes.Element;
+import org.jsoup.select.Elements;
 import org.springblade.common.constant.CommonConstant;
 import org.springblade.common.utils.CommonUtil;
 import org.springblade.common.utils.SnowFlakeUtil;
 import org.springblade.core.oss.model.BladeFile;
+import org.springblade.core.tool.utils.FileUtil;
+import org.springblade.core.tool.utils.IoUtil;
 import org.springblade.core.tool.utils.ObjectUtil;
-import org.springblade.manager.entity.ExcelTab;
-import org.springblade.manager.entity.WbsTreeContract;
-import org.springblade.manager.entity.WbsTreePrivate;
+import org.springblade.core.tool.utils.StringUtil;
+import org.springblade.manager.entity.*;
 import org.springblade.repair.util.ExcelInfoUtils;
 import org.springblade.repair.util.FileUtils;
 import org.springblade.resource.feign.NewIOSSClient;
@@ -21,19 +26,19 @@ import org.springblade.system.cache.ParamCache;
 import org.springframework.jdbc.core.BeanPropertyRowMapper;
 import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.transaction.support.TransactionTemplate;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 import org.springblade.manager.feign.ExcelTabClient;
 
+import javax.validation.constraints.NotNull;
 import java.io.*;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.nio.file.StandardCopyOption;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
 import java.util.stream.Collectors;
 
 
@@ -418,4 +423,261 @@ public class CheckAndRepairController {
         }
         System.out.println("检查完毕,更新了"+i+"条记录");
     }
+
+
+    private final TransactionTemplate transactionTemplate;
+    @RequestMapping("/checkAndRepairExcelHtmlDefaultValue")
+    @ApiOperation("定时检测修复ExcelHtml")
+    @Scheduled(cron = "00 00 01 * * ?")
+    public void checkAndRepairExcelHtmlDefaultValue() {
+//        String projectSql = "SELECT * from m_project_info WHERE is_deleted = 0 and id != 1904814720589430785";
+        String projectSql = "SELECT * from m_project_info WHERE is_deleted = 0 and id = 1630011899725201410";
+        List<ProjectInfo> projectInfos = jdbcTemplate.query(projectSql, new BeanPropertyRowMapper<>(ProjectInfo.class));
+        projectInfos.forEach(projectInfo -> {
+            String sql = "SELECT html_url from m_wbs_tree_private WHERE html_url is not null and html_url != '' and is_deleted = 0 and project_id = ? group by html_url LIMIT ? offset ?;";
+            long pageSize = 2000L;
+            long offset = 0L;
+            boolean flag = true;
+            while (flag) {
+                List<String> htmlUrls = jdbcTemplate.queryForList(sql, String.class,projectInfo.getId(), pageSize, offset);
+                if (!htmlUrls.isEmpty()) {
+                    for (String htmlUrl : htmlUrls) {
+                        try  {
+                            List<TextdictInfo> textDictInfoDefaultByHtml = new ArrayList<>();
+                            List<TextdictInfo> textDictInfoTipsByHtml = new ArrayList<>();
+                            // 获取html中的 默认值信息和提示信息
+                            getTextDictInfos(htmlUrl, textDictInfoTipsByHtml, textDictInfoDefaultByHtml);
+                            List<WbsTreePrivate> wbsTreePrivates = jdbcTemplate.query("SELECT * from m_wbs_tree_private WHERE is_deleted = 0 and project_id = ? and html_url = ?", new BeanPropertyRowMapper<>(WbsTreePrivate.class),
+                                    projectInfo.getId(), htmlUrl);
+                            // 获取表元素信息
+                            Map<String, Map<String, String>> tableElementInfo = getTableElementInfo(wbsTreePrivates);
+                            for (WbsTreePrivate wbsTreePrivate : wbsTreePrivates) {
+                                List<TextdictInfo> textDictInfoList = jdbcTemplate.query("SELECT * from m_textdict_info WHERE type in (4,5) and is_deleted = 0 and tab_id = " + wbsTreePrivate.getPKeyId() + " and project_id = " + wbsTreePrivate.getProjectId(),
+                                        new BeanPropertyRowMapper<>(TextdictInfo.class));
+                                Map<String, String> map = tableElementInfo.get(wbsTreePrivate.getInitTableName());
+                                Map<String, TextdictInfo> insertTextDictInfoMaps = new HashMap<>();
+                                List<TextdictInfo> updateHtmlTextDictInfos = new ArrayList<>();
+                                if (textDictInfoList.isEmpty()) {
+                                    createTextDictInfos(wbsTreePrivate, textDictInfoTipsByHtml, map, insertTextDictInfoMaps, 5, "提示信息");
+                                    createTextDictInfos(wbsTreePrivate, textDictInfoDefaultByHtml, map, insertTextDictInfoMaps, 4, "默认值");
+                                } else {
+                                    // 去重并保留id最大的
+                                    Map<String, TextdictInfo> tempMap = new HashMap<>();
+                                    textDictInfoList.forEach(info -> {
+                                        if (info.getColKey() == null || info.getColKey().isEmpty()) {
+                                            return;
+                                        }
+                                        TextdictInfo temp = tempMap.get(info.getColKey() + "_" + info.getType());
+                                        if (temp == null || info.getId() > temp.getId()) {
+                                            tempMap.put(info.getColKey() + "_" + info.getType(), info);
+                                        }
+                                    });
+                                    // 与html中的进行对比, 保留数据库中的值
+                                    textDictInfoDefaultByHtml.forEach(info -> {
+                                        TextdictInfo temp = tempMap.get(info.getColKey() + "_" + info.getType());
+                                        if (temp != null) {
+                                            if (!temp.getSigRoleName().equals(info.getSigRoleName())) {
+                                                // 更新html中的值
+                                                temp.setColName(info.getColName());
+                                                info.setSigRoleName(temp.getSigRoleName());
+                                                updateHtmlTextDictInfos.add(temp);
+                                            }
+                                            tempMap.remove(info.getColKey() + "_" + info.getType());
+                                        }
+                                        TextdictInfo textdictInfo = createTextDictInfo(wbsTreePrivate, map, 4, "默认值", info);
+                                        insertTextDictInfoMaps.put(textdictInfo.getColKey() + "_" + textdictInfo.getType(), textdictInfo);
+                                    });
+                                    textDictInfoTipsByHtml.forEach(info -> {
+                                        TextdictInfo temp = tempMap.get(info.getColKey() + "_" + info.getType());
+                                        if (temp != null) {
+                                            if (!temp.getSigRoleName().equals(info.getSigRoleName())) {
+                                                // 更新html中的值
+                                                temp.setColName(info.getColName());
+                                                info.setSigRoleName(temp.getSigRoleName());
+                                                updateHtmlTextDictInfos.add(temp);
+                                            }
+                                            tempMap.remove(info.getColKey() + "_" + info.getType());
+                                        }
+                                        TextdictInfo textdictInfo = createTextDictInfo(wbsTreePrivate, map, 5, "提示信息", info);
+                                        insertTextDictInfoMaps.put(textdictInfo.getColKey() + "_" + textdictInfo.getType(), textdictInfo);
+                                    });
+                                    if (!tempMap.isEmpty()) {
+                                        tempMap.forEach((key, value) -> {
+                                            if (value.getType() == 4) {
+                                                TextdictInfo textdictInfo = createTextDictInfo(wbsTreePrivate, map, 4, "默认值", value);
+                                                insertTextDictInfoMaps.put(textdictInfo.getColKey() + "_" + textdictInfo.getType(), textdictInfo);
+                                            } else if (value.getType() == 5) {
+                                                TextdictInfo textdictInfo = createTextDictInfo(wbsTreePrivate, map, 5, "提示信息", value);
+                                                insertTextDictInfoMaps.put(textdictInfo.getColKey() + "_" + textdictInfo.getType(), textdictInfo);
+                                            }
+                                            updateHtmlTextDictInfos.add(value);
+                                        });
+                                    }
+                                }
+                                String replace;
+                                if (!updateHtmlTextDictInfos.isEmpty()) {
+                                    InputStream fileInputStream = FileUtils.getInputStreamByUrl(wbsTreePrivate.getHtmlUrl());
+                                    String htmlString = IoUtil.readToString(fileInputStream);
+                                    Document doc = Jsoup.parse(htmlString);
+                                    updateHtmlTextDictInfos.forEach(textdictInfo -> {
+                                        Element element = doc.getElementById(textdictInfo.getColKey());
+                                        if (element != null) {
+                                            element.attr("placeholder", textdictInfo.getColName());
+                                            if (textdictInfo.getType() == 4) {
+                                                element.attr("defText", textdictInfo.getSigRoleName());
+                                            } else if (textdictInfo.getType() == 5) {
+                                                Element parent = element.parent();
+                                                // 判断 parent 是否是el-tooltip
+                                                if (parent.tagName().equals("el-tooltip")) {
+                                                    parent.attr("content", textdictInfo.getSigRoleName());
+                                                } else {
+                                                    String lastHtml = " <el-tooltip content='" + textdictInfo.getSigRoleName() + "' placement='top' effect='customized'>" + parent.html() + "</el-tooltip>";
+                                                    parent.empty().append(lastHtml);
+                                                }
+                                            }
+                                        }
+                                    });
+                                    String url = wbsTreePrivate.getHtmlUrl();
+                                    File writeFile = new File(url);
+                                    FileUtil.writeToFile(writeFile, doc.html(), Boolean.parseBoolean("UTF-8"));
+                                    String str1 = url.replace("Desktop//privateUrl", "Desktop/privateUrl");
+                                    replace = str1.replace("\\", "\\\\");
+                                } else {
+                                    replace = null;
+                                }
+                                transactionTemplate.execute( status -> {
+                                    if (!insertTextDictInfoMaps.isEmpty()) {
+                                        // 使用jdbcTemplate批量插入
+                                        jdbcTemplate.batchUpdate("insert into m_textdict_info_copy3 (id,name,type,tab_id,col_key,col_name,sig_role_id,sig_role_name,pyzbx,pyzby,excel_id,project_id,is_deleted,time_col_key,time_name,time_state) values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",
+                                                insertTextDictInfoMaps.values(),
+                                                insertTextDictInfoMaps.values().size(), (ps, textdictInfo) -> {
+                                                    ps.setLong(1, textdictInfo.getId());
+                                                    ps.setString(2, textdictInfo.getName());
+                                                    ps.setInt(3, textdictInfo.getType());
+                                                    ps.setString(4, textdictInfo.getTabId());
+                                                    ps.setString(5, textdictInfo.getColKey());
+                                                    ps.setString(6, textdictInfo.getColName());
+                                                    ps.setString(7, textdictInfo.getSigRoleId());
+                                                    ps.setString(8, textdictInfo.getSigRoleName());
+                                                    ps.setDouble(9, 0);
+                                                    ps.setDouble(10, 0);
+                                                    ps.setString(11, textdictInfo.getExcelId());
+                                                    ps.setString(12, textdictInfo.getProjectId());
+                                                    ps.setInt(13, 0);
+                                                    ps.setString(14, textdictInfo.getTimeColKey());
+                                                    ps.setString(15, textdictInfo.getTimeName());
+                                                    ps.setInt(16, 0);
+                                                }
+                                        );
+                                    }
+                                    if (replace != null) {
+                                        String updateSqlP = "update m_wbs_tree_private_copy6 set html_url = '" + replace + "' where p_key_id = " + wbsTreePrivate.getPKeyId() + " and project_id = " + wbsTreePrivate.getProjectId();
+                                        jdbcTemplate.execute(updateSqlP);
+                                    }
+                                    if (!textDictInfoList.isEmpty()) {
+                                        List<Long> ids = textDictInfoList.stream().map(TextdictInfo::getId).collect(Collectors.toList());
+                                        jdbcTemplate.execute("update  m_textdict_info_copy3 set is_deleted = 2 where  id in (" + StringUtil.join(ids, ",") + ")");
+                                    }
+                                    return true;
+                                });
+                            }
+                        } catch (Exception e) {
+                            e.printStackTrace();
+                        }
+                    }
+                } else {
+                    flag = false;
+                }
+                offset  += pageSize;
+            }
+        });
+    }
+    private static void createTextDictInfos(WbsTreePrivate wbsTreePrivate, List<TextdictInfo> textDictInfos, Map<String, String> map, Map<String, TextdictInfo> insertTextDictInfoMaps, int type, String name) {
+        if (!textDictInfos.isEmpty()) {
+            for (TextdictInfo textdictInfo : textDictInfos) {
+                TextdictInfo saveTextdictInfo = createTextDictInfo(wbsTreePrivate, map, type, name, textdictInfo);
+                insertTextDictInfoMaps.put(saveTextdictInfo.getColKey() + "_" + saveTextdictInfo.getType(), saveTextdictInfo);
+            }
+        }
+    }
+    @NotNull
+    private static TextdictInfo createTextDictInfo(WbsTreePrivate wbsTreePrivate, Map<String, String> map, int type, String name, TextdictInfo textdictInfo) {
+        TextdictInfo saveTextdictInfo = new TextdictInfo();
+        saveTextdictInfo.setColKey(textdictInfo.getColKey());
+        saveTextdictInfo.setColName(textdictInfo.getColName());
+        saveTextdictInfo.setSigRoleName(textdictInfo.getSigRoleName());
+        saveTextdictInfo.setId(SnowFlakeUtil.getId());
+        saveTextdictInfo.setTabId(wbsTreePrivate.getPKeyId() + "");
+        saveTextdictInfo.setType(type);
+        saveTextdictInfo.setName(name);
+        saveTextdictInfo.setExcelId(wbsTreePrivate.getExcelId() + "");
+        saveTextdictInfo.setProjectId(wbsTreePrivate.getProjectId());
+        if (map != null) {
+            String s = map.get(saveTextdictInfo.getColKey().split("__")[0]);
+            if (s != null && !s.trim().isEmpty()) {
+                saveTextdictInfo.setColName(s);
+            }
+        }
+        return saveTextdictInfo;
+    }
+    private Map<String, Map<String, String>> getTableElementInfo(List<WbsTreePrivate> wbsTreePrivates) {
+        String inSql = wbsTreePrivates.stream().map(e -> "'" + e.getInitTableName() + "'").distinct().collect(Collectors.joining(","));
+        List<TableInfo> tableInfos = jdbcTemplate.query("SELECT id, tab_en_name from m_table_info  where tab_en_name in (" + inSql + ")", new BeanPropertyRowMapper<>(TableInfo.class));
+        if (tableInfos.isEmpty()) {
+            return new HashMap<>();
+        }
+        Map<String, String> map = tableInfos.stream().collect(Collectors.toMap(tableInfo -> tableInfo.getId() + "", TableInfo::getTabEnName));
+        List<WbsFormElement> wbsFormElementList = jdbcTemplate.query("SELECT f_id,e_key,e_name from m_wbs_form_element WHERE f_id in (" + StringUtil.join(map.keySet(), ",") + ")", new BeanPropertyRowMapper<>(WbsFormElement.class));
+        // 将 initTableNames 与 wbsFormElementList 关联
+        return wbsFormElementList.stream().peek(item -> item.setFId(map.get(item.getFId())))
+                .collect(Collectors.groupingBy(WbsFormElement::getFId, Collectors.toMap(WbsFormElement::getEKey, WbsFormElement::getEName, (v1, v2) -> v1)));
+    }
+    private static void getTextDictInfos(String htmlUrl, List<TextdictInfo> textDictInfoTips, List<TextdictInfo> textDictInfoDefault) throws Exception {
+        InputStream fileInputStream = FileUtils.getInputStreamByUrl(htmlUrl);
+        String htmlString = IoUtil.readToString(fileInputStream);
+        Document doc = Jsoup.parse(htmlString);
+        Element table = doc.select("table").first();
+        Elements trs = table.select("tr");
+        trs.forEach(tr -> {
+            Elements td = tr.select("td");
+            for (Element element : td) {
+                Elements tooltips = element.select("el-tooltip");
+                getTextDictInfo(tooltips, "content", textDictInfoTips);
+                Elements inputs = element.select("el-input");
+                getTextDictInfo(inputs, "deftext", textDictInfoDefault);
+            }
+        });
+    }
+    private static void getTextDictInfo(Elements elements, String attrName, List<TextdictInfo> textDictInfos) {
+        if (!elements.isEmpty()) {
+            elements.forEach(element -> {
+                String content = element.attr(attrName);
+                if (content != null && !content.trim().isEmpty()) {
+                    String keyname = element.children().attr("keyname");
+                    String placeholder = element.children().attr("placeholder");
+                    if (keyname == null || !keyname.trim().isEmpty()) {
+                        String html = element.html();
+                        keyname = getHtmlAttrValue(html, "keyname");
+                        placeholder = getHtmlAttrValue(html, "placeholder");
+                    }
+                    if (keyname != null) {
+                        TextdictInfo info = new TextdictInfo();
+                        info.setColKey(keyname);
+                        info.setColName(placeholder);
+                        info.setSigRoleName(content);
+                        textDictInfos.add(info);
+                    }
+                }
+            });
+        }
+    }
+    private static String getHtmlAttrValue(String html, String attr) {
+        int index = html.indexOf(attr);
+        if (index > 0) {
+            int start = attr.length() + index + 1;
+            char c = html.charAt(start);
+            return html.substring(start + 1, html.indexOf(c, start + 1));
+        }
+        return null;
+    }
 }

+ 58 - 15
blade-service/blade-user/src/main/java/org/springblade/system/user/service/impl/UserServiceImpl.java

@@ -806,7 +806,6 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
                                         Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(WbsTreeContractLazyVO::getPKeyId))),
                                         ArrayList::new
                                 ));
-
                         /*获取当前合同段节点对应的资料填报QueryInfo本地缓存信息*/
                         List<WbsTreeContractLazyQueryInfoVO> queryInfoList = this.getQueryInfoList(contractId, tableOwner);
                         Map<Long, Integer> queryInfoMaps = queryInfoList.stream().filter(f -> Func.isNotEmpty(f.getWbsId())&&Func.isNotEmpty(f.getStatus()))
@@ -814,7 +813,7 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
                         List<Long> pKeyIdList = new ArrayList<>(queryInfoMaps.keySet());
 
                         /* ================ 处理数量 ================ */
-                        List<WbsTreeContractLazyVO> lowestNodesTB = distinctLowestNodesAll.parallelStream().filter(f -> pKeyIdList.contains(f.getPKeyId())).collect(Collectors.toList());
+                        List<WbsTreeContractLazyVO> lowestNodesTB = distinctLowestNodesAll.parallelStream().filter(f -> queryInfoMaps.containsKey(f.getPKeyId())).collect(Collectors.toList());
                         List<Long> lowestNodeParentIdsTB = lowestNodesTB.parallelStream().map(WbsTreeContractLazyVO::getParentId).collect(Collectors.toList());
                         List<WbsTreeContractLazyVO> resultParentNodesTB = this.getCachedParentCountNodes(contractId, lowestNodeParentIdsTB, nodesAll, tableOwner);
                         Map<Long, WbsTreeContractLazyVO> lowestNodesMap = lowestNodesTB.stream()
@@ -831,7 +830,7 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
                         long startTime = System.currentTimeMillis();
 //                        List<NodeVO> nodeVOList = distinctNodesAll.stream().map(this::convertToNodeVO).collect(Collectors.toList());
 //                        Map<Long, NodeVO> nodeVOMap = nodeVOList.stream().collect(Collectors.toMap(NodeVO::getId, vo -> vo, (existing, replacement) -> existing));
-                        List<NodeVO> treeNodeVOList = this.buildNodeTreeByStream(distinctNodesAll, lowestNodesMap);
+                        List<NodeVO> treeNodeVOList = this.buildNodeTreeByStream1(distinctNodesAll, lowestNodesMap);
 //                        NodeVO.calculateStatusToDFS(treeNodeVOList, nodeVOMap);
                         Map<Long, Integer> nodeColorStatusMap = new HashMap<>();
                         NodeVO.calculateStatusToDFS1(treeNodeVOList, nodeColorStatusMap);
@@ -842,7 +841,6 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
                         long endTime = System.currentTimeMillis();
                         long executionTime = endTime - startTime;
                         _logger.info("合同段 " + contractId + " 处理颜色 执行时间:" + executionTime + " ms");
-
                         /* ================ 处理最终结果集 ================ */
                         if (lazyNodes.size() > 0) {
                             Map<Long, Integer> countMap = new HashMap<>();
@@ -974,7 +972,7 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
 
 //                                List<NodeVO> nodeVOList = distinctNodesAll.stream().map(this::convertToNodeVO).collect(Collectors.toList());
 //                                Map<Long, NodeVO> nodeVOMap = nodeVOList.stream().collect(Collectors.toMap(NodeVO::getId, vo -> vo, (existing, replacement) -> existing));
-                                List<NodeVO> treeNodeVOList = this.buildNodeTreeByStream(distinctNodesAll, lowestNodesMap);
+                                List<NodeVO> treeNodeVOList = this.buildNodeTreeByStream1(distinctNodesAll, lowestNodesMap);
 //                                NodeVO.calculateStatusToDFS(treeNodeVOList, nodeVOMap);
 //                                List<NodeVO> nodeVOS = this.flattenTree(treeNodeVOList);
 //                                Map<Long, Integer> nodeColorStatusMap = nodeVOS.stream().collect(Collectors.toMap(NodeVO::getPKeyId, NodeVO::getStatus, (existing, replacement) -> existing));
@@ -1396,7 +1394,7 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
                     }
                 }
                 //更新本地缓存
-                localCacheNodes.put(contractId, nodesAll);
+//                localCacheNodes.put(contractId, nodesAll);
             }
         }
         return nodesAll;
@@ -1446,7 +1444,7 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
 
         if (queryInfoList.size() > 0) {
             //更新本地缓存
-            localCacheQueryInfos.put(cacheKey, queryInfoList);
+//            localCacheQueryInfos.put(cacheKey, queryInfoList);
         }
         return queryInfoList;
     }
@@ -1471,17 +1469,17 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
             long startTime = System.currentTimeMillis();
 
             /*重新计算,进行递归获取父节点计数统计*/
-            this.recursiveGetParentNodes(resultParentNodesTB, lowestNodeParentIdsTB, nodesAll);
-//            Map<Long, List<WbsTreeContractLazyVO>> map = nodesAll.stream().collect(Collectors.groupingBy(WbsTreeContractLazyVO::getId));
-//            recursiveGetParentNodes(resultParentNodesTB, lowestNodeParentIdsTB, map);
+//            this.recursiveGetParentNodes(resultParentNodesTB, lowestNodeParentIdsTB, nodesAll);
+            Map<Long, List<WbsTreeContractLazyVO>> map = nodesAll.stream().collect(Collectors.groupingBy(WbsTreeContractLazyVO::getId));
+            recursiveGetParentNodes(resultParentNodesTB, lowestNodeParentIdsTB, map);
             long endTime = System.currentTimeMillis();
             long executionTime = endTime - startTime;
             _logger.info("合同段 " + contractId + " wbs节点树 数量计算 执行时间:" + executionTime + " ms");
 
-            if (resultParentNodesTB.size() > 0) {
-                //更新本地缓存
-                localCacheParentCountNodes.put(cacheKey, resultParentNodesTB);
-            }
+//            if (resultParentNodesTB.size() > 0) {
+//                //更新本地缓存
+//                localCacheParentCountNodes.put(cacheKey, resultParentNodesTB);
+//            }
         }
         return resultParentNodesTB;
     }
@@ -1551,7 +1549,7 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
                 })
                 .collect(Collectors.toList());
         List<Long> collect = collectedNodes.stream()
-                .map(WbsTreeContractLazyVO::getParentId).filter(Objects::nonNull).distinct()
+                .map(WbsTreeContractLazyVO::getParentId).filter(Objects::nonNull)
                 .collect(Collectors.toList());
         if (!collect.isEmpty()) {
             result.addAll(collectedNodes);
@@ -1614,6 +1612,51 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
         return result;
     }
 
+    /**
+     * 构造树形结构数据 (解决节点颜色问题)
+     *
+     * @param distinctNodesAll 去重后所有节点数据
+     * @return
+     */
+    public List<NodeVO> buildNodeTreeByStream1(List<WbsTreeContractLazyVO> distinctNodesAll,
+                                              Map<Long, WbsTreeContractLazyVO> lowestNodesMap) {
+        List<WbsTreeContractLazyVO> list = distinctNodesAll.stream().filter(f->f.getParentId()!=null).filter(f -> f.getParentId().equals(0L)).collect(Collectors.toList());
+        Map<Long, List<WbsTreeContractLazyVO>> map = distinctNodesAll.stream().filter(f->f.getParentId()!=null).collect(Collectors.groupingBy(WbsTreeContractLazyVO::getParentId));
+        Map<Long, NodeVO> nodeVOMap = new HashMap<>();
+        return recursionFnNodeTree(list, map, lowestNodesMap,nodeVOMap);
+    }
+
+    public List<NodeVO> recursionFnNodeTree
+            (List<WbsTreeContractLazyVO> list, Map<Long, List<WbsTreeContractLazyVO>> map,
+             Map<Long, WbsTreeContractLazyVO> lowestNodesMap, Map<Long, NodeVO> nodeVOMap) {
+        List<NodeVO> result = new ArrayList<>();
+        for (WbsTreeContractLazyVO vo : list) {
+            if (vo.getHasChildren().equals(0)) {
+                WbsTreeContractLazyVO lowestNodeVO = lowestNodesMap.getOrDefault(vo.getPKeyId(), null);
+                if (lowestNodeVO != null && lowestNodeVO.getColorStatus() != null) {
+                    //最底层颜色初始化
+                    vo.setColorStatus(lowestNodeVO.getColorStatus());
+                }
+            } else {
+                //非最底层节点,颜色默认=1黑色
+                vo.setColorStatus(1);
+            }
+            //转换为NodeVO
+            NodeVO nodeVO = convertToNodeVO(vo);
+            nodeVOMap.put(nodeVO.getPKeyId(), nodeVO);
+            List<WbsTreeContractLazyVO> childrenList = map.get(vo.getId());
+            if (childrenList != null && !childrenList.isEmpty()) {
+                List<WbsTreeContractLazyVO> collect = childrenList.stream().filter(child -> !nodeVOMap.containsKey(child.getPKeyId()))
+                        .collect(Collectors.toList());
+                if (!collect.isEmpty()) {
+                    nodeVO.setChildren(recursionFnNodeTree(collect, map, lowestNodesMap, nodeVOMap));
+                }
+            }
+            result.add(nodeVO);
+        }
+        return result;
+    }
+
     /**
      * 树形层级结构转为普通List
      *