Browse Source

Merge remote-tracking branch 'origin/master' into master

yangyj 3 years ago
parent
commit
c0b25657a4
36 changed files with 2075 additions and 236 deletions
  1. 3 2
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/vo/MaterialProgressVO.java
  2. 3 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/vo/NeiWaiYeProgressVO.java
  3. 3 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/feign/ArchiveTreeClient.java
  4. 1 1
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/feign/WbsTreeContractClient.java
  5. 7 0
      blade-service/blade-business/src/main/java/org/springblade/business/controller/ArchiveFileController.java
  6. 9 2
      blade-service/blade-business/src/main/java/org/springblade/business/controller/ConstructionLedgerController.java
  7. 50 18
      blade-service/blade-business/src/main/java/org/springblade/business/controller/InformationWriteQueryController.java
  8. 33 40
      blade-service/blade-business/src/main/java/org/springblade/business/controller/MaterialProgressController.java
  9. 11 0
      blade-service/blade-business/src/main/java/org/springblade/business/controller/NeiWaiYeProgressController.java
  10. 2 0
      blade-service/blade-business/src/main/java/org/springblade/business/controller/RecycleBinController.java
  11. 5 2
      blade-service/blade-business/src/main/java/org/springblade/business/controller/UserOpinionController.java
  12. 3 1
      blade-service/blade-business/src/main/java/org/springblade/business/controller/UserOpinionFlowController.java
  13. 2 1
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/UserOpinionMapper.java
  14. 19 2
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/UserOpinionMapper.xml
  15. 0 4
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/ArchiveFileServiceImpl.java
  16. 9 1
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/UserOpinionServiceImpl.java
  17. 37 1
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/WeatherInfoServiceImpl.java
  18. 22 0
      blade-service/blade-manager/pom.xml
  19. 21 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/aop/AvoidRepeatableCommit.java
  20. 78 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/aop/AvoidRepeatableCommitAspect.java
  21. 48 21
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ExcelTabController.java
  22. 6 11
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ProjectInfoController.java
  23. 18 3
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/TextdictInfoController.java
  24. 16 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/feign/ArchiveTreeClientImpl.java
  25. 2 2
      blade-service/blade-manager/src/main/java/org/springblade/manager/feign/WbsTreeContractClientImpl.java
  26. 2 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsTreeContractMapper.java
  27. 24 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsTreeContractMapper.xml
  28. 6 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsTreePrivateMapper.xml
  29. 2 5
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ArchiveTreeServiceImpl.java
  30. 47 48
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ExcelTabServiceImpl.java
  31. 3 3
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsFormElementServiceImpl.java
  32. 20 22
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreeContractServiceImpl.java
  33. 44 13
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreePrivateServiceImpl.java
  34. 31 33
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreeServiceImpl.java
  35. 122 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/unit/ProtoStuffSerializerUtil.java
  36. 1366 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/unit/RedisUtil.java

+ 3 - 2
blade-service-api/blade-business-api/src/main/java/org/springblade/business/vo/MaterialProgressVO.java

@@ -200,8 +200,9 @@ public class MaterialProgressVO {
             this.title = title;
             this.amount = amount;
             this.successAmount = successAmount;
-            if(successAmount != 0L && amount > 0){
-                this.ratio = new BigDecimal(successAmount.toString()).divide(new BigDecimal(amount.toString()), 0, BigDecimal.ROUND_HALF_UP);
+            if(amount > 0){
+                this.ratio = new BigDecimal(successAmount.toString()).divide(new BigDecimal(amount.toString()), 4, BigDecimal.ROUND_HALF_UP);
+                this.ratio = this.ratio.multiply(new BigDecimal("100")).setScale(2, BigDecimal.ROUND_HALF_UP);
             } else {
                 this.ratio = new BigDecimal("0");
             }

+ 3 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/vo/NeiWaiYeProgressVO.java

@@ -49,6 +49,9 @@ public class NeiWaiYeProgressVO {
 
             double result2 = Double.parseDouble(String.valueOf(new BigDecimal(waiYeSuccessAmount.toString()).divide(new BigDecimal(amount.toString()), 2, BigDecimal.ROUND_HALF_UP)));
             this.waiYeRatio = result2 > -1 ? result2 * 100 : 0;
+        } else {
+            this.neiYeRatio = 0.00;
+            this.waiYeRatio = 0.00;
         }
     }
 

+ 3 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/feign/ArchiveTreeClient.java

@@ -20,6 +20,9 @@ public interface ArchiveTreeClient {
      */
     String API_PREFIX = "/api/manager/archive";
 
+    @PostMapping(API_PREFIX + "/queryAllChildByAncestors")
+    List<ArchiveTree> queryAllChildByAncestors(@RequestParam String id);
+
     @PostMapping(API_PREFIX + "/queryTreeNodeByIds")
     List<ArchiveTree> queryTreeNodeByIds(@RequestParam List<String> ids);
 

+ 1 - 1
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/feign/WbsTreeContractClient.java

@@ -74,7 +74,7 @@ public interface WbsTreeContractClient {
     WbsTreeContract getContractNodeByPrimaryKeyId(@RequestParam String primaryKeyId);
 
     @PostMapping(API_PREFIX + "/removeContractTreeNode")
-    Boolean removeContractTreeNode(@RequestParam String ids);
+    Boolean removeContractTreeNode(@RequestParam List<String> ids);
 
     /**
      * 根据合同段ID和id获取合同段划分树的节点信息

+ 7 - 0
blade-service/blade-business/src/main/java/org/springblade/business/controller/ArchiveFileController.java

@@ -216,6 +216,13 @@ public class ArchiveFileController extends BladeController {
 	@ApiOperationSupport(order = 4)
 	@ApiOperation(value = "分页")
 	public R<IPage<ArchiveFileVO>> page(ArchiveFileVO queryVo){
+		List<ArchiveTree> archiveTrees = this.archiveTreeClient.queryAllChildByAncestors(queryVo.getNodeIds());
+		if(archiveTrees != null && archiveTrees.size() > 0){
+			List<String> ids = JSONArray.parseArray(JSONObject.toJSONString(archiveTrees.stream().map(ArchiveTree::getId).distinct().collect(Collectors.toList())), String.class);
+			ids.add(queryVo.getNodeIds());
+			queryVo.setNodeIdArray(ids);
+		}
+
 		return R.data(this.archiveFileService.selectArchiveFilePage(queryVo));
 	}
 

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

@@ -1,8 +1,6 @@
 package org.springblade.business.controller;
 
 import cn.hutool.core.date.DateUtil;
-import com.alibaba.fastjson.JSONArray;
-import com.alibaba.fastjson.JSONObject;
 import io.swagger.annotations.*;
 import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
 import lombok.AllArgsConstructor;
@@ -164,6 +162,15 @@ public class ConstructionLedgerController extends BladeController {
 			vos.setDetectionTimeStr(DateUtil.format(vos.getSiteEndTime(), "yyyy-MM-dd"));
 			vos.setDetectionStartTimeValue(DateUtil.format(vos.getDetectionStartTime(), "yyyy-MM-dd"));
 			vos.setDetectionEndTimeValue(DateUtil.format(vos.getDetectionEndTime(), "yyyy-MM-dd"));
+
+			if(StringUtils.isNotEmpty(vos.getSiteTimeStr()) &&
+					StringUtils.isNotEmpty(vos.getDetectionTimeStr()) &&
+					StringUtils.isNotEmpty(vos.getDetectionStartTimeValue()) &&
+					StringUtils.isNotEmpty(vos.getDetectionEndTimeValue())){
+
+				vos.setSiteTimeStr(vos.getSiteTimeStr() + "~" + vos.getDetectionTimeStr());
+				vos.setDetectionTimeStr(vos.getDetectionStartTimeValue() + "~" + vos.getDetectionEndTimeValue());
+			}
 		});
 
 		return R.data(voiPage);

+ 50 - 18
blade-service/blade-business/src/main/java/org/springblade/business/controller/InformationWriteQueryController.java

@@ -677,7 +677,12 @@ public class InformationWriteQueryController extends BladeController {
 
 				//重塑关键信息
 				Map<Long,Long> oldToNewIdMap = new HashMap<>();
-				allList.forEach(node -> oldToNewIdMap.put(node.getId(), SnowFlakeUtil.getId()));
+				//节点信息
+				Map<String, WbsTreeContract> nodeMap = new HashMap<>();
+				allList.forEach(node -> {
+					oldToNewIdMap.put(node.getId(), SnowFlakeUtil.getId());
+					nodeMap.put(node.getId().toString(), node);
+				});
 				//todo 单份复制
 				allList.forEach(node -> {
 					WbsTreeContract newData = new WbsTreeContract();
@@ -723,7 +728,7 @@ public class InformationWriteQueryController extends BladeController {
 
 					if(new Integer("6").equals(node.getDeptCategory())){
 						//生成施工日志
-						this.createLedger(newData, saveLedger);
+						this.createLedger(newData, saveLedger, nodeMap, null);
 					}
 				});
 			}
@@ -739,7 +744,11 @@ public class InformationWriteQueryController extends BladeController {
 
 					//重塑关键信息
 					Map<Long,Long> oldToNewIdMap = new HashMap<>();
-					allList.forEach(node -> oldToNewIdMap.put(node.getId(), SnowFlakeUtil.getId()));
+					Map<String, WbsTreeContract> nodeMap = new HashMap<>();
+					allList.forEach(node -> {
+						oldToNewIdMap.put(node.getId(), SnowFlakeUtil.getId());
+						nodeMap.put(node.getId().toString(), node);
+					});
 
 					allList.forEach(node -> {
 						WbsTreeContract newData = new WbsTreeContract();
@@ -784,7 +793,7 @@ public class InformationWriteQueryController extends BladeController {
 
 						if(new Integer("6").equals(node.getDeptCategory())){
 							//生成施工日志
-							this.createLedger(newData, saveLedger);
+							this.createLedger(newData, saveLedger, nodeMap, null);
 						}
 					});
 
@@ -820,10 +829,31 @@ public class InformationWriteQueryController extends BladeController {
 	/**
 	 * 生成施工日志记录
 	 */
-	private void createLedger(WbsTreeContract newData, List<ConstructionLedger> saveLedger){
+	private void createLedger(WbsTreeContract newData, List<ConstructionLedger> saveLedger, Map<String, WbsTreeContract> contractNodeMap, Map<String, WbsTreePrivate> projectNodeMap){
 		//工序,需要新增施工台账
 		ConstructionLedger ledger = new ConstructionLedger();
-		ledger.setSite(newData.getDeptName());
+		//获取这个节点的原始信息
+		if(contractNodeMap != null){
+			if(contractNodeMap.containsKey(newData.getOldId())){
+				WbsTreeContract contractNode = contractNodeMap.get(newData.getOldId());
+				if(contractNode.getParentId() != null && StringUtils.isNotEmpty(contractNode.getParentId().toString())){
+					WbsTreeContract parentNode = this.wbsTreeContractClient.queryCurrentNodeAllParent(Long.parseLong(contractNode.getContractId()), contractNode.getParentId());
+					if(parentNode != null){
+						ledger.setStation(StringUtils.isNotEmpty(parentNode.getFullName()) ? parentNode.getFullName() : parentNode.getDeptName());
+					}
+				}
+			}
+		} else if(projectNodeMap != null) {
+			if(projectNodeMap.containsKey(newData.getOldId())){
+				WbsTreePrivate contractNode = projectNodeMap.get(newData.getOldId());
+				if(contractNode.getParentId() != null && StringUtils.isNotEmpty(contractNode.getParentId().toString())){
+					WbsTreePrivate parentNode = this.wbsTreePrivateClient.queryPeersNodeByProjectIdAndId(contractNode.getProjectId(), contractNode.getParentId());
+					ledger.setStation(StringUtils.isNotEmpty(parentNode.getFullName()) ? parentNode.getFullName() : parentNode.getDeptName());
+				}
+			}
+		}
+
+		ledger.setSite(StringUtils.isNotEmpty(newData.getFullName()) ? newData.getFullName() : newData.getDeptName());
 		ledger.setIsBeton(newData.getIsConcrete());
 		ledger.setWbsId(newData.getPKeyId());
 		ledger.setContractId(Long.parseLong(newData.getContractId()));
@@ -1099,10 +1129,13 @@ public class InformationWriteQueryController extends BladeController {
 		String nodeName = StringUtils.isNotEmpty(removeNode.getFullName()) ? removeNode.getFullName() : removeNode.getDeptName() + "," + removeNodeList.stream().map(wbs -> StringUtils.isNotEmpty(wbs.getFullName()) ? wbs.getFullName() : wbs.getDeptName()).collect(Collectors.joining());
 
 		//获取当前节点下所有填报节点
-		List<QueryProcessDataVO> queryProcess = this.informationQueryService.queryProcessDataByParentIdAndContractId(removeNode.getId().toString(), 1, removeNode.getContractId());
-		if(queryProcess == null || queryProcess.size() == 0){
-			//填报节点
-			queryProcess = this.informationQueryService.queryProcessDataByPrimaryKeyIdAndClassify(removeNode.getPKeyId().toString(), 1);
+		List<QueryProcessDataVO> queryProcess = new ArrayList<>();
+		if(!Arrays.asList("1,2,3,4".split(",")).contains(removeNode.getMajorDataType().toString())){
+			queryProcess = this.informationQueryService.queryProcessDataByParentIdAndContractId(removeNode.getId().toString(), 1, removeNode.getContractId());
+			if(queryProcess == null || queryProcess.size() == 0){
+				//填报节点
+				queryProcess = this.informationQueryService.queryProcessDataByPrimaryKeyIdAndClassify(removeNode.getPKeyId().toString(), 1);
+			}
 		}
 
 		if(queryProcess != null && queryProcess.size() > 0){
@@ -1120,7 +1153,7 @@ public class InformationWriteQueryController extends BladeController {
 		//保存进回收站
 		this.recycleBinClient.saveDelBusinessData(ids, removeNode.getDeptName(), 2, parentNodeName.toString(), removeNode.getProjectId(), removeNode.getContractId());
 
-		return R.data(this.wbsTreeContractClient.removeContractTreeNode(ids));
+		return R.data(this.wbsTreeContractClient.removeContractTreeNode(Func.toStrList(ids)));
 	}
 
 	/**
@@ -1204,7 +1237,11 @@ public class InformationWriteQueryController extends BladeController {
 		if(selectedNodeList.size() > 0){
 			//重塑关键信息
 			Map<Long, Long> OldIdToNewIdMap = new HashMap<>();
-			selectedNodeList.forEach(half -> OldIdToNewIdMap.put(half.getId(), SnowFlakeUtil.getId()));
+			Map<String, WbsTreePrivate> nodeMap = new HashMap<>();
+			selectedNodeList.forEach(half -> {
+				OldIdToNewIdMap.put(half.getId(), SnowFlakeUtil.getId());
+				nodeMap.put(half.getId().toString(), half);
+			});
 
 			//处理数据
 			selectedNodeList.forEach(half -> {
@@ -1272,7 +1309,7 @@ public class InformationWriteQueryController extends BladeController {
 
 				if(new Integer("6").equals(newData.getDeptCategory())){
 					//生成施工日志
-					this.createLedger(newData, saveLedger);
+					this.createLedger(newData, saveLedger, null, nodeMap);
 				}
 
 			});
@@ -1346,11 +1383,6 @@ public class InformationWriteQueryController extends BladeController {
 				//还有子级,继续向下
 				this.foreachQueryChild(childs, childList);
 			}
-			//查询这个节点下是否存在表格数据
-			List<WbsTreePrivate> exlTables = this.wbsTreePrivateClient.queryExcelTableByParentId(parent);
-			if(exlTables != null && exlTables.size() > 0){
-				childList.addAll(exlTables);
-			}
 		});
 	}
 

+ 33 - 40
blade-service/blade-business/src/main/java/org/springblade/business/controller/MaterialProgressController.java

@@ -101,7 +101,7 @@ public class MaterialProgressController extends BladeController {
 
             }
         }
-        return R.data(300, null, "未找到数据");
+        return R.data(200, null, "未找到数据");
     }
 
     private void countAmount(List<WbsTreeContractTreeVOS> nodeResult, List<QueryProcessDataVO> queryDataResult, String contractId, MaterialProgressVO reVO){
@@ -210,48 +210,38 @@ public class MaterialProgressController extends BladeController {
                     }
                 }
                 if(countTypeList.size() > 0){
-                    //判断数量
-                    AtomicInteger imageAmount = new AtomicInteger();
-                    AtomicInteger videoAmount = new AtomicInteger();
-                    countTypeList.forEach(type -> {
-                        switch (type) {
-                            case 1:
-                                videoAmount.getAndIncrement();
-                                break;
-                            case 2:
-                                imageAmount.getAndIncrement();
-                                break;
-                        }
-                    });
-                    reVO.setContractImageClassificationList(countTypeList.size(), imageAmount.get(), videoAmount.get());
-
+                    this.setContractImageClassificationList(countTypeList, reVO);
                     return R.data(reVO);
                 }
             }
         } else {
             List<Integer> fileTypes = this.imageClassificationFileService.queryCurrentContractImageFileType(contractId);
             if(fileTypes != null && fileTypes.size() > 0){
-                //判断数量
-                AtomicInteger imageAmount = new AtomicInteger();
-                AtomicInteger videoAmount = new AtomicInteger();
-                fileTypes.forEach(type -> {
-                    switch (type) {
-                        case 1:
-                            videoAmount.getAndIncrement();
-                            break;
-                        case 2:
-                            imageAmount.getAndIncrement();
-                            break;
-                    }
-                });
-                reVO.setContractImageClassificationList(fileTypes.size(), imageAmount.get(), videoAmount.get());
-
+                //设置数据
+                this.setContractImageClassificationList(fileTypes, reVO);
                 return R.data(reVO);
             }
         }
 
 
-        return R.data(300, null, "未找到数据");
+        return R.data(200, null, "未找到数据");
+    }
+
+    private void setContractImageClassificationList(List<Integer> fileTypes, MaterialProgressVO reVO){
+        //判断数量
+        AtomicInteger imageAmount = new AtomicInteger();
+        AtomicInteger videoAmount = new AtomicInteger();
+        fileTypes.forEach(type -> {
+            switch (type) {
+                case 1:
+                    videoAmount.getAndIncrement();
+                    break;
+                case 2:
+                    imageAmount.getAndIncrement();
+                    break;
+            }
+        });
+        reVO.setContractImageClassificationList(fileTypes.size(), imageAmount.get(), videoAmount.get());
     }
 
     /**
@@ -294,7 +284,7 @@ public class MaterialProgressController extends BladeController {
             }
         }
 
-        return R.data(300, null, "未找到数据");
+        return R.data(200, null, "未找到数据");
     }
 
     private void setTaskParameter(MaterialProgressVO reVO, List<WbsTreeContract> submitNodeList){
@@ -326,25 +316,28 @@ public class MaterialProgressController extends BladeController {
 
         //处理工序资料
         if(processSubmitList != null && processSubmitList.size() > 0){
-            this.setParameter(reVO, processSubmitList);
+            this.setParameter("工序资料", reVO, processSubmitList);
         } else {
             reVO.setProcessMaterialStatusList("工序资料", 0, 0 ,0);
         }
+
         //处理开工报告
         if(workStartReportsSubmitList != null && workStartReportsSubmitList.size() > 0){
-            this.setParameter(reVO, workStartReportsSubmitList);
+            this.setParameter("开工报告", reVO, workStartReportsSubmitList);
         } else {
             reVO.setProcessMaterialStatusList("开工报告", 0, 0 ,0);
         }
+
         //处理评定资料
         if(evaluationSubmitList != null && evaluationSubmitList.size() > 0){
-            this.setParameter(reVO, evaluationSubmitList);
+            this.setParameter("评定资料", reVO, evaluationSubmitList);
         } else {
             reVO.setProcessMaterialStatusList("评定资料", 0, 0 ,0);
         }
+
         //处理中间交工
         if(completionSubmitList != null && completionSubmitList.size() > 0){
-            this.setParameter(reVO, completionSubmitList);
+            this.setParameter("中间交工", reVO, completionSubmitList);
         } else {
             reVO.setProcessMaterialStatusList("中间交工", 0, 0 ,0);
         }
@@ -392,7 +385,7 @@ public class MaterialProgressController extends BladeController {
             }
         }
 
-        return R.data(300, null, "未找到数据");
+        return R.data(200, null, "未找到数据");
     }
 
     /**
@@ -435,7 +428,7 @@ public class MaterialProgressController extends BladeController {
     /**
      * 设置参数
      */
-    private void setParameter(MaterialProgressVO reVO, List<InformationQuery> list){
+    private void setParameter(String title, MaterialProgressVO reVO, List<InformationQuery> list){
         //待审批
         AtomicInteger await = new AtomicInteger();
         //已审批
@@ -451,7 +444,7 @@ public class MaterialProgressController extends BladeController {
 
             }
         });
-        reVO.setProcessMaterialStatusList("工序资料", list.size(), await.get(), approval.get());
+        reVO.setProcessMaterialStatusList(title, list.size(), await.get(), approval.get());
     }
 
     /**

+ 11 - 0
blade-service/blade-business/src/main/java/org/springblade/business/controller/NeiWaiYeProgressController.java

@@ -1,10 +1,13 @@
 package org.springblade.business.controller;
 
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import lombok.AllArgsConstructor;
 import org.apache.commons.lang.StringUtils;
+import org.springblade.business.entity.ConstructionLedger;
+import org.springblade.business.service.IConstructionLedgerService;
 import org.springblade.business.service.IContractLogWbsService;
 import org.springblade.business.service.IInformationQueryService;
 import org.springblade.business.vo.NeiWaiYeProgressVO;
@@ -35,6 +38,8 @@ public class NeiWaiYeProgressController {
 
     private final IContractLogWbsService contractLogWbsService;
 
+    private final IConstructionLedgerService constructionLedgerService;
+
     /**
      * 内外业进度
      */
@@ -89,6 +94,12 @@ public class NeiWaiYeProgressController {
                             Integer logCount = this.contractLogWbsService.countContractLogBySelectPrimaryKeyIdsAndClassify(Func.toStrList(vo.getPrimaryKeyId()), 7);
                             if(logCount != null && logCount > 0){
                                 waiYeSuccessAmount ++;
+                            } else {
+                                //检查是否填有对应的施工台账(以施工台账是否填写开工时间为准)
+                                ConstructionLedger ledger = this.constructionLedgerService.getOne(Wrappers.<ConstructionLedger>lambdaQuery().eq(ConstructionLedger::getWbsId, vo.getPrimaryKeyId()));
+                                if(ledger != null && ledger.getSiteStartTime() != null){
+                                    waiYeSuccessAmount ++;
+                                }
                             }
                             //统计总数
                             amount ++;

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

@@ -147,6 +147,8 @@ public class RecycleBinController extends BladeController {
 			wrapper.lambda().eq(RecycleBin::getCreateUser, AuthUtil.getUserId());
 		}
 
+		wrapper.lambda().orderByDesc(RecycleBin::getCreateTime);
+
 		return R.data(this.recycleBinService.page(Condition.getPage(query), wrapper));
 	}
 	

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

@@ -265,7 +265,9 @@ public class UserOpinionController extends BladeController {
 
 		//生成第一次流程
 		List<UserOpinionFlow> saveFlowList = new ArrayList<>();
-		String manageTime = DateUtil.format(DateUtils.addDays(new Date(), 5), "yyyy-MM-dd");
+		Date nowDate = new Date();
+		//30分钟相应时间
+		String manageTime = DateUtil.format(DateUtil.plusMinutes(nowDate, 30), "yyyy-MM-dd HH:mm:ss");
 		//提交成功环节
 		saveFlowList.add(setUserData(new UserOpinionFlow(idKey, 2, 1, 1, "已提交", "已成功提交您的工单信息", manageTime, manageUser, manageUserName, manegeUserPhone)));
 		//分配维护人员环节
@@ -279,7 +281,8 @@ public class UserOpinionController extends BladeController {
 		//最后新增主表数据
 		UserOpinion newUserOpinion = new UserOpinion();
 		BeanUtils.copyProperties(userOpinionVo, newUserOpinion);
-		newUserOpinion.setCreateTime(new Date());
+		newUserOpinion.setCreateTime(nowDate);
+
 		return R.status(this.userOpinionService.save(newUserOpinion));
 	}
 

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

@@ -128,7 +128,9 @@ public class UserOpinionFlowController extends BladeController {
 
 			//生成新流程
 			List<UserOpinionFlow> saveFlowList = new ArrayList<>();
-			String manageTime = DateUtil.format(DateUtils.addDays(new Date(), 5), "yyyy-MM-dd");
+			Date nowDate = new Date();
+			//30分钟相应时间
+			String manageTime = DateUtil.format(DateUtil.plusMinutes(nowDate, 30), "yyyy-MM-dd HH:mm:ss");
 			//提交成功环节
 			saveFlowList.add(this.setUserData(new UserOpinionFlow(Long.parseLong(userOpinionId), 2, newNumber, 1, "已提交", "已成功提交您的工单信息", manageTime, manageUser, manageUserName, manegeUserPhone), true));
 			//分配维护人员环节

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

@@ -21,7 +21,6 @@ import org.springblade.business.entity.UserOpinion;
 import org.springblade.business.vo.BusinessUserOpinionVO;
 import org.springblade.business.vo.UserOpinionVO;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
 import java.util.List;
 
 /**
@@ -32,6 +31,8 @@ import java.util.List;
  */
 public interface UserOpinionMapper extends BaseMapper<UserOpinion> {
 
+	List<UserOpinion> opinionPage(@Param("current")Long current, @Param("size")Long size, @Param("param") UserOpinionVO userOpinion, @Param("currentUser") String currentUser);
+
 	List<UserOpinion> queryOpinionTypeAmount();
 
 	List<BusinessUserOpinionVO> queryManageUserOpinionList(@Param("currentUser") String currentUser);

+ 19 - 2
blade-service/blade-business/src/main/java/org/springblade/business/mapper/UserOpinionMapper.xml

@@ -72,11 +72,12 @@
                     uof.*
                 from
                 (
-                    select user_opinion_id,is_current,manage_time,number,sort,evaluation,manage_user_name from u_user_opinion_flow where is_deleted = 0
+                    select user_opinion_id,is_current,manage_time,number,sort,evaluation,manage_user_name from u_user_opinion_flow AS of1 where is_deleted = 0
                     <if test="currentUser != null and currentUser != ''">
                         and manage_user = #{currentUser}
                     </if>
-                    and sort = 4 order by number DESC
+                    and sort = 4
+                    and not exists(select 1 from u_user_opinion_flow AS of2 where of1.user_opinion_id = of2.user_opinion_id and of2.number > of1.number)
                 ) as uof
             ) as uof on uof.user_opinion_id = uo.id
             where uo.is_deleted = 0 order by uof.number DESC
@@ -91,4 +92,20 @@
         select id,project_id,contract_id,opinion_content,problem_type,create_time,good_number, number,create_user,create_user_name from u_user_opinion where is_deleted = 0 and create_user != #{currentUser} order by create_time DESC limit ${current},${size}
     </select>
 
+    <select id="opinionPage" resultMap="userOpinionResultMap">
+        select
+          id,
+          project_id,
+          contract_id,
+          opinion_content,
+          problem_type,
+          create_time,
+          good_number,
+          number,
+          create_user,
+          create_user_name
+        from u_user_opinion
+        where is_deleted = 0 order by create_user = #{currentUser} DESC,create_time DESC limit ${current},${size}
+    </select>
+
 </mapper>

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

@@ -39,10 +39,6 @@ public class ArchiveFileServiceImpl extends BaseServiceImpl<ArchiveFileMapper, A
 		//设置分页
 		IPage<ArchiveFileVO> iPage = Condition.getPage(query);
 
-		if(StringUtils.isNotEmpty(vo.getNodeIds())){
-			vo.setNodeIdArray(Arrays.asList(vo.getNodeIds().split(",")));
-		}
-
 		//汇总
 		Integer total = this.baseMapper.selectArchiveFileCount(vo);
 		if(total == null){

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

@@ -134,7 +134,7 @@ public class UserOpinionServiceImpl extends BaseServiceImpl<UserOpinionMapper, U
 						vo.setTimeRemaining("已处理");
 					} else {
 						//未处理
-						Date manageDate = DateUtil.parseDate(vo.getManageTime()), nowDate = new Date();
+						Date manageDate = DateUtil.parse(vo.getManageTime().contains(":") ? vo.getManageTime() : vo.getManageTime() + " 00:00:00", "yyyy-MM-dd HH:mm:ss"), nowDate = new Date();
 						long between = manageDate.getTime() - nowDate.getTime();
 						if(between > 0){
 							long day = between / (24 * 60 * 60 * 1000);
@@ -225,6 +225,11 @@ public class UserOpinionServiceImpl extends BaseServiceImpl<UserOpinionMapper, U
 	public IPage<UserOpinionVO> selectUserOpinionPage(IPage<UserOpinionVO> page, UserOpinionVO userOpinion, BladeUser users) {
 		//当前页面数据
 		long current = (page.getCurrent() - 1L) * page.getSize();
+		//获取总数
+		long pageCount = this.count();
+//		//获取数据
+//		List<UserOpinion> currentUserResult = this.baseMapper.opinionPage(current, page.getSize(), userOpinion, String.valueOf(users.getUserId()));
+
 		//获取当前用户的提交记录
 		List<UserOpinion> currentUserResult = this.baseMapper.queryCurrentUserOpinionList(users.getUserId());
 		//获取非当前用户提交记录
@@ -280,6 +285,9 @@ public class UserOpinionServiceImpl extends BaseServiceImpl<UserOpinionMapper, U
 				}
 
 			});
+
+			page.setTotal(pageCount);
+
 			return page.setRecords(resultVo);
 		}
 		return null;

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

@@ -9,7 +9,9 @@ import org.springblade.business.entity.WeatherInfo;
 import org.springblade.business.mapper.WeatherInfoMapper;
 import org.springblade.business.service.WeatherInfoService;
 //import org.springframework.scheduling.annotation.Scheduled;
+import org.springblade.core.tool.utils.Func;
 import org.springblade.manager.entity.ProjectContractArea;
+import org.springblade.manager.feign.ProjectClient;
 import org.springblade.manager.feign.ProjectContractAreaClient;
 import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Service;
@@ -25,6 +27,8 @@ public class WeatherInfoServiceImpl extends ServiceImpl<WeatherInfoMapper, Weath
 
     private final ProjectContractAreaClient projectContractAreaClient;
 
+    private final ProjectClient projectClient;
+
     /**
      * 根据所选年份获取当年所有天气台账
      */
@@ -93,7 +97,6 @@ public class WeatherInfoServiceImpl extends ServiceImpl<WeatherInfoMapper, Weath
         //获取所有合同段的定位信息
         List<ProjectContractArea> areaList = this.projectContractAreaClient.queryAllContractArea();
 
-        //todo 这里之后会换成批量
         for(ProjectContractArea area : areaList){
             try{
                 //校验当前区域是否已经获取当天日期(手动补填或自动获取)
@@ -125,4 +128,37 @@ public class WeatherInfoServiceImpl extends ServiceImpl<WeatherInfoMapper, Weath
         }
     }
 
+    /**
+     * 同步历史天气
+     */
+    @Scheduled(cron = "0 0 8 * * ?")
+    public void syncHistoryWeatherInfo(){
+        //获取所有合同段的定位信息
+        List<ProjectContractArea> areaList = this.projectContractAreaClient.queryAllContractArea();
+
+        //分组,以项目为单位
+        Map<String, List<ProjectContractArea>> map = new HashMap<>();
+        areaList.forEach(area -> {
+            List<ProjectContractArea> list;
+            if(map.containsKey(area.getProjectId())){
+                list = map.get(area.getProjectId());
+            } else {
+                list = new ArrayList<>();
+            }
+
+            list.add(area);
+            map.put(area.getProjectId(), list);
+        });
+
+        for(ProjectContractArea area : areaList){
+            try{
+                //获取项目的计划开工时间
+                this.projectClient.queryProjectList(Func.toStrList(area.getProjectId()));
+
+            }catch (Exception e){
+                e.printStackTrace();
+            }
+        }
+    }
+
 }

+ 22 - 0
blade-service/blade-manager/pom.xml

@@ -136,6 +136,28 @@
             <version>4.6.0.2</version>
         </dependency>
 
+        <!-- 序列化相关-->
+        <dependency>
+            <groupId>com.dyuproject.protostuff</groupId>
+            <artifactId>protostuff-core</artifactId>
+            <version>1.1.5</version>
+        </dependency>
+        <dependency>
+            <groupId>com.dyuproject.protostuff</groupId>
+            <artifactId>protostuff-runtime</artifactId>
+            <version>1.1.5</version>
+        </dependency>
+        <dependency>
+            <groupId>com.bstek.ureport</groupId>
+            <artifactId>ureport2-console</artifactId>
+            <version>2.2.9</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>me.zhyd.oauth</groupId>
+            <artifactId>JustAuth</artifactId>
+        </dependency>
+
     </dependencies>
 
 </project>

+ 21 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/aop/AvoidRepeatableCommit.java

@@ -0,0 +1,21 @@
+package org.springblade.manager.aop;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 避免接口重复提交AOP
+ * @author liuyc
+ * @since  2022-09-02
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface AvoidRepeatableCommit {
+    /**
+     * 过期时间,单位毫秒
+     */
+    long timeout() default 60000;
+
+}

+ 78 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/aop/AvoidRepeatableCommitAspect.java

@@ -0,0 +1,78 @@
+package org.springblade.manager.aop;
+
+import lombok.extern.slf4j.Slf4j;
+import me.zhyd.oauth.utils.IpUtils;
+import org.apache.commons.lang.StringUtils;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Before;
+import org.aspectj.lang.reflect.MethodSignature;
+import org.springblade.common.utils.SnowFlakeUtil;
+import org.springblade.core.log.exception.ServiceException;
+import org.springblade.core.tool.utils.DateUtil;
+import org.springblade.manager.unit.RedisUtil;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.lang.reflect.Method;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 避免接口重复提交AOP
+ * @author liuyc
+ * @since  2022-09-02
+ */
+@Aspect
+@Component
+@Slf4j
+public class AvoidRepeatableCommitAspect {
+
+    private final static String KEY_NAME = "submit-wbs-project:";
+
+    @Resource
+    private RedisUtil redisUtil;
+
+    @Around("@annotation(org.springblade.manager.aop.AvoidRepeatableCommit)")
+    public Object around(ProceedingJoinPoint point) throws Throwable {
+
+        String ip = IpUtils.getLocalIp();
+
+        //获取注解
+        MethodSignature signature = (MethodSignature) point.getSignature();
+        Method method = signature.getMethod();
+
+        //目标类、方法
+        String className = method.getDeclaringClass().getName();
+
+        String name = method.getName();
+
+        //类名和方法
+        String ipKey = String.format("%s#%s", className, name);
+
+        //HashCode
+        int hashCode = Math.abs(ipKey.hashCode());
+
+        String key = String.format("%s:%s_%d",KEY_NAME, ip, hashCode);
+
+        log.info("ipKey={},hashCode={},key={}", ipKey, hashCode, key);
+
+        AvoidRepeatableCommit avoidRepeatableCommit = method.getAnnotation(AvoidRepeatableCommit.class);
+
+        long timeout = avoidRepeatableCommit.timeout();
+
+        String value = redisUtil.get(key);
+
+        if (StringUtils.isNotEmpty(value)) {
+            throw new ServiceException("请勿重复提交请求,60秒后重试!");
+        }
+
+        //过期时间
+        redisUtil.setEx(key, String.valueOf(SnowFlakeUtil.getId()), timeout, TimeUnit.MILLISECONDS);
+
+        //执行方法
+        return point.proceed();
+
+    }
+
+}

+ 48 - 21
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ExcelTabController.java

@@ -117,7 +117,6 @@ public class ExcelTabController extends BladeController {
     // pdf转换
     private final CommonFileClient commonFileClient;
 
-    private final FileUtilsClient fileUtilsClient;
 
     private final IWbsParamService wbsParamService;
 
@@ -350,12 +349,12 @@ public class ExcelTabController extends BladeController {
 
 
     /**
-     * 清表编辑 - 下拉框 树节点
+     * 后管 -- 清表保存
      */
     @PostMapping("/sava-dataInfo")
     @ApiOperationSupport(order = 13)
     @ApiOperation(value = "编辑-保存", notes = "编辑-保存")
-    public R<List<WbsTreeVO>> savaDataInfo(@Valid @RequestBody WbsExclTabParmVO wbsExclTabParmVO, BladeUser bladeUser) {
+    public R<List<WbsTreeVO>> savaDataInfo(@Valid @RequestBody WbsExclTabParmVO wbsExclTabParmVO, BladeUser bladeUser) throws IOException {
         // 保存节点信息
         ExcelTab excelTab = new ExcelTab();
         if(wbsExclTabParmVO.getId()!=null){// 修改
@@ -378,15 +377,27 @@ public class ExcelTabController extends BladeController {
         List<ExcelTabWbsTypeVO> linkDataInfo = wbsExclTabParmVO.getLinkDataInfo();
 
         if(linkDataInfo!=null && linkDataInfo.size()>=1){
+            // 判断是否上传excle
+            if((excelTab.getFileUrl()!=null || excelTab.getFileUrl()!="") && excelTab.getFileType()!=3){
+                return R.fail("请上传清表!");
+            }
             for (ExcelTabWbsTypeVO info : linkDataInfo){
                 String[] pk_id = info.getLinkIds().split(",");
                 for(String pkInfo : pk_id){
+
                     UpdateWrapper<WbsTreePrivate> updateWrapper = new UpdateWrapper<>();
                     String [] pk_type = pkInfo.trim().split("_");
                     updateWrapper.in("p_key_id",Long.parseLong(pk_type[0]));
+
+                    if(pk_type[1].equals("2")){
+                        this.saveLinkeTab(excelTab.getId() ,Long.parseLong(pk_type[0]));
+                    }
+
                     updateWrapper.set("is_link_table",Integer.parseInt(pk_type[1]));
                     updateWrapper.set("excel_id",excelTab.getId());
+
                     wbsTreePrivateService.update(updateWrapper);
+
                 }
             }
         }
@@ -416,12 +427,13 @@ public class ExcelTabController extends BladeController {
             @ApiImplicitParam(name = "exceTabId", value = "清表id", required = true),
             @ApiImplicitParam(name = "tabId", value = "表Id", required = true)
     })
-    public R<List<ExceTabTreVO>> saveLinkeTab(Long exceTabId, Long tabId, BladeUser bladeUser) throws IOException {
+    public R<List<ExceTabTreVO>> saveLinkeTab(Long exceTabId, Long tabId) throws IOException {
         String file_path = ParamCache.getValue(CommonConstant.SYS_LOCAL_URL);
         // 查询私有项目信息
         WbsTreePrivate wbsTree = new WbsTreePrivate();
         wbsTree.setPKeyId(tabId);
         WbsTreePrivate aPrivate = wbsTreePrivateService.getOne(Condition.getQueryWrapper(wbsTree));
+        aPrivate.setExcelId(exceTabId);
 
         UpdateWrapper<WbsTreePrivate> updateWrapper = new UpdateWrapper<>();
         updateWrapper.in("p_key_id",tabId);
@@ -512,7 +524,7 @@ public class ExcelTabController extends BladeController {
 
 
     /**
-     * 清表生成html
+     * 质检 获取html接口
      */
     @GetMapping("/get-excel-html_buss")
     @ApiOperationSupport(order = 16)
@@ -535,6 +547,7 @@ public class ExcelTabController extends BladeController {
 
         String htmlString =  IoUtil.readToString(fileInputStream);
         htmlString = htmlString.replaceAll("placeholder","placeholderxx");
+     //   htmlString = htmlString.replaceAll("@focu","@focu212");
         // 解析 style
         Document doc = Jsoup.parse(htmlString);
         Element table = doc.select("table").first();
@@ -1275,6 +1288,10 @@ public class ExcelTabController extends BladeController {
         // 获取清表信息
         ExcelTab excelTab = excelTabService.getById(wbsTreeContract.getExcelId());
 
+        if(excelTab==null){
+            return R.fail("失败");
+        }
+
         Map<String, Object> DataInfo = (Map<String, Object>) getBussDataInfo(pkeyId).getData();
 
         // 获取excel流 和 html流
@@ -1373,7 +1390,7 @@ public class ExcelTabController extends BladeController {
         tableFileList.sort(Comparator.comparing(TableFile::getType));
 
 
-        List<String> dataListPdf = tableFileList.stream().filter(tableFile -> tableFile.getDomainPdfUrl()!=null).map(TableFile::getDomainPdfUrl).collect(Collectors.toList());
+        List<String> dataListPdf = tableFileList.stream().filter(tableFile -> tableFile.getDomainPdfUrl()!=null && (tableFile.getType()==1 || tableFile.getType()==2)).map(TableFile::getDomainPdfUrl).collect(Collectors.toList());
 
         String pdfPath2 = file_path+"/pdf//"+pkeyId+"_2.pdf";
 
@@ -1408,16 +1425,20 @@ public class ExcelTabController extends BladeController {
                 .eq(WbsTreeContract::getId,wbsTreeContract.getId())
                 .eq(WbsTreeContract::getContractId,wbsTreeContract.getContractId())
                 .eq(WbsTreeContract::getParentId,wbsTreeContract.getParentId()));
+        List<WbsTreeContract> wbsTreeContractList2 = wbsTreeContractList.stream().sorted(Comparator.comparing(WbsTreeContract::getCreateTime).reversed()).collect(Collectors.toList());
+
 
         long newPkId = SnowFlakeUtil.getId();
         Long  id = wbsTreeContract.getId();
         wbsTreeContract.setPKeyId(newPkId);
         wbsTreeContract.setCreateTime(new Date());
-        String deptName  = wbsTreeContract.getDeptName();
+        String deptName  = wbsTreeContractList2.get(0).getDeptName();
+
         if(deptName.indexOf("__")>=0){
-            deptName = deptName.split("__")[0]+"__"+wbsTreeContractList.size();
+            String oldName[] = deptName.split("__");
+            deptName = oldName[0]+"__"+ (Integer.parseInt(oldName[1])+1);
         }else{
-            deptName = deptName +"__"+wbsTreeContractList.size();
+            deptName = deptName +"__"+1;
         }
         wbsTreeContract.setDeptName(deptName);
         wbsTreeContract.setIsCopeTab(2);
@@ -1520,7 +1541,7 @@ public class ExcelTabController extends BladeController {
         tableFileList.sort(Comparator.comparing(TableFile::getType));
 
         //
-        List<String> dataListPdf = tableFileList.stream().filter(tableFile1 -> tableFile1.getDomainPdfUrl()!=null).map(TableFile::getDomainPdfUrl).collect(Collectors.toList());
+        List<String> dataListPdf = tableFileList.stream().filter(tableFile1 -> tableFile1.getDomainPdfUrl()!=null && (tableFile1.getType()==1 || tableFile1.getType()==2)).map(TableFile::getDomainPdfUrl).collect(Collectors.toList());
 
         String pdfPath2 = file_path+"/pdf//"+pkeyId+"_2.pdf";
         File tabpdf2 = ResourceUtil.getFile(pdfPath2);
@@ -1572,23 +1593,30 @@ public class ExcelTabController extends BladeController {
         String file_path = ParamCache.getValue(CommonConstant.SYS_LOCAL_URL);
         // 获取有权限的节点信息
         List<WbsTreeContract> wbsTreeContractList = wbsTreeContractService.searchNodeAllTable(nodeId, classify, contractId, projectId);
-        List<String> data = wbsTreeContractList.stream().filter(wbsTreeContract ->  wbsTreeContract.getPdfUrl()!=null && wbsTreeContract.getIsBussShow()!=2).map(WbsTreeContract::getPdfUrl).collect(Collectors.toList());
+        List<String> data = new ArrayList<>();
+
+        if(wbsTreeContractList!=null && wbsTreeContractList.size()>=1){
+            for(WbsTreeContract wbsInfo:wbsTreeContractList){
+                // 隐藏的不生成pdf
+                if(wbsInfo.getIsBussShow()!=2){ //
+                    if(wbsInfo.getPdfUrl()==null ||wbsInfo.getPdfUrl().equals("")){
+                        data.add(wbsInfo.getPdfUrl());
+                    }else{
+                        R bussPdfInfo = this.getBussPdfInfo(wbsInfo.getPKeyId());
+                        if (bussPdfInfo.getCode()==200){
+                            data.add(bussPdfInfo.getData()+"");
+                        }
+                    }
+                }
+            }
+        }
 
         String listPdf = file_path+"pdf/"+nodeId+".pdf";
         File tabpdf2 = ResourceUtil.getFile(listPdf);
         if(tabpdf2.exists()){
             tabpdf2.delete();
         }
-        // 添加从来没有预览过的pdf
-        for (WbsTreeContract wbsTreeContract:wbsTreeContractList){
-            if((wbsTreeContract.getPdfUrl()==null ||wbsTreeContract.getPdfUrl().equals("")) && wbsTreeContract.getIsBussShow()!=2){
-                 R bussPdfInfo = this.getBussPdfInfo(wbsTreeContract.getPKeyId());
-
-                data.add(bussPdfInfo.getData()+"");
-            }
-        }
         FileUtils.mergePdfPublicMethods(data,listPdf);
-
         BladeFile bladeFile = this.newIOSSClient.uploadFile(nodeId+".pdf", listPdf);
 
         // 合并pdf集合
@@ -1626,7 +1654,6 @@ public class ExcelTabController extends BladeController {
             fontProvider.addFont(fontProgram);
             properties.setFontProvider(fontProvider);
         } catch (IOException e) {
-            //  log.error("creat base font erro" , e );
             System.out.println("creat base font erro");
         }
         return properties;

+ 6 - 11
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ProjectInfoController.java

@@ -7,6 +7,7 @@ import lombok.AllArgsConstructor;
 
 import javax.validation.Valid;
 
+import org.springblade.core.log.exception.ServiceException;
 import org.springblade.core.mp.support.Condition;
 import org.springblade.core.mp.support.Query;
 import org.springblade.core.tool.api.R;
@@ -211,21 +212,15 @@ public class ProjectInfoController extends BladeController {
     @PostMapping("/submitWbsTreeInProject")
     @ApiOperationSupport(order = 12)
     @ApiOperation(value = "保存或修改分配项目级wbs树", notes = "传入WbsTreeContractDTO")
-    public R submitWbsTreeInProject(@RequestBody WbsTreeContractDTO pawDTO){
+    public R submitWbsTreeInProject(@RequestBody WbsTreeContractDTO pawDTO) {
         if (pawDTO.getWbsType() == 1) {
-            boolean b = wbsTreeService.submitWbsTreeInProject1(pawDTO);
-            if (b) {
-                return R.success("关联质检项目级树失败");
+            if (wbsTreeService.submitWbsTreeInProject1(pawDTO)) {
+                return R.success("关联质检项目级树成功");
             }
-            return R.fail(200,"关联质检项目级树失败");
         } else if (pawDTO.getWbsType() == 2) {
-            boolean b = wbsTreeService.submitWbsTreeInProject1(pawDTO);
-            if (b) {
-                return R.success("关联试验项目级树失败");
-            }
-            return R.fail(200,"关联试验项目级树失败");
+            throw new ServiceException("当前试验功能未开放");
         }
-        return R.fail(200, "操作失败");
+        return R.fail("操作失败");
     }
 
     /**

+ 18 - 3
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/TextdictInfoController.java

@@ -41,6 +41,7 @@ import org.springblade.manager.entity.WbsTreePrivate;
 import org.springblade.manager.mapper.WbsTreePrivateMapper;
 import org.springblade.manager.vo.TextdictDataInfoVO;
 import org.springblade.manager.vo.TextdictInfo_vo;
+import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.bind.annotation.RequestParam;
 import com.baomidou.mybatisplus.core.metadata.IPage;
@@ -55,7 +56,7 @@ import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.stream.Collectors;
+import java.util.Map;
 
 /**
  * 参数信息表 控制器
@@ -71,6 +72,9 @@ public class TextdictInfoController extends BladeController {
 
 	private final ITextdictInfoService textdictInfoService;
 	private final WbsTreePrivateMapper wbsTreePrivateMapper;
+
+	private final JdbcTemplate jdbcTemplate;
+
 	/**
 	 * 详情
 	 */
@@ -230,8 +234,6 @@ public class TextdictInfoController extends BladeController {
 			element.empty().append("<el-date-picker  v-model="+vmode+" type='datetimerange' placeholder="+placeholder+"  start-placeholder='开始日期'  end-placeholder='结束日期' format='YYYY年MM月DD日' trIndex="+trindex+" keyname="+keyname+" weighing="+weighing+" tdIndex="+tdindex+"  x1="+x1+" x2="+x2+" y1="+y1+" y2="+y2+">");
 			element.children().get(0).attr("@focus","getInformation("+oncklickText+")");
 			element.children().get(0).attr("@change","datePickerChange($event,'"+keyname+"')");
-			element.children().get(0).attr("@calendar-change","datePickerCalendarChange($event,'"+keyname+"')");
-
 		}else if(textdictInfo.getTextId().equals("img")){
 			element.empty().append("<el-upload placeholder="+placeholder+" v-model="+vmode+" keyname="+keyname+" weighing="+weighing+"  class='hc-upload-table-form' action='/api/blade-resource/oss/endpoint/put-file' trIndex="+trindex+" tdIndex="+tdindex+"  x1="+x1+" x2="+x2+" y1="+y1+" y2="+y2+"  @exceed='formUploadExceed' accept='image/png,image/jpg,image/jpeg' :headers='getTokenHeader' :show-file-list='false' > <img v-if='"+vmode+"' :src="+vmode+" class='hc-table-form-img' /> <div class='hc-table-form-icon' v-else> 点此选择文件并上传 </div> </el-upload>");
 			element.children().get(0).attr("@success","formUploadSuccess($event,'"+keyname+"')");
@@ -241,6 +243,19 @@ public class TextdictInfoController extends BladeController {
 			File writefile = new File(wbsTreePrivate.getHtmlUrl());
 		FileUtil.writeToFile(writefile, doc.html(), Boolean.parseBoolean("UTF-8"));
 		Thread.sleep(300);
+
+		// 清空相关的保存数据
+		String tabName = wbsTreePrivate.getInitTableName();
+		String isExitSql = " select * from information_schema.TABLES where TABLE_NAME='"+tabName+"'";
+		List<Map<String, Object>> tablist = jdbcTemplate.queryForList(isExitSql);
+		if(tablist!=null && tablist.size()>0){
+			String clarSql = "update  "+tabName+" set "+keyname.split("__")[0]+"=null where p_key_id in(SELECT p_key_id FROM m_wbs_tree_contract WHERE id ='"+wbsTreePrivate.getId()+"' and project_id='"+wbsTreePrivate.getProjectId()+"' )";
+			jdbcTemplate.execute(clarSql);
+		}
+
+
+
+
 		return R.success("操作成功");
 	}
 

+ 16 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/feign/ArchiveTreeClientImpl.java

@@ -9,6 +9,7 @@ import org.springblade.manager.service.IArchiveTreeService;
 import org.springblade.manager.vo.ArchiveTreeVO;
 import org.springframework.web.bind.annotation.RestController;
 
+import java.util.ArrayList;
 import java.util.List;
 
 @RestController
@@ -17,6 +18,21 @@ public class ArchiveTreeClientImpl implements ArchiveTreeClient {
 
     private final IArchiveTreeService archiveTreeService;
 
+    @Override
+    public List<ArchiveTree> queryAllChildByAncestors(String id) {
+        List<ArchiveTree> archiveTreeList = this.archiveTreeService.list(Wrappers.<ArchiveTree>lambdaQuery().like(ArchiveTree::getAncestors, id));
+        if(archiveTreeList == null || archiveTreeList.size() <= 0){
+            //有可能已经是最底节点
+            archiveTreeList = new ArrayList<>();
+            ArchiveTree archiveTree = this.archiveTreeService.getById(id);
+            if(archiveTree != null){
+                archiveTreeList.add(archiveTree);
+            }
+        }
+
+        return archiveTreeList;
+    }
+
     @Override
     public List<ArchiveTree> queryTreeNodeByIds(List<String> ids) {
         return this.archiveTreeService.list(Wrappers.<ArchiveTree>lambdaQuery().in(ArchiveTree::getId, ids));

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

@@ -141,8 +141,8 @@ public class WbsTreeContractClientImpl implements WbsTreeContractClient {
     }
 
     @Override
-    public Boolean removeContractTreeNode(String ids) {
-        return this.wbsTreeContractService.update(Wrappers.<WbsTreeContract>lambdaUpdate().set(WbsTreeContract::getIsDeleted, 1).in(WbsTreeContract::getPKeyId, Func.toLongList(ids)));
+    public Boolean removeContractTreeNode(List<String> ids) {
+        return this.wbsTreeContractService.update(Wrappers.<WbsTreeContract>lambdaUpdate().set(WbsTreeContract::getIsDeleted, 1).in(WbsTreeContract::getPKeyId, ids));
     }
 
     @Override

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

@@ -77,4 +77,6 @@ public interface WbsTreeContractMapper extends BaseMapper<WbsTreeContract> {
 
     void updateBatchByIds2(@Param("wbsTreePrivate") WbsTreePrivate wbsTreePrivate,@Param("id")  Long id);
 
+    void updateContractTablesInfo(@Param("contractInfoId") Long contractInfoId,@Param("wbsTreePrivate") WbsTreePrivate wbsTreePrivate);
+
 }

+ 24 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsTreeContractMapper.xml

@@ -448,6 +448,9 @@
             partition_code = #{wbsTree.partitionCode},
             table_type = #{wbsTree.tableType},
             table_owner = #{wbsTree.tableOwner}
+            <if test="wbsTree.sort != null and wbsTree.sort != ''">
+                , sort = #{wbsTree.sort}
+            </if>
         WHERE id = #{wbsTree.id}
           AND contract_id = #{id}
           AND status = 1
@@ -464,12 +467,33 @@
             partition_code = #{wbsTreePrivate.partitionCode},
             table_type = #{wbsTreePrivate.tableType},
             table_owner = #{wbsTreePrivate.tableOwner}
+            <if test="wbsTreePrivate.sort != null and wbsTreePrivate.sort != ''">
+                , sort = #{wbsTreePrivate.sort}
+            </if>
         WHERE id = #{wbsTreePrivate.id}
           AND contract_id = #{id}
           AND status = 1
           AND is_deleted = 0
     </update>
 
+    <update id="updateContractTablesInfo">
+        UPDATE m_wbs_tree_contract
+        SET dept_name = #{wbsTreePrivate.deptName},
+            full_name =#{wbsTreePrivate.deptName},
+            table_type  = #{wbsTreePrivate.tableType},
+            table_owner = #{wbsTreePrivate.tableOwner}
+            <if test="wbsTreePrivate.sort != null and wbsTreePrivate.sort != ''">
+                , sort = #{wbsTreePrivate.sort}
+            </if>
+        WHERE id = #{wbsTreePrivate.id}
+        AND project_id = #{wbsTreePrivate.projectId}
+        AND contract_id = #{contractInfoId}
+        AND old_id is null
+        AND type = 2
+        AND status = 1
+        AND is_deleted = 0
+    </update>
+
     <select id="selectQueryValueLikeNodeName" resultMap="ResultMap">
         select * from m_wbs_tree_contract where is_deleted = 0 and contract_id = #{contractId} and (dept_name like concat('%',#{queryValue},'%') or full_name like concat('%',#{queryValue},'%')) and `type` = '1'
     </select>

+ 6 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsTreePrivateMapper.xml

@@ -209,6 +209,9 @@
             partition_code = #{wbsTree.partitionCode},
             table_type = #{wbsTree.tableType},
             table_owner = #{wbsTree.tableOwner}
+            <if test="wbsTree.sort != null and wbsTree.sort != ''">
+                , sort = #{wbsTree.sort}
+            </if>
         WHERE id = #{wbsTree.id}
         AND project_id = #{projectId}
         AND status = 1
@@ -225,6 +228,9 @@
             partition_code = #{wbsTreePrivate.partitionCode},
             table_type = #{wbsTreePrivate.tableType},
             table_owner = #{wbsTreePrivate.tableOwner}
+            <if test="wbsTreePrivate.sort != null and wbsTreePrivate.sort != ''">
+                , sort = #{wbsTreePrivate.sort}
+            </if>
         WHERE id = #{wbsTreePrivate.id}
           AND project_id = #{projectId}
           AND wbs_id = #{wbsId}

+ 2 - 5
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ArchiveTreeServiceImpl.java

@@ -4,7 +4,6 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.StringPool;
 import com.baomidou.mybatisplus.core.toolkit.StringUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import com.fasterxml.jackson.databind.BeanProperty;
 import lombok.AllArgsConstructor;
 import org.springblade.core.log.exception.ServiceException;
 import org.springblade.core.secure.utils.AuthUtil;
@@ -18,7 +17,6 @@ import org.springblade.manager.vo.ArchiveTreeVO;
 import org.springblade.manager.mapper.ArchiveTreeMapper;
 import org.springblade.manager.service.IArchiveTreeService;
 import org.springblade.core.mp.base.BaseServiceImpl;
-import org.springframework.beans.BeanUtils;
 import org.springframework.stereotype.Service;
 
 import java.util.*;
@@ -178,8 +176,7 @@ public class ArchiveTreeServiceImpl extends BaseServiceImpl<ArchiveTreeMapper, A
             archiveTreeDTO.setIsStorageNode(1);
         }
 
-        //新增默认排序
-        //获取同级节点List
+        //默认排序
         if (archiveTreeDTO.getId() == null) {
             List<ArchiveTree> trees = baseMapper.selectList(Wrappers.<ArchiveTree>query().lambda()
                     .eq(ArchiveTree::getParentId, archiveTreeDTO.getParentId())
@@ -191,7 +188,7 @@ public class ArchiveTreeServiceImpl extends BaseServiceImpl<ArchiveTreeMapper, A
                 }
                 return true;
             }).collect(Collectors.toList());
-            //获取最大sort
+            //最大sort
             Optional<ArchiveTree> max = collect.stream().max(Comparator.comparingInt(ArchiveTree::getSort));
             Integer sort = 0;
             if (max.isPresent()) {

+ 47 - 48
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ExcelTabServiceImpl.java

@@ -16,17 +16,15 @@
  */
 package org.springblade.manager.service.impl;
 
-import cn.hutool.core.date.StopWatch;
-import cn.hutool.log.StaticLog;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.mixsmart.utils.ListUtils;
-import com.mixsmart.utils.StringUtils;
 import lombok.AllArgsConstructor;
 import lombok.Data;
+import org.apache.commons.lang.StringUtils;
 import org.springblade.business.feign.InformationQueryClient;
 import org.springblade.common.utils.SnowFlakeUtil;
 import org.springblade.core.oss.model.BladeFile;
@@ -35,15 +33,12 @@ import org.springblade.core.tool.node.ForestNodeMerger;
 import org.springblade.core.tool.utils.Func;
 import org.springblade.core.tool.utils.StringPool;
 import org.springblade.manager.bean.TableInfo;
-import org.springblade.manager.dto.ElementData;
 import org.springblade.manager.dto.FormData;
 import org.springblade.manager.entity.ExcelTab;
 import org.springblade.manager.entity.Formula;
 import org.springblade.manager.entity.WbsTree;
 import org.springblade.manager.entity.WbsTreeContract;
-import org.springblade.manager.formula.ITableElementConverter;
 import org.springblade.manager.formula.KeyMapper;
-import org.springblade.manager.formula.impl.TableElementConverter;
 import org.springblade.manager.service.IFormulaService;
 import org.springblade.manager.service.IWbsParamService;
 import org.springblade.manager.service.IWbsTreeContractService;
@@ -60,7 +55,6 @@ import org.springframework.stereotype.Service;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 
 import java.util.*;
-import java.util.concurrent.atomic.AtomicInteger;
 import java.util.stream.Collectors;
 
 /**
@@ -77,6 +71,7 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
 	private final InformationQueryClient informationQueryClient;
 	// 元素信息表-
 	private final IWbsTreeContractService wbsTreeContractService;
+	private final IWbsTreeService wbsTreeService;
 	private final IFormulaService formulaService;
 	private final JdbcTemplate jdbcTemplate;
 
@@ -214,20 +209,36 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
 
 	@Override
 	public void formulaFillData(List<TableInfo> tableInfoList) {
-		StopWatch stopWatch = new StopWatch();
-		stopWatch.start("公式处理");
-		String ids =tableInfoList.stream().map(TableInfo::getPkeyId).collect(Collectors.joining(","));
-		List<Map<String,Object>> list=this.jdbcTemplate.queryForList("SELECT   a.p_key_id as nodeId,b.id as fieldId,b.e_key as field,c.init_table_name as tableName  from m_wbs_tree_contract a LEFT JOIN m_wbs_form_element b on a.id=b.f_id left JOIN m_wbs_tree c on a.id=c.id where a.p_key_id in ("+ids+")");
-		List<KeyMapper> keyMappers = JSON.parseArray(JSONArray.toJSONString(list), KeyMapper.class);
-		List<Formula> formulas =this.formulaService.list(Wrappers.<Formula>lambdaQuery().in(Formula::getElementId,keyMappers.stream().map(KeyMapper::getFieldId).distinct().collect(Collectors.toList())));
-		TableElementConverter tec= new TableElementConverter(tableInfoList,keyMappers,formulas);
-		if(tec.isPresent()){
-			tec.before();
-			this.formulaService.execute(tec);
-			tec.after();
+		List<FormData> fds = new ArrayList<>();
+		List<WbsTreeContract>  wbsTreeContractList = wbsTreeContractService.list(Wrappers.<WbsTreeContract>lambdaQuery().in(WbsTreeContract::getPKeyId,tableInfoList.stream().map(TableInfo::getPkeyId).collect(Collectors.toList())));
+		if(Func.isNotEmpty(wbsTreeContractList)){
+			List<WbsTree> wbsTrees = this.wbsTreeService.list(Wrappers.<WbsTree>lambdaQuery().in(WbsTree::getId,wbsTreeContractList.stream().map(WbsTreeContract::getId).distinct().collect(Collectors.toList())));
+			Map<Long,List<WbsTree>>  treeMap = wbsTrees.stream().collect(Collectors.groupingBy(WbsTree::getId));
+			LinkedHashMap<Long,Long> map = new LinkedHashMap<>(wbsTreeContractList.size()*2);
+			String ids =tableInfoList.stream().map(TableInfo::getPkeyId).collect(Collectors.joining(","));
+			List<Map<String,Object>> list=this.jdbcTemplate.queryForList("SELECT   a.p_key_id as nodeId,b.id as fieldId,b.e_key as field,c.init_table_name as tableName  from m_wbs_tree_contract a LEFT JOIN m_wbs_form_element b on a.id=b.f_id left JOIN m_wbs_tree c on a.id=c.id where a.p_key_id in ("+ids+")");
+			List<KeyMapper> keyMappers = JSON.parseArray(JSONArray.toJSONString(list), KeyMapper.class);
+			if(Func.isNotEmpty(keyMappers)){
+				/*当前节点所有已经配置的公式*/
+				List<Formula> formulas =this.formulaService.list(Wrappers.<Formula>lambdaQuery().in(Formula::getElementId,keyMappers.stream().map(KeyMapper::getFieldId).distinct().collect(Collectors.toList())));
+				Map<Long,Formula> formulaMap = new HashMap<>();
+				if(Func.isNotEmpty(formulas)){
+					formulas.forEach(e->{
+						formulaMap.put(e.getElementId(),e);
+					});
+				}
+				LinkedHashMap<String,List<KeyMapper>> dataMap =keyMappers.stream().collect(Collectors.groupingBy(e->e.getTableName()+e.getField(), LinkedHashMap<String,List<KeyMapper>>::new,Collectors.toList()));
+				for(Map.Entry<String,List<KeyMapper>> entry:dataMap.entrySet()){
+					String code=	entry.getKey();
+					List<KeyMapper> keyMapperList =entry.getValue();
+					KeyMapper km = keyMapperList.get(0);
+					fds.add(new FormData(code,new ArrayList<>(),formulaMap.get(km.getFieldId())));
+				}
+			}
+			System.out.println();
 		}
-		stopWatch.stop();
-		StaticLog.info("{}",stopWatch);
+		//stopWatch.stop();
+		//StaticLog.info("{}",stopWatch);
 	}
 
 
@@ -246,43 +257,30 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
 				String tabName = wbsTreeContract.getInitTableName();
 
 				// 判读修改还是 添加
-			//	String querySql = "select * from "+tabName+" where p_key_id="+tableInfo.getPkeyId() ;
-			//	List<Map<String, Object>> dataIn = jdbcTemplate.queryForList(querySql);
 				String delSql = "delete from "+tabName+" where p_key_id="+tableInfo.getPkeyId();
 				jdbcTemplate.execute(delSql);
 
 				String sqlInfo="";
-                 LinkedHashMap<String,String> dataMap2 = tableInfo.getDataMap();
-			//	if(dataIn.isEmpty()){ //插入
-					sqlInfo = "INSERT INTO "+tabName+" ( ";
-					String keyStr = "id,";
-					String valStr = SnowFlakeUtil.getId() + ",";
-					for (String keys : dataMap2.keySet()){
-						keyStr += keys+",";
-						valStr += "'"+dataMap2.get(keys)+"',";
-					}
-					keyStr=keyStr.substring(0,keyStr.lastIndexOf(","));
-					valStr=valStr.substring(0,valStr.lastIndexOf(","));
-					sqlInfo = sqlInfo + keyStr+") VALUES (" +valStr +")";
-
+				LinkedHashMap<String,String> dataMap2 = tableInfo.getDataMap();
+				sqlInfo = "INSERT INTO "+tabName+" ( ";
+				String keyStr = "id,";
+				String valStr = SnowFlakeUtil.getId() + ",";
+				for (String keys : dataMap2.keySet()){
+					keyStr += keys+",";
+					valStr += "'"+dataMap2.get(keys)+"',";
+				}
+				keyStr=keyStr.substring(0,keyStr.lastIndexOf(","));
+				valStr=valStr.substring(0,valStr.lastIndexOf(","));
+				sqlInfo = sqlInfo + keyStr+") VALUES (" +valStr +")";
 
-					WbsTreeContract wbsTreeContractByP = wbsTreeContractService.getBaseMapper().selectOne(Wrappers.<WbsTreeContract>query().lambda()
+				WbsTreeContract wbsTreeContractByP = wbsTreeContractService.getBaseMapper().selectOne(Wrappers.<WbsTreeContract>query().lambda()
 							.eq(WbsTreeContract::getId, wbsTreeContract.getParentId()).eq(WbsTreeContract::getContractId,tableInfo.getContractId()));
-
 					//处理文件提名
-					String fileName = this.wbsParamService.createFileTitle(wbsTreeContractByP.getPKeyId(), Long.parseLong(wbsTreeContractByP.getContractId()));
+				String fileName = this.wbsParamService.createFileTitle(wbsTreeContractByP.getPKeyId(), Long.parseLong(wbsTreeContractByP.getContractId()));
 					fileName = StringUtils.isNotEmpty(fileName) ? fileName : "缺少文件提名配置";
 
 					//huangjn 保存成功后调用生成资料查询列表数据
-					this.informationQueryClient.saveOrUpdateInformationQueryData(wbsTreeContractByP.getPKeyId()+"", fileName, Integer.parseInt(tableInfo.getClassify()), 2);
-				/*}else{ //更新
-					sqlInfo = "update  "+tabName+" set ";
-					for (String keys : dataMap2.keySet()){
-						sqlInfo += keys+"='"+dataMap2.get(keys)+"',";
-					}
-					sqlInfo=sqlInfo.substring(0,sqlInfo.lastIndexOf(","));
-					sqlInfo = sqlInfo + " where p_key_id="+tableInfo.getPkeyId();
-				}*/
+				this.informationQueryClient.saveOrUpdateInformationQueryData(wbsTreeContractByP.getPKeyId()+"", fileName, Integer.parseInt(tableInfo.getClassify()), 2);
 
 				UpdateWrapper<WbsTreeContract> updateWrapper = new UpdateWrapper<>();
 				updateWrapper.in("p_key_id",tableInfo.getPkeyId());
@@ -290,7 +288,8 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
 				wbsTreeContractService.update(updateWrapper);
 
 				jdbcTemplate.execute(sqlInfo);
-				// this.getBussPdfInfo(Long.parseLong(pkeyId));
+				// pdf 预览添加
+			   //this.getBussPdfInfo(Long.parseLong(tableInfo.getPkeyId()));
 			}
 		}
 	}

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

@@ -80,7 +80,7 @@ public class WbsFormElementServiceImpl extends BaseServiceImpl<WbsFormElementMap
     @Override
     public Boolean initTable(List<WbsFormElement> elementList, String tableName) {
         String sql = createSQL(elementList);
-        //建表
+
         return wbsFormElementMapper.createTable(sql, tableName) >= 0;
     }
 
@@ -314,9 +314,9 @@ public class WbsFormElementServiceImpl extends BaseServiceImpl<WbsFormElementMap
                 }*/
 
                 //设置默认长度
-                if (eLength < 255 && eLength > 65) {
+                if (eLength <= 255 && eLength > 65) {
                     eLength = 255;
-                } else if (eLength == 1000) {
+                } else if (eLength <= 1000 && eLength > 500) {
                     eLength = 500;
                 } else if (eLength >= 0 && eLength <= 65) {
                     eLength = 20;

+ 20 - 22
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreeContractServiceImpl.java

@@ -74,7 +74,7 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
         List<String> collect7 = new ArrayList<>();
 
         if (list.size() > 0) {
-            //节点下所有表单Id
+            //所有表单
             List<WbsTreeContract> collect2 = list.stream().filter(f -> f.getType() == 2).collect(Collectors.toList());
             List<Long> collect4 = collect2.stream().map(WbsTreeContract::getId).collect(Collectors.toList());
             collect3 = collect4.stream().map(String::valueOf).collect(Collectors.toList());
@@ -85,11 +85,11 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
             collect7 = collect6.stream().map(String::valueOf).collect(Collectors.toList());
 
         }
-        //idList1-入参ids、collect7-当前项目所有节点ids
-        //需要新增节点ids
+
+        //新增节点ids
         List<String> collect8 = collect7;
         List<String> saveIds = idList1.stream().filter(f -> !collect8.contains(f)).collect(Collectors.toList());
-        //需要删除节点ids
+        //删除节点ids
         List<String> delIds = collect8.stream().filter(f -> !idList1.contains(f)).collect(Collectors.toList());
 
         if (saveIds.size() == 0 && delIds.size() == 0) {
@@ -102,7 +102,7 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                     .eq(WbsTreePrivate::getType, 2)
             );
 
-            //获取当前引用节点下的所有表
+            //获取当前引用节点下的所有表
             wbsTreePrivateList.forEach(wbsTreePrivate -> {
                 idList1.forEach(id -> {
                     if (Long.parseLong(id) == (wbsTreePrivate.getParentId()) && wbsTreePrivate.getType() == 2) {
@@ -112,7 +112,7 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                 });
             });
 
-            //私有wbs树下所有元素表的Id collect2
+            //私有wbs树下所有元素表的Id
             List<Long> collect = wbsTreePrivateList2.stream().map(WbsTreePrivate::getId).collect(Collectors.toList());
             List<String> collect2 = collect.stream().map(String::valueOf).collect(Collectors.toList());
             //获取所有wbsTreePrivate新增的表单Id
@@ -134,13 +134,11 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                 });
                 this.saveBatch(wbsTreeContracts, 10000);
             }
-
         } else {
-            //节点id改变,进行新增或删除节点以及该节点下的元素表
 
             //删除
             if (delIds.size() > 0) {
-                //判断是否被监理合同引用
+                //是否被监理合同引用
                 List<ContractRelationJlyz> contractRelationJLYZList = baseMapper.selectContractRelationInfoByidSG2(pawDTO.getContractId());
                 if (contractRelationJLYZList.size() > 0) {
                     throw new ServiceException("当前施工合同段wbs树被监理或业主合同段引用中,删除失败!");
@@ -148,7 +146,7 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
 
                 List<Long> ids1 = delIds.stream().map(Long::parseLong).collect(Collectors.toList());
 
-                //获取当前节点、表的信息
+                //获取当前节点、表
                 List<WbsTreeContract> wbsTreeContractList = baseMapper.selectTableListInfo(ids1, pawDTO.getWbsId(), pawDTO.getProjectId(), pawDTO.getContractId());
 
                 List<WbsTreeContract> tableNames = new ArrayList<>();
@@ -166,8 +164,8 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                     String names = StringUtils.join(nodeNames, " , ");
                     throw new ServiceException(StringUtil.format("节点下的 {} 中存在填报数据,删除失败!", names));
                 }
-                //删除
                 baseMapper.deleteBatch(ids1, pawDTO.getWbsId(), pawDTO.getProjectId(), pawDTO.getContractId());
+
             }
 
             //新增
@@ -176,7 +174,7 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                 List<WbsTreePrivate> wbsTreePrivatesList = new ArrayList<>();
                 ArrayList<ConstructionLedger> constructionLedgerList = new ArrayList<>();
 
-                //获取wbs私有树下节点、表 saveIds=新增的节点id
+                //获取wbs私有树下节点、表
                 List<WbsTreePrivate> wbsTreePrivates = wbsTreePrivateMapper.selectNodeAndTable2(pawDTO.getWbsId(), pawDTO.getProjectId());
 
                 for (WbsTreePrivate wbsTreePrivate : wbsTreePrivates) {
@@ -193,11 +191,11 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
 
                 //初始化
                 wbsTreePrivatesList.forEach(wbsTreePrivate -> {
-                    //节点、表信息
+                    //节点、表
                     WbsTreeContract wbsTreeContract = getWbsTreeContract(wbsTreePrivate, pawDTO);
                     wbsTreeContractList.add(wbsTreeContract);
 
-                    //台账信息
+                    //台账
                     if (wbsTreeContract.getDeptCategory() == 6) {
                         ConstructionLedger constructionLedger = new ConstructionLedger();
                         constructionLedger.setIsBeton(0);
@@ -209,7 +207,7 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                     }
                 });
 
-                //新增合同段wbs树、元素
+                //新增合同段节点、
                 this.saveBatch(wbsTreeContractList, 10000);
 
                 //新增施工台账
@@ -321,7 +319,7 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
 
 
     public List<WbsTreeContractTreeVO3> lazyTreeThree(String contractIdRelation, Long parentId, String contractId) {
-        //根据当前监理、业主合同段id,获取关联权限信息
+        //获取关联信息
         List<ContractRelationJlyz> listContractRelationInfo = baseMapper.selectContractRelationInfo(Long.valueOf(contractId));
 
         //获取关联施工合同段Id
@@ -349,16 +347,17 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
 
     @Override
     public List<WbsTreeContract> searchNodeAllTable(String primaryKeyId, String tableOwner, String contractId, String projectId) {
-        //获取当前节点
         WbsTreeContract wbsTreeContract = baseMapper.selectOne(Wrappers.<WbsTreeContract>query().lambda()
                 .eq(WbsTreeContract::getPKeyId, primaryKeyId));
         if (wbsTreeContract == null) {
             return Collections.emptyList();
         }
 
-        //获取当前项目合同段的角色roleId-默认查询施工合同段
         //当前项目合同段只会存在一个角色roleId
         SaveUserInfoByProject userInfo = baseMapper.selectRoleInfo(AuthUtil.getUserId(), contractId, projectId);
+        if (userInfo == null){
+            throw new ServiceException("请先分配当前用户对该合同段的角色信息");
+        }
         String roleId = userInfo.getRoleId();
 
         //获取当前用户角色与表单所属方关系信息
@@ -367,21 +366,20 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
             throw new ServiceException("当前用户角色未授权,请先分配角色查看元素表相对应的权限");
         }
 
-        //获取tableOwnerNumber
         List<String> tableOwnerNumbers = wbsTableOwnerRoleList.stream().map(WbsTableOwnerRole::getTableOwnerNumber).collect(Collectors.toList());
 
         List<String> tableOwnerList = null;
         if (StringUtils.isNotEmpty(tableOwner)) {
             String tableOwners = "";
-            if (tableOwner.equals("1")) { //此处加载字典owner_type 固定写死 施工质检1= 1 2 3
+            //此处加载字典owner_type 固定写死 施工质检1= 1 2 3 , 监理抽检2= 4 5 6
+            if (tableOwner.equals("1")) {
                 tableOwners = "1,2,3";
-            } else if (tableOwner.equals("2")) { //监理抽检2= 4 5 6
+            } else if (tableOwner.equals("2")) {
                 tableOwners = "4,5,6";
             }
             tableOwnerList = Func.toStrList(tableOwners);
         }
 
-        //根据tableOwnerList、tableOwnerNumber 获取当前节点下表单
         return baseMapper.selectWbsTreeContractList(tableOwnerNumbers, wbsTreeContract.getProjectId(), wbsTreeContract.getWbsId(),
                 wbsTreeContract.getContractId(), wbsTreeContract.getId(), wbsTreeContract.getContractIdRelation(), tableOwnerList);
 

+ 44 - 13
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreePrivateServiceImpl.java

@@ -2,6 +2,7 @@ package org.springblade.manager.service.impl;
 
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import lombok.AllArgsConstructor;
 import org.springblade.common.utils.SnowFlakeUtil;
@@ -14,10 +15,7 @@ import org.springblade.manager.dto.WbsTreePrivateDTO2;
 import org.springblade.manager.dto.WbsTreePrivateDTO3;
 import org.springblade.manager.entity.*;
 
-import org.springblade.manager.mapper.ContractInfoMapper;
-import org.springblade.manager.mapper.WbsInfoMapper;
-import org.springblade.manager.mapper.WbsTreeContractMapper;
-import org.springblade.manager.mapper.WbsTreePrivateMapper;
+import org.springblade.manager.mapper.*;
 import org.springblade.manager.service.IWbsTreePrivateService;
 import org.springblade.manager.vo.WbsNodeTableVO;
 import org.springblade.manager.vo.WbsTreePrivateVO;
@@ -40,7 +38,6 @@ public class WbsTreePrivateServiceImpl extends BaseServiceImpl<WbsTreePrivateMap
 
     @Override
     public List<WbsTreePrivateVO> tree(String wbsId, String projectId) {
-        //获取wbsType
         WbsInfo wbsInfo = wbsInfoMapper.selectOne(Wrappers.<WbsInfo>query().lambda().eq(WbsInfo::getId, wbsId));
         if (wbsInfo != null) {
             return ForestNodeMerger.merge(baseMapper.tree(wbsId, projectId, wbsInfo.getWbsType()));
@@ -68,7 +65,7 @@ public class WbsTreePrivateServiceImpl extends BaseServiceImpl<WbsTreePrivateMap
             wbsTreePrivate.setStatus(1);
             Long pKeyId = SnowFlakeUtil.getId();
             wbsTreePrivate.setPKeyId(pKeyId);
-            //获取wbsType
+
             WbsInfo wbsInfo = wbsInfoMapper.selectById(wbsTreePrivate.getWbsId());
             wbsTreePrivate.setWbsType(String.valueOf(wbsInfo.getWbsType())); //质检=1 试验=2 计量=3 日志=4
 
@@ -78,7 +75,7 @@ public class WbsTreePrivateServiceImpl extends BaseServiceImpl<WbsTreePrivateMap
                 wbsTreePrivate.setAncestors(ancestors);
             }
 
-            //初始化排序sort
+            //初始化sort
             List<WbsTreePrivate> trees = baseMapper.selectList(Wrappers.<WbsTreePrivate>query().lambda()
                     .eq(WbsTreePrivate::getProjectId, wbsTreePrivate.getProjectId())
                     .eq(WbsTreePrivate::getParentId, wbsTreePrivate.getParentId())
@@ -92,7 +89,7 @@ public class WbsTreePrivateServiceImpl extends BaseServiceImpl<WbsTreePrivateMap
                 }
                 return true;
             }).collect(Collectors.toList());
-            //获取最大sort
+            //最大sort
             Optional<WbsTreePrivate> max = collect.stream().max(Comparator.comparingInt(WbsTreePrivate::getSort));
             Integer sort = 0;
             if (max.isPresent()) {
@@ -155,8 +152,6 @@ public class WbsTreePrivateServiceImpl extends BaseServiceImpl<WbsTreePrivateMap
             wbsTree.setSort(number);
             baseMapper.updateSortById(wbsTree.getPKeyId(), wbsTree.getSort());
 
-            //同步合同段节点排序
-            //获取projectId、id、wbsId
             WbsTreePrivate objPrivate = baseMapper.selectOne(Wrappers.<WbsTreePrivate>query().lambda().eq(WbsTreePrivate::getPKeyId, wbsTree.getPKeyId()));
             if (objPrivate != null) {
                 String projectId = objPrivate.getProjectId();
@@ -172,7 +167,6 @@ public class WbsTreePrivateServiceImpl extends BaseServiceImpl<WbsTreePrivateMap
             }
             number++;
         }
-
         return true;
     }
 
@@ -180,11 +174,9 @@ public class WbsTreePrivateServiceImpl extends BaseServiceImpl<WbsTreePrivateMap
     public boolean wbsTreePrivateTableSort(List<WbsTreePrivateDTO2> wbsTreeDTO) {
         int number = 1;
         for (WbsTreePrivateDTO2 wbsTreePrivate : wbsTreeDTO) {
-            //私有wbs树排序
             wbsTreePrivate.setSort(number);
             baseMapper.updateSortById2(wbsTreePrivate.getPKeyId(), wbsTreePrivate.getSort());
 
-            //获取projectId、id、wbsId
             WbsTreePrivate objPrivate = baseMapper.selectOne(Wrappers.<WbsTreePrivate>query().lambda().eq(WbsTreePrivate::getPKeyId, wbsTreePrivate.getPKeyId()));
             if (objPrivate != null) {
                 String projectId = objPrivate.getProjectId();
@@ -218,9 +210,48 @@ public class WbsTreePrivateServiceImpl extends BaseServiceImpl<WbsTreePrivateMap
     @Transactional(rollbackFor = Exception.class)
     public boolean updateBatchByPid(List<WbsTreePrivateDTO3> wbsTreePrivates) {
         try {
+            //修改当前私有项目元素表基础信息
             wbsTreePrivates.forEach(list -> {
                 baseMapper.updateBatchByPid(list);
             });
+
+            //修改当前项目下所有合同段中的元素表基础信息
+            String projectId = "";
+            String parentId = "";
+            List<WbsTreePrivate> wbsTreePrivateList = new ArrayList<>();
+            int number = 0;
+            for (WbsTreePrivateDTO3 wbsTreePrivate : wbsTreePrivates) {
+                WbsTreePrivate wbsTreePrivate1 = baseMapper.selectOne(Wrappers.<WbsTreePrivate>query().lambda().eq(WbsTreePrivate::getPKeyId, wbsTreePrivate.getPKeyId()));
+                wbsTreePrivateList.add(wbsTreePrivate1);
+                if (number == 0) {
+                    projectId = wbsTreePrivate1.getProjectId();
+                    parentId = String.valueOf(wbsTreePrivate1.getParentId());
+                    number = 1;
+                }
+            }
+            if (StringUtils.isNotEmpty(projectId) && StringUtils.isNotEmpty(parentId) && wbsTreePrivateList.size() > 0) {
+                //获取所有合同段ids
+                List<ContractInfo> contractInfos = contractInfoMapper.selectList(Wrappers.<ContractInfo>query().lambda().eq(ContractInfo::getPId, projectId));
+                if (contractInfos.size() > 0) {
+                    List<Long> contractInfoIds = contractInfos.stream().map(ContractInfo::getId).collect(Collectors.toList());
+                    for (Long contractInfoId : contractInfoIds) {
+                        for (WbsTreePrivate wbsTreePrivate : wbsTreePrivateList) {
+                            //判断当前合同段是否存在该元素表
+                            WbsTreeContract wbsTreeContract = wbsTreeContractMapper.selectOne(Wrappers.<WbsTreeContract>query().lambda()
+                                    .eq(WbsTreeContract::getContractId, contractInfoId)
+                                    .eq(WbsTreeContract::getProjectId, wbsTreePrivate.getProjectId())
+                                    .eq(WbsTreeContract::getId, wbsTreePrivate.getId())
+                                    .eq(WbsTreeContract::getStatus, 1)
+                                    .isNull(WbsTreeContract::getOldId) //不是客户端的复制或新增的节点
+                            );
+                            if (wbsTreeContract != null) {
+                                wbsTreeContractMapper.updateContractTablesInfo(contractInfoId, wbsTreePrivate);
+                            }
+                        }
+                    }
+                }
+            }
+
         } catch (Exception e) {
             throw new ServiceException("操作失败");
         }

+ 31 - 33
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreeServiceImpl.java

@@ -2,7 +2,6 @@ package org.springblade.manager.service.impl;
 
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import lombok.AllArgsConstructor;
-import lombok.SneakyThrows;
 import net.sourceforge.pinyin4j.PinyinHelper;
 import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
 import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
@@ -10,17 +9,17 @@ import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
 import net.sourceforge.pinyin4j.format.HanyuPinyinVCharType;
 import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;
 import org.apache.commons.lang.StringUtils;
-import org.jsoup.helper.DataUtil;
 import org.springblade.common.utils.SnowFlakeUtil;
 import org.springblade.core.log.exception.ServiceException;
+import org.springblade.core.redis.cache.BladeRedis;
 import org.springblade.core.secure.utils.AuthUtil;
-import org.springblade.core.tool.api.R;
 import org.springblade.core.tool.constant.BladeConstant;
 import org.springblade.core.tool.node.ForestNodeMerger;
 import org.springblade.core.tool.utils.DateUtil;
 import org.springblade.core.tool.utils.Func;
 import org.springblade.core.tool.utils.StringPool;
 import org.springblade.core.tool.utils.StringUtil;
+import org.springblade.manager.aop.AvoidRepeatableCommit;
 import org.springblade.manager.dto.FormElementDTO;
 import org.springblade.manager.dto.WbsTreeBatchImportDTO;
 import org.springblade.manager.dto.WbsTreeContractDTO;
@@ -32,6 +31,7 @@ import org.springblade.manager.mapper.*;
 import org.springblade.manager.service.IWbsFormElementService;
 import org.springblade.manager.service.IWbsTreeService;
 import org.springblade.core.mp.base.BaseServiceImpl;
+import org.springblade.manager.unit.RedisUtil;
 import org.springblade.manager.vo.*;
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
@@ -57,6 +57,7 @@ public class WbsTreeServiceImpl extends BaseServiceImpl<WbsTreeMapper, WbsTree>
     private final WbsTreeContractMapper wbsTreeContractMapper;
     private final ContractInfoMapper contractInfoMapper;
     private final FormulaMapper formulaMapper;
+    private final BladeRedis bladeRedis;
 
     @Override
     public IPage<WbsTreeVO> selectWbsTreePage(IPage<WbsTreeVO> page, WbsTreeVO wbsTree) {
@@ -89,9 +90,7 @@ public class WbsTreeServiceImpl extends BaseServiceImpl<WbsTreeMapper, WbsTree>
     }
 
     private List<WbsTreeVO2> buildWbsTreeByStream(List<WbsTreeVO2> wbsTreeVO2s) {
-        //根节点
         List<WbsTreeVO2> list = wbsTreeVO2s.stream().filter(f -> f.getParentId() == 0L).collect(Collectors.toList());
-        //子节点分组
         Map<Long, List<WbsTreeVO2>> map = wbsTreeVO2s.stream().collect(Collectors.groupingBy(WbsTreeVO2::getParentId));
         this.recursionFnTree(list, map);
         return list;
@@ -102,9 +101,7 @@ public class WbsTreeServiceImpl extends BaseServiceImpl<WbsTreeMapper, WbsTree>
             List<WbsTreeVO2> childrenList = map.get(wbsTreeVO2.getId());
             wbsTreeVO2.setChildren(childrenList);
             if (childrenList != null && childrenList.size() > 0) {
-                //存在子级
                 wbsTreeVO2.setHasChildren(true);
-                //递归查询
                 recursionFnTree(childrenList, map);
             }
         }
@@ -132,8 +129,7 @@ public class WbsTreeServiceImpl extends BaseServiceImpl<WbsTreeMapper, WbsTree>
         wbsTree.setStatus(1);
         wbsTree.setIsDeleted(BladeConstant.DB_NOT_DELETED);
 
-        //默认排序
-        //获取当前同级节点List
+        //当前同级节点
         if (wbsTree.getId() == null) {
             List<WbsTree> trees = baseMapper.selectList(Wrappers.<WbsTree>query().lambda()
                     .eq(WbsTree::getParentId, wbsTree.getParentId())
@@ -145,7 +141,7 @@ public class WbsTreeServiceImpl extends BaseServiceImpl<WbsTreeMapper, WbsTree>
                 }
                 return true;
             }).collect(Collectors.toList());
-            //获取最大sort
+            //最大sort
             Optional<WbsTree> max = collect.stream().max(Comparator.comparingInt(WbsTree::getSort));
             Integer sort = 0;
             if (max.isPresent()) {
@@ -402,10 +398,7 @@ public class WbsTreeServiceImpl extends BaseServiceImpl<WbsTreeMapper, WbsTree>
     @Override
     public boolean removeTableById(String id) {
         Integer integer = wbsTreeMapper.removeTableById(id);
-        if (integer > 0) {
-            return true;
-        }
-        return false;
+        return integer > 0;
     }
 
     @Override
@@ -418,6 +411,7 @@ public class WbsTreeServiceImpl extends BaseServiceImpl<WbsTreeMapper, WbsTree>
             if (escapeChar != null) {
                 elements.setEAllowDeviation(escapeChar);
             }
+
             //是否保存过公式
             List<Formula> formulas = formulaMapper.selectList(Wrappers.<Formula>query().lambda()
                     .eq(Formula::getElementId, elements.getId())
@@ -510,7 +504,7 @@ public class WbsTreeServiceImpl extends BaseServiceImpl<WbsTreeMapper, WbsTree>
                         wbsTreeZi.setSort(sortNumber);
                         sortNumber++;
 
-                        //结果集
+                        //返回结果集
                         allNodeData.add(wbsTreeZi);
 
                     } else {
@@ -535,7 +529,8 @@ public class WbsTreeServiceImpl extends BaseServiceImpl<WbsTreeMapper, WbsTree>
                     && tree.getWbsId().equals(wbsTreeZi.getWbsId())
                     && tree.getDeptCategory().equals(wbsTreeZi.getDeptCategory())
                     && tree.getProjectNodeId().equals(wbsTreeZi.getProjectNodeId())) {
-                //判断上级节点不同,当前节点名相同的tree选择问题,例如:第X跨的上级有上部构造现场浇筑、上部构造预制和安装,导致下方新增重复节点判断时找到的是前一个
+                //判断上级节点不同,当前节点名相同的tree选择问题
+                //例如:第X跨的上级有上部构造现场浇筑、上部构造预制和安装,导致下方新增重复节点判断时找到的是前一个
                 if (!tree.getAncestors().equals(wbsTreeZi.getAncestors())) {
                     wbsTrees.add(tree);
                     break;
@@ -597,7 +592,6 @@ public class WbsTreeServiceImpl extends BaseServiceImpl<WbsTreeMapper, WbsTree>
     @Override
     public List<Map> findProjectAndContractList(Long userId) {
         List<SaveUserInfoByProjectVO2> list = baseMapper.selectListByUserId(userId);
-        //用户项目合同段角色返回Map
         Map<String, List<SaveUserInfoByProjectVO2>> collect = list.stream().collect(Collectors.groupingBy(SaveUserInfoByProjectVO2::getProjectName));
         return collect.entrySet().stream().map(entity -> {
             Map<String, Object> resultMap = new HashMap<>();
@@ -619,7 +613,7 @@ public class WbsTreeServiceImpl extends BaseServiceImpl<WbsTreeMapper, WbsTree>
             wbsTree.setSort(number);
             baseMapper.updateSortById(wbsTree.getId(), wbsTree.getSort());
 
-            //同步项目私有节点排序
+            //私有节点
             wbsTreePrivateMapper.updateSortById3(wbsTree.getId(), wbsTree.getSort());
             number++;
         }
@@ -646,6 +640,7 @@ public class WbsTreeServiceImpl extends BaseServiceImpl<WbsTreeMapper, WbsTree>
 
     @Override
     @Transactional(rollbackFor = Exception.class)
+    //@AvoidRepeatableCommit //aop
     public Boolean submitWbsTreeInProject1(WbsTreeContractDTO pawDTO) {
         if (StringUtils.isEmpty(pawDTO.getWbsId())) {
             throw new ServiceException("请正确选择一个wbs模板");
@@ -653,7 +648,6 @@ public class WbsTreeServiceImpl extends BaseServiceImpl<WbsTreeMapper, WbsTree>
         String wbsTreeIds = pawDTO.getWbsTreeIds();
         String[] ids = wbsTreeIds.split(",");
         List<String> idList = Arrays.asList(ids);
-        //入参ids
         List<String> idList1 = idList.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
 
         //当前项目存在的引用ids
@@ -683,9 +677,9 @@ public class WbsTreeServiceImpl extends BaseServiceImpl<WbsTreeMapper, WbsTree>
             });
         }
 
-        //需要新增节点ids
+        //新增节点ids
         List<String> saveIds = idList1.stream().filter(f -> !idList2.contains(f)).collect(Collectors.toList());
-        //需要删除节点ids
+        //删除节点ids
         List<String> delIds = idList2.stream().filter(f -> !idList1.contains(f)).collect(Collectors.toList());
 
         if (saveIds.size() == 0 && delIds.size() == 0) {
@@ -991,6 +985,14 @@ public class WbsTreeServiceImpl extends BaseServiceImpl<WbsTreeMapper, WbsTree>
 
             //2.新增
             if (saveIds.size() > 0) {
+                if (saveIds.size() >=  1000){ //新增1000个以上节点时,防止响应过慢重复提交
+                    //获取Redis的Value
+                    String redisValue = bladeRedis.get("submit-wbs-project:" + pawDTO.getProjectId());
+                    if (StringUtils.isNotEmpty(redisValue) && redisValue.equals("1")) {
+                        throw new ServiceException("请勿重复提交,请60秒后再次尝试!");
+                    }
+                }
+
                 //数据初始化节点-引用公有
                 List<WbsTreePrivate> insertData = new ArrayList<>();
                 //数据初始化节点-引用私有
@@ -1056,8 +1058,11 @@ public class WbsTreeServiceImpl extends BaseServiceImpl<WbsTreeMapper, WbsTree>
                     projectInfoMapper.updateTemplateIdById(pawDTO.getProjectId(), pawDTO.getPrimaryKeyId(), "private");
                 }
 
+                //设置Redis的Key、value
+                bladeRedis.set("submit-wbs-project:" + pawDTO.getProjectId(), "1");
+                //设置过期时间
+                bladeRedis.expire("submit-wbs-project:" + pawDTO.getProjectId(), 60);
             }
-
         }
         return true;
     }
@@ -1087,7 +1092,6 @@ public class WbsTreeServiceImpl extends BaseServiceImpl<WbsTreeMapper, WbsTree>
 
     private WbsTreePrivate getWbsTreePrivate1(WbsTree wbsTree, WbsTreeContractDTO pawDTO) {
         WbsTreePrivate wbsTreePrivate = new WbsTreePrivate();
-        //数据初始化
         Long snowId = SnowFlakeUtil.getId();
         wbsTreePrivate.setPKeyId(snowId);
         wbsTreePrivate.setId(wbsTree.getId());
@@ -1127,7 +1131,6 @@ public class WbsTreeServiceImpl extends BaseServiceImpl<WbsTreeMapper, WbsTree>
 
     private WbsTreePrivate getWbsTreePrivate2(WbsTreePrivate wbsTree, WbsTreeContractDTO pawDTO) {
         WbsTreePrivate wbsTreePrivate = new WbsTreePrivate();
-        //数据初始化
         Long snowId = SnowFlakeUtil.getId();
         wbsTreePrivate.setPKeyId(snowId);
         wbsTreePrivate.setId(wbsTree.getId());
@@ -1170,7 +1173,6 @@ public class WbsTreeServiceImpl extends BaseServiceImpl<WbsTreeMapper, WbsTree>
 
     private WbsTreeContract getWbsTreeContract(WbsTreePrivate wbsTree, WbsTreeContractDTO pawDTO) {
         WbsTreeContract wbsTreeContract = new WbsTreeContract();
-        //数据初始化-施工合同
         Long snowId = SnowFlakeUtil.getId();
         wbsTreeContract.setPKeyId(snowId);
         wbsTreeContract.setId(wbsTree.getId());
@@ -1217,11 +1219,10 @@ public class WbsTreeServiceImpl extends BaseServiceImpl<WbsTreeMapper, WbsTree>
     @Override
     public WbsTreeAllListVO findWbsTreeList(Integer type) {
         WbsTreeAllListVO wbsTreeAllListVO = new WbsTreeAllListVO();
-        //公有树
+
         List<WbsInfo> wbsInfos = wbsInfoMapper.selectAll(type);
         wbsTreeAllListVO.setWbsInfos(wbsInfos);
 
-        //私有树
         List<WbsTreePrivate> wbsTreePrivates = wbsTreePrivateMapper.selectAll(type);
         wbsTreeAllListVO.setWbsTreePrivates(wbsTreePrivates);
 
@@ -1252,17 +1253,16 @@ public class WbsTreeServiceImpl extends BaseServiceImpl<WbsTreeMapper, WbsTree>
             throw new ServiceException("表名长度错误,输入范围1-100个字符长度");
         }
 
-        //初始化表名
         //String realName = getFirstSpell(deptName);
         Long id = SnowFlakeUtil.getId();
         String newTableName = "m_" + DateUtil.time() + "_" + id;
         formElementDTO.setInitTableName(newTableName);
 
-        //创建元素
+        //新增
         boolean b1 = submit2(formElementDTO);
+
         List<WbsFormElement> elementList = formElementDTO.getElementList();
         int i = 1;
-
         for (WbsFormElement wbsFormElement : elementList) {
             if ((wbsFormElement.getEType() == 1 || wbsFormElement.getEType() == 6 || wbsFormElement.getEType() == 7)
                     && (wbsFormElement.getELength() > 1000 || wbsFormElement.getELength() < 10)) {
@@ -1276,7 +1276,6 @@ public class WbsTreeServiceImpl extends BaseServiceImpl<WbsTreeMapper, WbsTree>
                 throw new ServiceException("请输入正确的长度,该类型范围为10-65");
             }
 
-            //当前元素表中元素对应实体表唯一key值、fId
             wbsFormElement.setEKey("key_" + i++);
             wbsFormElement.setFId(String.valueOf(formElementDTO.getId()));
         }
@@ -1284,10 +1283,9 @@ public class WbsTreeServiceImpl extends BaseServiceImpl<WbsTreeMapper, WbsTree>
         //新增元素
         boolean b2 = wbsFormElementService.saveBatch(elementList, 10000);
 
-        //找到当前元素表中所有元素
         List<WbsFormElement> list = wbsFormElementService.selectElementListByFid(String.valueOf(formElementDTO.getId()));
 
-        //初始化实体表
+        //新增实体表
         Boolean b3 = wbsFormElementService.initTable(list, newTableName);
 
         if (b1 && b2 && b3) {

+ 122 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/unit/ProtoStuffSerializerUtil.java

@@ -0,0 +1,122 @@
+package org.springblade.manager.unit;
+
+import com.dyuproject.protostuff.LinkedBuffer;
+import com.dyuproject.protostuff.ProtostuffIOUtil;
+import com.dyuproject.protostuff.Schema;
+import com.dyuproject.protostuff.runtime.RuntimeSchema;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * ProtoStuffSerializerUtil
+ */
+public class ProtoStuffSerializerUtil {
+    /**
+     * 序列化对象
+     *
+     * @param obj
+     * @return
+     */
+    public static <T> byte[] serialize(T obj) {
+        if (obj == null) {
+            throw new RuntimeException("序列化对象(" + obj + ")!");
+        }
+        @SuppressWarnings("unchecked")
+        Schema<T> schema = (Schema<T>) RuntimeSchema.getSchema(obj.getClass());
+        LinkedBuffer buffer = LinkedBuffer.allocate(1024 * 1024);
+        byte[] protostuff = null;
+        try {
+            protostuff = ProtostuffIOUtil.toByteArray(obj, schema, buffer);
+        } catch (Exception e) {
+            throw new RuntimeException("序列化(" + obj.getClass() + ")对象(" + obj + ")发生异常!", e);
+        } finally {
+            buffer.clear();
+        }
+        return protostuff;
+    }
+
+    /**
+     * 反序列化对象
+     *
+     * @param paramArrayOfByte
+     * @param targetClass
+     * @return
+     */
+    public static <T> T deserialize(byte[] paramArrayOfByte, Class<T> targetClass) {
+        if (paramArrayOfByte == null || paramArrayOfByte.length == 0) {
+            throw new RuntimeException("反序列化对象发生异常,byte序列为空!");
+        }
+        T instance = null;
+        try {
+            instance = targetClass.newInstance();
+        } catch (InstantiationException e1) {
+            throw new RuntimeException("反序列化过程中依据类型创建对象失败!", e1);
+        } catch (IllegalAccessException e2) {
+            throw new RuntimeException("反序列化过程中依据类型创建对象失败!", e2);
+        }
+        Schema<T> schema = RuntimeSchema.getSchema(targetClass);
+        ProtostuffIOUtil.mergeFrom(paramArrayOfByte, instance, schema);
+        return instance;
+    }
+
+    /**
+     * 序列化列表
+     *
+     * @param objList
+     * @return
+     */
+    public static <T> byte[] serializeList(List<T> objList) {
+        if (objList == null || objList.isEmpty()) {
+            throw new RuntimeException("序列化对象列表(" + objList + ")参数异常!");
+        }
+        @SuppressWarnings("unchecked")
+        Schema<T> schema = (Schema<T>) RuntimeSchema.getSchema(objList.get(0).getClass());
+        LinkedBuffer buffer = LinkedBuffer.allocate(1024 * 1024);
+        byte[] protostuff = null;
+        ByteArrayOutputStream bos = null;
+        try {
+            bos = new ByteArrayOutputStream();
+            ProtostuffIOUtil.writeListTo(bos, objList, schema, buffer);
+            protostuff = bos.toByteArray();
+        } catch (Exception e) {
+            throw new RuntimeException("序列化对象列表(" + objList + ")发生异常!", e);
+        } finally {
+            buffer.clear();
+            try {
+                if (bos != null) {
+                    bos.close();
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+
+        return protostuff;
+    }
+
+    /**
+     * 反序列化列表
+     *
+     * @param paramArrayOfByte
+     * @param targetClass
+     * @return
+     */
+    public static <T> List<T> deserializeList(byte[] paramArrayOfByte, Class<T> targetClass) {
+        if (paramArrayOfByte == null || paramArrayOfByte.length == 0) {
+            throw new RuntimeException("反序列化对象发生异常,byte序列为空!");
+        }
+
+        Schema<T> schema = RuntimeSchema.getSchema(targetClass);
+        List<T> result = null;
+        try {
+            result = ProtostuffIOUtil.parseListFrom(new ByteArrayInputStream(paramArrayOfByte), schema);
+        } catch (IOException e) {
+            throw new RuntimeException("反序列化对象列表发生异常!", e);
+        }
+        return result;
+    }
+
+}

+ 1366 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/unit/RedisUtil.java

@@ -0,0 +1,1366 @@
+package org.springblade.manager.unit;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.dao.DataAccessException;
+import org.springframework.data.redis.connection.DataType;
+import org.springframework.data.redis.connection.RedisConnection;
+import org.springframework.data.redis.core.Cursor;
+import org.springframework.data.redis.core.RedisCallback;
+import org.springframework.data.redis.core.ScanOptions;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.data.redis.core.ZSetOperations.TypedTuple;
+import org.springframework.stereotype.Component;
+
+import java.util.*;
+import java.util.Map.Entry;
+import java.util.concurrent.TimeUnit;
+
+@Component
+public class RedisUtil {
+
+    @Autowired
+    private StringRedisTemplate redisTemplate;
+
+    /** -------------------key相关操作--------------------- */
+
+    /**
+     * 删除key
+     *
+     * @param key
+     */
+    public void delete(String key) {
+        redisTemplate.delete(key);
+    }
+
+    /**
+     * 批量删除key
+     *
+     * @param keys
+     */
+    public void delete(Collection<String> keys) {
+        redisTemplate.delete(keys);
+    }
+
+    /**
+     * 序列化key
+     *
+     * @param key
+     * @return
+     */
+    public byte[] dump(String key) {
+        return redisTemplate.dump(key);
+    }
+
+    /**
+     * 是否存在key
+     *
+     * @param key
+     * @return
+     */
+    public Boolean hasKey(String key) {
+        return redisTemplate.hasKey(key);
+    }
+
+    /**
+     * 设置过期时间
+     *
+     * @param key
+     * @param timeout
+     * @param unit
+     * @return
+     */
+    public Boolean expire(String key, long timeout, TimeUnit unit) {
+        return redisTemplate.expire(key, timeout, unit);
+    }
+
+    /**
+     * 设置过期时间
+     *
+     * @param key
+     * @param date
+     * @return
+     */
+    public Boolean expireAt(String key, Date date) {
+        return redisTemplate.expireAt(key, date);
+    }
+
+    /**
+     * 查找匹配的key
+     *
+     * @param pattern
+     * @return
+     */
+    public Set<String> keys(String pattern) {
+        return redisTemplate.keys(pattern);
+    }
+
+    /**
+     * 将当前数据库的 key 移动到给定的数据库 db 当中
+     *
+     * @param key
+     * @param dbIndex
+     * @return
+     */
+    public Boolean move(String key, int dbIndex) {
+        return redisTemplate.move(key, dbIndex);
+    }
+
+    /**
+     * 移除 key 的过期时间,key 将持久保持
+     *
+     * @param key
+     * @return
+     */
+    public Boolean persist(String key) {
+        return redisTemplate.persist(key);
+    }
+
+    /**
+     * 返回 key 的剩余的过期时间
+     *
+     * @param key
+     * @param unit
+     * @return
+     */
+    public Long getExpire(String key, TimeUnit unit) {
+        return redisTemplate.getExpire(key, unit);
+    }
+
+    /**
+     * 返回 key 的剩余的过期时间
+     *
+     * @param key
+     * @return
+     */
+    public Long getExpire(String key) {
+        return redisTemplate.getExpire(key);
+    }
+
+    /**
+     * 从当前数据库中随机返回一个 key
+     *
+     * @return
+     */
+    public String randomKey() {
+        return redisTemplate.randomKey();
+    }
+
+    /**
+     * 修改 key 的名称
+     *
+     * @param oldKey
+     * @param newKey
+     */
+    public void rename(String oldKey, String newKey) {
+        redisTemplate.rename(oldKey, newKey);
+    }
+
+    /**
+     * 仅当 newkey 不存在时,将 oldKey 改名为 newkey
+     *
+     * @param oldKey
+     * @param newKey
+     * @return
+     */
+    public Boolean renameIfAbsent(String oldKey, String newKey) {
+        return redisTemplate.renameIfAbsent(oldKey, newKey);
+    }
+
+    /**
+     * 返回 key 所储存的值的类型
+     *
+     * @param key
+     * @return
+     */
+    public DataType type(String key) {
+        return redisTemplate.type(key);
+    }
+
+    /** -------------------string相关操作--------------------- */
+
+    /**
+     * 设置指定 key 的值
+     *
+     * @param key
+     * @param value
+     */
+    public void set(String key, String value) {
+        redisTemplate.opsForValue().set(key, value);
+    }
+
+    /**
+     * 获取指定 key 的值
+     *
+     * @param key
+     * @return
+     */
+    public String get(String key) {
+        return redisTemplate.opsForValue().get(key);
+    }
+
+    /**
+     * 返回 key 中字符串值的子字符
+     *
+     * @param key
+     * @param start
+     * @param end
+     * @return
+     */
+    public String getRange(String key, long start, long end) {
+        return redisTemplate.opsForValue().get(key, start, end);
+    }
+
+    /**
+     * 将给定 key 的值设为 value ,并返回 key 的旧值(old value)
+     *
+     * @param key
+     * @param value
+     * @return
+     */
+    public String getAndSet(String key, String value) {
+        return redisTemplate.opsForValue().getAndSet(key, value);
+    }
+
+    /**
+     * 对 key 所储存的字符串值,获取指定偏移量上的位(bit)
+     *
+     * @param key
+     * @param offset
+     * @return
+     */
+    public Boolean getBit(String key, long offset) {
+        return redisTemplate.opsForValue().getBit(key, offset);
+    }
+
+    /**
+     * 批量获取
+     *
+     * @param keys
+     * @return
+     */
+    public List<String> multiGet(Collection<String> keys) {
+        return redisTemplate.opsForValue().multiGet(keys);
+    }
+
+    /**
+     * 设置ASCII码, 字符串'a'的ASCII码是97, 转为二进制是'01100001', 此方法是将二进制第offset位值变为value
+     *
+     * @param key   位置
+     * @param value 值,true为1, false为0
+     * @return
+     */
+    public boolean setBit(String key, long offset, boolean value) {
+        return redisTemplate.opsForValue().setBit(key, offset, value);
+    }
+
+    /**
+     * 将值 value 关联到 key ,并将 key 的过期时间设为 timeout
+     *
+     * @param key
+     * @param value
+     * @param timeout 过期时间
+     * @param unit    时间单位, 天:TimeUnit.DAYS 小时:TimeUnit.HOURS 分钟:TimeUnit.MINUTES
+     *                秒:TimeUnit.SECONDS 毫秒:TimeUnit.MILLISECONDS
+     */
+    public void setEx(String key, String value, long timeout, TimeUnit unit) {
+        redisTemplate.opsForValue().set(key, value, timeout, unit);
+    }
+
+    /**
+     * 只有在 key 不存在时设置 key 的值
+     *
+     * @param key
+     * @param value
+     * @return 之前已经存在返回false, 不存在返回true
+     */
+    public boolean setIfAbsent(String key, String value) {
+        return redisTemplate.opsForValue().setIfAbsent(key, value);
+    }
+
+    /**
+     * 用 value 参数覆写给定 key 所储存的字符串值,从偏移量 offset 开始
+     *
+     * @param key
+     * @param value
+     * @param offset 从指定位置开始覆写
+     */
+    public void setRange(String key, String value, long offset) {
+        redisTemplate.opsForValue().set(key, value, offset);
+    }
+
+    /**
+     * 获取字符串的长度
+     *
+     * @param key
+     * @return
+     */
+    public Long size(String key) {
+        return redisTemplate.opsForValue().size(key);
+    }
+
+    /**
+     * 批量添加
+     *
+     * @param maps
+     */
+    public void multiSet(Map<String, String> maps) {
+        redisTemplate.opsForValue().multiSet(maps);
+    }
+
+    /**
+     * 同时设置一个或多个 key-value 对,当且仅当所有给定 key 都不存在
+     *
+     * @param maps
+     * @return 之前已经存在返回false, 不存在返回true
+     */
+    public boolean multiSetIfAbsent(Map<String, String> maps) {
+        return redisTemplate.opsForValue().multiSetIfAbsent(maps);
+    }
+
+    /**
+     * 增加(自增长), 负数则为自减
+     *
+     * @param key
+     * @param increment
+     * @return
+     */
+    public Long incrBy(String key, long increment) {
+        return redisTemplate.opsForValue().increment(key, increment);
+    }
+
+    /**
+     * 增加(自增长), 负数则为自减
+     *
+     * @param key
+     * @param increment
+     * @return
+     */
+    public Double incrByFloat(String key, double increment) {
+        return redisTemplate.opsForValue().increment(key, increment);
+    }
+
+    /**
+     * 追加到末尾
+     *
+     * @param key
+     * @param value
+     * @return
+     */
+    public Integer append(String key, String value) {
+        return redisTemplate.opsForValue().append(key, value);
+    }
+
+    /** -------------------hash相关操作------------------------- */
+
+    /**
+     * 获取存储在哈希表中指定字段的值
+     *
+     * @param key
+     * @param field
+     * @return
+     */
+    public Object hGet(String key, String field) {
+        return redisTemplate.opsForHash().get(key, field);
+    }
+
+    /**
+     * 获取所有给定字段的值
+     *
+     * @param key
+     * @return
+     */
+    public Map<Object, Object> hGetAll(String key) {
+        return redisTemplate.opsForHash().entries(key);
+    }
+
+    /**
+     * 获取所有给定字段的值
+     *
+     * @param key
+     * @param fields
+     * @return
+     */
+    public List<Object> hMultiGet(String key, Collection<Object> fields) {
+        return redisTemplate.opsForHash().multiGet(key, fields);
+    }
+
+    public void hPut(String key, String hashKey, String value) {
+        redisTemplate.opsForHash().put(key, hashKey, value);
+    }
+
+    public void hPutAll(String key, Map<String, String> maps) {
+        redisTemplate.opsForHash().putAll(key, maps);
+    }
+
+    /**
+     * 仅当hashKey不存在时才设置
+     *
+     * @param key
+     * @param hashKey
+     * @param value
+     * @return
+     */
+    public Boolean hPutIfAbsent(String key, String hashKey, String value) {
+        return redisTemplate.opsForHash().putIfAbsent(key, hashKey, value);
+    }
+
+    /**
+     * 删除一个或多个哈希表字段
+     *
+     * @param key
+     * @param fields
+     * @return
+     */
+    public Long hDelete(String key, Object... fields) {
+        return redisTemplate.opsForHash().delete(key, fields);
+    }
+
+    /**
+     * 查看哈希表 key 中,指定的字段是否存在
+     *
+     * @param key
+     * @param field
+     * @return
+     */
+    public boolean hExists(String key, String field) {
+        return redisTemplate.opsForHash().hasKey(key, field);
+    }
+
+    /**
+     * 为哈希表 key 中的指定字段的整数值加上增量 increment
+     *
+     * @param key
+     * @param field
+     * @param increment
+     * @return
+     */
+    public Long hIncrBy(String key, Object field, long increment) {
+        return redisTemplate.opsForHash().increment(key, field, increment);
+    }
+
+    /**
+     * 为哈希表 key 中的指定字段的整数值加上增量 increment
+     *
+     * @param key
+     * @param field
+     * @param delta
+     * @return
+     */
+    public Double hIncrByFloat(String key, Object field, double delta) {
+        return redisTemplate.opsForHash().increment(key, field, delta);
+    }
+
+    /**
+     * 获取所有哈希表中的字段
+     *
+     * @param key
+     * @return
+     */
+    public Set<Object> hKeys(String key) {
+        return redisTemplate.opsForHash().keys(key);
+    }
+
+    /**
+     * 获取哈希表中字段的数量
+     *
+     * @param key
+     * @return
+     */
+    public Long hSize(String key) {
+        return redisTemplate.opsForHash().size(key);
+    }
+
+    /**
+     * 获取哈希表中所有值
+     *
+     * @param key
+     * @return
+     */
+    public List<Object> hValues(String key) {
+        return redisTemplate.opsForHash().values(key);
+    }
+
+    /**
+     * 迭代哈希表中的键值对
+     *
+     * @param key
+     * @param options
+     * @return
+     */
+    public Cursor<Entry<Object, Object>> hScan(String key, ScanOptions options) {
+        return redisTemplate.opsForHash().scan(key, options);
+    }
+
+    /** ------------------------list相关操作---------------------------- */
+
+    /**
+     * 通过索引获取列表中的元素
+     *
+     * @param key
+     * @param index
+     * @return
+     */
+    public String lIndex(String key, long index) {
+        return redisTemplate.opsForList().index(key, index);
+    }
+
+    /**
+     * 获取列表指定范围内的元素
+     *
+     * @param key
+     * @param start 开始位置, 0是开始位置
+     * @param end   结束位置, -1返回所有
+     * @return
+     */
+    public List<String> lRange(String key, long start, long end) {
+        return redisTemplate.opsForList().range(key, start, end);
+    }
+
+    /**
+     * 存储在list头部
+     *
+     * @param key
+     * @param value
+     * @return
+     */
+    public Long lLeftPush(String key, String value) {
+        return redisTemplate.opsForList().leftPush(key, value);
+    }
+
+    /**
+     * @param key
+     * @param value
+     * @return
+     */
+    public Long lLeftPushAll(String key, String... value) {
+        return redisTemplate.opsForList().leftPushAll(key, value);
+    }
+
+    /**
+     * @param key
+     * @param value
+     * @return
+     */
+    public Long lLeftPushAll(String key, Collection<String> value) {
+        return redisTemplate.opsForList().leftPushAll(key, value);
+    }
+
+    /**
+     * 当list存在的时候才加入
+     *
+     * @param key
+     * @param value
+     * @return
+     */
+    public Long lLeftPushIfPresent(String key, String value) {
+        return redisTemplate.opsForList().leftPushIfPresent(key, value);
+    }
+
+    /**
+     * 如果pivot存在,再pivot前面添加
+     *
+     * @param key
+     * @param pivot
+     * @param value
+     * @return
+     */
+    public Long lLeftPush(String key, String pivot, String value) {
+        return redisTemplate.opsForList().leftPush(key, pivot, value);
+    }
+
+    /**
+     * @param key
+     * @param value
+     * @return
+     */
+    public Long lRightPush(String key, String value) {
+        return redisTemplate.opsForList().rightPush(key, value);
+    }
+
+    /**
+     * @param key
+     * @param value
+     * @return
+     */
+    public Long lRightPushAll(String key, String... value) {
+        return redisTemplate.opsForList().rightPushAll(key, value);
+    }
+
+    /**
+     * @param key
+     * @param value
+     * @return
+     */
+    public Long lRightPushAll(String key, Collection<String> value) {
+        return redisTemplate.opsForList().rightPushAll(key, value);
+    }
+
+    /**
+     * 为已存在的列表添加值
+     *
+     * @param key
+     * @param value
+     * @return
+     */
+    public Long lRightPushIfPresent(String key, String value) {
+        return redisTemplate.opsForList().rightPushIfPresent(key, value);
+    }
+
+    /**
+     * 在pivot元素的右边添加值
+     *
+     * @param key
+     * @param pivot
+     * @param value
+     * @return
+     */
+    public Long lRightPush(String key, String pivot, String value) {
+        return redisTemplate.opsForList().rightPush(key, pivot, value);
+    }
+
+    /**
+     * 通过索引设置列表元素的值
+     *
+     * @param key
+     * @param index 位置
+     * @param value
+     */
+    public void lSet(String key, long index, String value) {
+        redisTemplate.opsForList().set(key, index, value);
+    }
+
+    /**
+     * 移出并获取列表的第一个元素
+     *
+     * @param key
+     * @return 删除的元素
+     */
+    public String lLeftPop(String key) {
+        return redisTemplate.opsForList().leftPop(key);
+    }
+
+    /**
+     * 移出并获取列表的第一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止
+     *
+     * @param key
+     * @param timeout 等待时间
+     * @param unit    时间单位
+     * @return
+     */
+    public String lBLeftPop(String key, long timeout, TimeUnit unit) {
+        return redisTemplate.opsForList().leftPop(key, timeout, unit);
+    }
+
+    /**
+     * 移除并获取列表最后一个元素
+     *
+     * @param key
+     * @return 删除的元素
+     */
+    public String lRightPop(String key) {
+        return redisTemplate.opsForList().rightPop(key);
+    }
+
+    /**
+     * 移出并获取列表的最后一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止
+     *
+     * @param key
+     * @param timeout 等待时间
+     * @param unit    时间单位
+     * @return
+     */
+    public String lBRightPop(String key, long timeout, TimeUnit unit) {
+        return redisTemplate.opsForList().rightPop(key, timeout, unit);
+    }
+
+    /**
+     * 移除列表的最后一个元素,并将该元素添加到另一个列表并返回
+     *
+     * @param sourceKey
+     * @param destinationKey
+     * @return
+     */
+    public String lRightPopAndLeftPush(String sourceKey, String destinationKey) {
+        return redisTemplate.opsForList().rightPopAndLeftPush(sourceKey,
+                destinationKey);
+    }
+
+    /**
+     * 从列表中弹出一个值,将弹出的元素插入到另外一个列表中并返回它; 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止
+     *
+     * @param sourceKey
+     * @param destinationKey
+     * @param timeout
+     * @param unit
+     * @return
+     */
+    public String lBRightPopAndLeftPush(String sourceKey, String destinationKey,
+                                        long timeout, TimeUnit unit) {
+        return redisTemplate.opsForList().rightPopAndLeftPush(sourceKey,
+                destinationKey, timeout, unit);
+    }
+
+    /**
+     * 删除集合中值等于value得元素
+     *
+     * @param key
+     * @param index index=0, 删除所有值等于value的元素; index>0, 从头部开始删除第一个值等于value的元素;
+     *              index<0, 从尾部开始删除第一个值等于value的元素;
+     * @param value
+     * @return
+     */
+    public Long lRemove(String key, long index, String value) {
+        return redisTemplate.opsForList().remove(key, index, value);
+    }
+
+    /**
+     * 裁剪list
+     *
+     * @param key
+     * @param start
+     * @param end
+     */
+    public void lTrim(String key, long start, long end) {
+        redisTemplate.opsForList().trim(key, start, end);
+    }
+
+    /**
+     * 获取列表长度
+     *
+     * @param key
+     * @return
+     */
+    public Long lLen(String key) {
+        return redisTemplate.opsForList().size(key);
+    }
+
+    /** --------------------set相关操作-------------------------- */
+
+    /**
+     * set添加元素
+     *
+     * @param key
+     * @param values
+     * @return
+     */
+    public Long sAdd(String key, String... values) {
+        return redisTemplate.opsForSet().add(key, values);
+    }
+
+    /**
+     * set移除元素
+     *
+     * @param key
+     * @param values
+     * @return
+     */
+    public Long sRemove(String key, Object... values) {
+        return redisTemplate.opsForSet().remove(key, values);
+    }
+
+    /**
+     * 移除并返回集合的一个随机元素
+     *
+     * @param key
+     * @return
+     */
+    public String sPop(String key) {
+        return redisTemplate.opsForSet().pop(key);
+    }
+
+    /**
+     * 将元素value从一个集合移到另一个集合
+     *
+     * @param key
+     * @param value
+     * @param destKey
+     * @return
+     */
+    public Boolean sMove(String key, String value, String destKey) {
+        return redisTemplate.opsForSet().move(key, value, destKey);
+    }
+
+    /**
+     * 获取集合的大小
+     *
+     * @param key
+     * @return
+     */
+    public Long sSize(String key) {
+        return redisTemplate.opsForSet().size(key);
+    }
+
+    /**
+     * 判断集合是否包含value
+     *
+     * @param key
+     * @param value
+     * @return
+     */
+    public Boolean sIsMember(String key, Object value) {
+        return redisTemplate.opsForSet().isMember(key, value);
+    }
+
+    /**
+     * 获取两个集合的交集
+     *
+     * @param key
+     * @param otherKey
+     * @return
+     */
+    public Set<String> sIntersect(String key, String otherKey) {
+        return redisTemplate.opsForSet().intersect(key, otherKey);
+    }
+
+    /**
+     * 获取key集合与多个集合的交集
+     *
+     * @param key
+     * @param otherKeys
+     * @return
+     */
+    public Set<String> sIntersect(String key, Collection<String> otherKeys) {
+        return redisTemplate.opsForSet().intersect(key, otherKeys);
+    }
+
+    /**
+     * key集合与otherKey集合的交集存储到destKey集合中
+     *
+     * @param key
+     * @param otherKey
+     * @param destKey
+     * @return
+     */
+    public Long sIntersectAndStore(String key, String otherKey, String destKey) {
+        return redisTemplate.opsForSet().intersectAndStore(key, otherKey,
+                destKey);
+    }
+
+    /**
+     * key集合与多个集合的交集存储到destKey集合中
+     *
+     * @param key
+     * @param otherKeys
+     * @param destKey
+     * @return
+     */
+    public Long sIntersectAndStore(String key, Collection<String> otherKeys,
+                                   String destKey) {
+        return redisTemplate.opsForSet().intersectAndStore(key, otherKeys,
+                destKey);
+    }
+
+    /**
+     * 获取两个集合的并集
+     *
+     * @param key
+     * @param otherKeys
+     * @return
+     */
+    public Set<String> sUnion(String key, String otherKeys) {
+        return redisTemplate.opsForSet().union(key, otherKeys);
+    }
+
+    /**
+     * 获取key集合与多个集合的并集
+     *
+     * @param key
+     * @param otherKeys
+     * @return
+     */
+    public Set<String> sUnion(String key, Collection<String> otherKeys) {
+        return redisTemplate.opsForSet().union(key, otherKeys);
+    }
+
+    /**
+     * key集合与otherKey集合的并集存储到destKey中
+     *
+     * @param key
+     * @param otherKey
+     * @param destKey
+     * @return
+     */
+    public Long sUnionAndStore(String key, String otherKey, String destKey) {
+        return redisTemplate.opsForSet().unionAndStore(key, otherKey, destKey);
+    }
+
+    /**
+     * key集合与多个集合的并集存储到destKey中
+     *
+     * @param key
+     * @param otherKeys
+     * @param destKey
+     * @return
+     */
+    public Long sUnionAndStore(String key, Collection<String> otherKeys,
+                               String destKey) {
+        return redisTemplate.opsForSet().unionAndStore(key, otherKeys, destKey);
+    }
+
+    /**
+     * 获取两个集合的差集
+     *
+     * @param key
+     * @param otherKey
+     * @return
+     */
+    public Set<String> sDifference(String key, String otherKey) {
+        return redisTemplate.opsForSet().difference(key, otherKey);
+    }
+
+    /**
+     * 获取key集合与多个集合的差集
+     *
+     * @param key
+     * @param otherKeys
+     * @return
+     */
+    public Set<String> sDifference(String key, Collection<String> otherKeys) {
+        return redisTemplate.opsForSet().difference(key, otherKeys);
+    }
+
+    /**
+     * key集合与otherKey集合的差集存储到destKey中
+     *
+     * @param key
+     * @param otherKey
+     * @param destKey
+     * @return
+     */
+    public Long sDifference(String key, String otherKey, String destKey) {
+        return redisTemplate.opsForSet().differenceAndStore(key, otherKey,
+                destKey);
+    }
+
+    /**
+     * key集合与多个集合的差集存储到destKey中
+     *
+     * @param key
+     * @param otherKeys
+     * @param destKey
+     * @return
+     */
+    public Long sDifference(String key, Collection<String> otherKeys,
+                            String destKey) {
+        return redisTemplate.opsForSet().differenceAndStore(key, otherKeys,
+                destKey);
+    }
+
+    /**
+     * 获取集合所有元素
+     *
+     * @param key
+     * @return
+     */
+    public Set<String> setMembers(String key) {
+        return redisTemplate.opsForSet().members(key);
+    }
+
+    /**
+     * 随机获取集合中的一个元素
+     *
+     * @param key
+     * @return
+     */
+    public String sRandomMember(String key) {
+        return redisTemplate.opsForSet().randomMember(key);
+    }
+
+    /**
+     * 随机获取集合中count个元素
+     *
+     * @param key
+     * @param count
+     * @return
+     */
+    public List<String> sRandomMembers(String key, long count) {
+        return redisTemplate.opsForSet().randomMembers(key, count);
+    }
+
+    /**
+     * 随机获取集合中count个元素并且去除重复的
+     *
+     * @param key
+     * @param count
+     * @return
+     */
+    public Set<String> sDistinctRandomMembers(String key, long count) {
+        return redisTemplate.opsForSet().distinctRandomMembers(key, count);
+    }
+
+    /**
+     * @param key
+     * @param options
+     * @return
+     */
+    public Cursor<String> sScan(String key, ScanOptions options) {
+        return redisTemplate.opsForSet().scan(key, options);
+    }
+
+    /**------------------zSet相关操作--------------------------------*/
+
+    /**
+     * 添加元素,有序集合是按照元素的score值由小到大排列
+     *
+     * @param key
+     * @param value
+     * @param score
+     * @return
+     */
+    public Boolean zAdd(String key, String value, double score) {
+        return redisTemplate.opsForZSet().add(key, value, score);
+    }
+
+    /**
+     * @param key
+     * @param values
+     * @return
+     */
+    public Long zAdd(String key, Set<TypedTuple<String>> values) {
+        return redisTemplate.opsForZSet().add(key, values);
+    }
+
+    /**
+     * @param key
+     * @param values
+     * @return
+     */
+    public Long zRemove(String key, Object... values) {
+        return redisTemplate.opsForZSet().remove(key, values);
+    }
+
+    /**
+     * 增加元素的score值,并返回增加后的值
+     *
+     * @param key
+     * @param value
+     * @param delta
+     * @return
+     */
+    public Double zIncrementScore(String key, String value, double delta) {
+        return redisTemplate.opsForZSet().incrementScore(key, value, delta);
+    }
+
+    /**
+     * 返回元素在集合的排名,有序集合是按照元素的score值由小到大排列
+     *
+     * @param key
+     * @param value
+     * @return 0表示第一位
+     */
+    public Long zRank(String key, Object value) {
+        return redisTemplate.opsForZSet().rank(key, value);
+    }
+
+    /**
+     * 返回元素在集合的排名,按元素的score值由大到小排列
+     *
+     * @param key
+     * @param value
+     * @return
+     */
+    public Long zReverseRank(String key, Object value) {
+        return redisTemplate.opsForZSet().reverseRank(key, value);
+    }
+
+    /**
+     * 获取集合的元素, 从小到大排序
+     *
+     * @param key
+     * @param start 开始位置
+     * @param end   结束位置, -1查询所有
+     * @return
+     */
+    public Set<String> zRange(String key, long start, long end) {
+        return redisTemplate.opsForZSet().range(key, start, end);
+    }
+
+    /**
+     * 获取集合元素, 并且把score值也获取
+     *
+     * @param key
+     * @param start
+     * @param end
+     * @return
+     */
+    public Set<TypedTuple<String>> zRangeWithScores(String key, long start,
+                                                    long end) {
+        return redisTemplate.opsForZSet().rangeWithScores(key, start, end);
+    }
+
+    /**
+     * 根据Score值查询集合元素
+     *
+     * @param key
+     * @param min 最小值
+     * @param max 最大值
+     * @return
+     */
+    public Set<String> zRangeByScore(String key, double min, double max) {
+        return redisTemplate.opsForZSet().rangeByScore(key, min, max);
+    }
+
+    /**
+     * 根据Score值查询集合元素, 从小到大排序
+     *
+     * @param key
+     * @param min 最小值
+     * @param max 最大值
+     * @return
+     */
+    public Set<TypedTuple<String>> zRangeByScoreWithScores(String key,
+                                                           double min, double max) {
+        return redisTemplate.opsForZSet().rangeByScoreWithScores(key, min, max);
+    }
+
+    /**
+     * @param key
+     * @param min
+     * @param max
+     * @param start
+     * @param end
+     * @return
+     */
+    public Set<TypedTuple<String>> zRangeByScoreWithScores(String key,
+                                                           double min, double max, long start, long end) {
+        return redisTemplate.opsForZSet().rangeByScoreWithScores(key, min, max,
+                start, end);
+    }
+
+    /**
+     * 获取集合的元素, 从大到小排序
+     *
+     * @param key
+     * @param start
+     * @param end
+     * @return
+     */
+    public Set<String> zReverseRange(String key, long start, long end) {
+        return redisTemplate.opsForZSet().reverseRange(key, start, end);
+    }
+
+    /**
+     * 获取集合的元素, 从大到小排序, 并返回score值
+     *
+     * @param key
+     * @param start
+     * @param end
+     * @return
+     */
+    public Set<TypedTuple<String>> zReverseRangeWithScores(String key,
+                                                           long start, long end) {
+        return redisTemplate.opsForZSet().reverseRangeWithScores(key, start,
+                end);
+    }
+
+    /**
+     * 根据Score值查询集合元素, 从大到小排序
+     *
+     * @param key
+     * @param min
+     * @param max
+     * @return
+     */
+    public Set<String> zReverseRangeByScore(String key, double min,
+                                            double max) {
+        return redisTemplate.opsForZSet().reverseRangeByScore(key, min, max);
+    }
+
+    /**
+     * 根据Score值查询集合元素, 从大到小排序
+     *
+     * @param key
+     * @param min
+     * @param max
+     * @return
+     */
+    public Set<TypedTuple<String>> zReverseRangeByScoreWithScores(
+            String key, double min, double max) {
+        return redisTemplate.opsForZSet().reverseRangeByScoreWithScores(key,
+                min, max);
+    }
+
+    /**
+     * @param key
+     * @param min
+     * @param max
+     * @param start
+     * @param end
+     * @return
+     */
+    public Set<String> zReverseRangeByScore(String key, double min,
+                                            double max, long start, long end) {
+        return redisTemplate.opsForZSet().reverseRangeByScore(key, min, max,
+                start, end);
+    }
+
+    /**
+     * 根据score值获取集合元素数量
+     *
+     * @param key
+     * @param min
+     * @param max
+     * @return
+     */
+    public Long zCount(String key, double min, double max) {
+        return redisTemplate.opsForZSet().count(key, min, max);
+    }
+
+    /**
+     * 获取集合大小
+     *
+     * @param key
+     * @return
+     */
+    public Long zSize(String key) {
+        return redisTemplate.opsForZSet().size(key);
+    }
+
+    /**
+     * 获取集合大小
+     *
+     * @param key
+     * @return
+     */
+    public Long zZCard(String key) {
+        return redisTemplate.opsForZSet().zCard(key);
+    }
+
+    /**
+     * 获取集合中value元素的score值
+     *
+     * @param key
+     * @param value
+     * @return
+     */
+    public Double zScore(String key, Object value) {
+        return redisTemplate.opsForZSet().score(key, value);
+    }
+
+    /**
+     * 移除指定索引位置的成员
+     *
+     * @param key
+     * @param start
+     * @param end
+     * @return
+     */
+    public Long zRemoveRange(String key, long start, long end) {
+        return redisTemplate.opsForZSet().removeRange(key, start, end);
+    }
+
+    /**
+     * 根据指定的score值的范围来移除成员
+     *
+     * @param key
+     * @param min
+     * @param max
+     * @return
+     */
+    public Long zRemoveRangeByScore(String key, double min, double max) {
+        return redisTemplate.opsForZSet().removeRangeByScore(key, min, max);
+    }
+
+    /**
+     * 获取key和otherKey的并集并存储在destKey中
+     *
+     * @param key
+     * @param otherKey
+     * @param destKey
+     * @return
+     */
+    public Long zUnionAndStore(String key, String otherKey, String destKey) {
+        return redisTemplate.opsForZSet().unionAndStore(key, otherKey, destKey);
+    }
+
+    /**
+     * @param key
+     * @param otherKeys
+     * @param destKey
+     * @return
+     */
+    public Long zUnionAndStore(String key, Collection<String> otherKeys,
+                               String destKey) {
+        return redisTemplate.opsForZSet()
+                .unionAndStore(key, otherKeys, destKey);
+    }
+
+    /**
+     * 交集
+     *
+     * @param key
+     * @param otherKey
+     * @param destKey
+     * @return
+     */
+    public Long zIntersectAndStore(String key, String otherKey,
+                                   String destKey) {
+        return redisTemplate.opsForZSet().intersectAndStore(key, otherKey,
+                destKey);
+    }
+
+    /**
+     * 交集
+     *
+     * @param key
+     * @param otherKeys
+     * @param destKey
+     * @return
+     */
+    public Long zIntersectAndStore(String key, Collection<String> otherKeys,
+                                   String destKey) {
+        return redisTemplate.opsForZSet().intersectAndStore(key, otherKeys,
+                destKey);
+    }
+
+    /**
+     * @param key
+     * @param options
+     * @return
+     */
+    public Cursor<TypedTuple<String>> zScan(String key, ScanOptions options) {
+        return redisTemplate.opsForZSet().scan(key, options);
+    }
+
+    /**
+     * 获取Redis List 序列化
+     *
+     * @param key
+     * @param targetClass
+     * @param <T>
+     * @return
+     */
+    public <T> List<T> getListCache(final String key, Class<T> targetClass) {
+        byte[] result = redisTemplate.execute(new RedisCallback<byte[]>() {
+            @Override
+            public byte[] doInRedis(RedisConnection connection) throws DataAccessException {
+                return connection.get(key.getBytes());
+            }
+        });
+        if (result == null) {
+            return null;
+        }
+        return ProtoStuffSerializerUtil.deserializeList(result, targetClass);
+    }
+
+    /***
+     * 将List 放进缓存里面
+     * @param key
+     * @param objList
+     * @param expireTime
+     * @param <T>
+     * @return
+     */
+    public <T> boolean putListCacheWithExpireTime(String key, List<T> objList, final long expireTime) {
+        final byte[] bkey = key.getBytes();
+        final byte[] bvalue = ProtoStuffSerializerUtil.serializeList(objList);
+        boolean result = redisTemplate.execute(new RedisCallback<Boolean>() {
+            @Override
+            public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
+                connection.setEx(bkey, expireTime, bvalue);
+                return true;
+            }
+        });
+        return result;
+    }
+}