瀏覽代碼

Merge remote-tracking branch 'origin/master'

liuyc 2 年之前
父節點
當前提交
64efba3bcd
共有 22 個文件被更改,包括 363 次插入66 次删除
  1. 24 0
      blade-common/src/main/java/org/springblade/common/utils/BaseUtils.java
  2. 3 0
      blade-service-api/blade-control-api/src/main/java/org/springblade/control/vo/DepartmentMonthPlanVO.java
  3. 4 1
      blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchiveFileController.java
  4. 33 1
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ArchivesAutoServiceImpl.java
  5. 20 0
      blade-service/blade-control/src/main/java/org/springblade/control/controller/ProjectCostBudgetController.java
  6. 3 3
      blade-service/blade-control/src/main/java/org/springblade/control/mapper/AnnualBudgetMapper.xml
  7. 3 0
      blade-service/blade-control/src/main/java/org/springblade/control/mapper/ContractInfoMapper.xml
  8. 1 1
      blade-service/blade-control/src/main/java/org/springblade/control/mapper/ContractReturnedInfoMapper.xml
  9. 2 1
      blade-service/blade-control/src/main/java/org/springblade/control/mapper/DepartmentMonthPlanMapper.xml
  10. 4 0
      blade-service/blade-control/src/main/java/org/springblade/control/mapper/ProjectCostBudgetMapper.java
  11. 32 6
      blade-service/blade-control/src/main/java/org/springblade/control/mapper/ProjectCostBudgetMapper.xml
  12. 4 0
      blade-service/blade-control/src/main/java/org/springblade/control/service/IProjectCostBudgetService.java
  13. 1 0
      blade-service/blade-control/src/main/java/org/springblade/control/service/IProjectInfoService.java
  14. 33 11
      blade-service/blade-control/src/main/java/org/springblade/control/service/impl/AnnualBudgetServiceImpl.java
  15. 3 0
      blade-service/blade-control/src/main/java/org/springblade/control/service/impl/DepartmentMonthPlanServiceImpl.java
  16. 26 0
      blade-service/blade-control/src/main/java/org/springblade/control/service/impl/ProjectCostBudgetServiceImpl.java
  17. 6 0
      blade-service/blade-control/src/main/java/org/springblade/control/service/impl/ProjectCostBudgetStatsServiceImpl.java
  18. 5 1
      blade-service/blade-control/src/main/java/org/springblade/control/service/impl/ProjectInfoServiceImpl.java
  19. 30 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/WbsParamController.java
  20. 2 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/IWbsParamService.java
  21. 79 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsParamServiceImpl.java
  22. 45 38
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreePrivateServiceImpl.java

+ 24 - 0
blade-common/src/main/java/org/springblade/common/utils/BaseUtils.java

@@ -15,6 +15,8 @@ import java.util.jar.JarEntry;
 import java.util.jar.JarFile;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
 
 /**
  * @author yangyj
@@ -74,6 +76,14 @@ public class BaseUtils {
         return false;
     }
 
+
+    /**
+     * @Description  判断对象是否为数值
+     * @Param [value]
+     * @return boolean
+     * @Author yangyj
+     * @Date 2023.01.17 13:48
+     **/
     public static boolean isNumber(Object value) {
         if ((value == null) || value.toString().trim().length() == 0) {
             return false;
@@ -87,4 +97,18 @@ public class BaseUtils {
         return m.matches();
     }
 
+    /**
+     * @Description  根据指定大小对LIST进行切分
+     * @Param [list, chunkSize:每一段长度]
+     * @return java.util.List<java.util.List<T>>
+     * @Author yangyj
+     * @Date 2023.07.03 13:46
+     **/
+    public static <T> List<List<T>> splitList(List<T> list, int chunkSize) {
+        return IntStream.range(0, (list.size() + chunkSize - 1) / chunkSize)
+                .mapToObj(i -> list.subList(i * chunkSize, Math.min((i + 1) * chunkSize, list.size())))
+                .collect(Collectors.toList());
+    }
+
+
 }

+ 3 - 0
blade-service-api/blade-control-api/src/main/java/org/springblade/control/vo/DepartmentMonthPlanVO.java

@@ -30,4 +30,7 @@ public class DepartmentMonthPlanVO extends DepartmentMonthPlan {
     @ApiModelProperty(value = "未完成计划")
     private Integer beginPlanTotal;
 
+    @ApiModelProperty(value = "计划制定人名称")
+    private String planDesignerName;
+
 }

+ 4 - 1
blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchiveFileController.java

@@ -366,7 +366,10 @@ public class ArchiveFileController extends BladeController {
     @ApiOperation(value = "文件收集-上传文件责任者")
     public R getDutyUser(Long contractId, Long projectId) {
         ContractInfo contractById = null;
-        if (contractId == -1) {
+        if (contractId == null || contractId == -1) {
+            if(projectId == null || projectId == -1){
+                return R.data(null);
+            }
             List<Long> longs = new ArrayList<>();
             longs.add(projectId);
             List<ContractInfo> contractInfos = contractClient.queryContractListByIds(longs);

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

@@ -41,6 +41,8 @@ import org.springblade.archive.mapper.ArchivesAutoMapper;
 import org.springblade.archive.service.IArchivesAutoService;
 import org.springblade.business.entity.ArchiveFile;
 import org.springblade.business.feign.ArchiveFileClient;
+import org.springblade.business.feign.MetadataClassificationClient;
+import org.springblade.business.vo.ArchiveFileVO;
 import org.springblade.common.utils.CommonUtil;
 import org.springblade.common.utils.SnowFlakeUtil;
 import org.springblade.core.log.exception.ServiceException;
@@ -111,6 +113,8 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 
 	private final IArchiveProjectConfigService archiveProjectConfigService;
 
+	private final MetadataClassificationClient metadataClassificationClient;
+
 
 	@Override
 	public IPage<ArchivesAutoVO> selectArchivesAutoPage(IPage<ArchivesAutoVO> page, ArchivesAutoVO archivesAuto) {
@@ -1023,7 +1027,7 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 		String projectName = projectInfo.getProjectName();
 		String contractName="";
 		Long contractId = node.getContractId();
-		if(contractId!=null){
+		if(contractId!=null && contractId != -1){
 			ContractInfo contract = contractClient.getContractById(contractId);
 			contractName=contract.getContractName();
 		}
@@ -1101,6 +1105,13 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 
 		}
 		archiveFileClient.updateArchiveFileForCreateArchive(waitArchiveFiles);
+		try {
+			for (ArchiveFile saveVo : waitArchiveFiles) {
+				metadataClassificationClient.createMetadataFile(saveVo.getId(), 0);
+			}
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
 	}
 
 	/**
@@ -1148,6 +1159,13 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 			file.setIsArchive(1);
 		}
 		archiveFileClient.updateArchiveFileForCreateArchive(waitArchiveFiles);
+		try {
+			for (ArchiveFile saveVo : waitArchiveFiles) {
+				metadataClassificationClient.createMetadataFile(saveVo.getId(), 0);
+			}
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
 	}
 
 	/**
@@ -1189,6 +1207,13 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 			file.setIsArchive(1);
 		}
 		archiveFileClient.updateArchiveFileForCreateArchive(waitArchiveFiles);
+		try {
+			for (ArchiveFile saveVo : waitArchiveFiles) {
+				metadataClassificationClient.createMetadataFile(saveVo.getId(), 0);
+			}
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
 	}
 
 	private void createArchiveBox(String boxName,List<ArchiveFile> waitArchiveFiles){
@@ -1237,6 +1262,13 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 			file.setIsArchive(1);
 		}
 		archiveFileClient.updateArchiveFileForCreateArchive(waitArchiveFiles);
+		try {
+			for (ArchiveFile saveVo : waitArchiveFiles) {
+				metadataClassificationClient.createMetadataFile(saveVo.getId(), 0);
+			}
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
 	}
 
 

+ 20 - 0
blade-service/blade-control/src/main/java/org/springblade/control/controller/ProjectCostBudgetController.java

@@ -8,6 +8,7 @@ import io.swagger.annotations.ApiOperation;
 import lombok.AllArgsConstructor;
 import org.springblade.control.dto.ControlProjectInfoDTO;
 import org.springblade.control.dto.ProjectCostBudgetDTO;
+import org.springblade.control.entity.DictInfo;
 import org.springblade.control.entity.ProjectCostBudget;
 import org.springblade.control.service.IProjectCostBudgetService;
 import org.springblade.control.vo.*;
@@ -168,5 +169,24 @@ public class ProjectCostBudgetController {
         return R.data(budgetService.planFinishedRatio(deptId,userId,start,end));
     }
 
+    /**
+     * 查询预览-费用分类列表
+     */
+    @GetMapping("/getCostType")
+    @ApiOperationSupport(order = 12)
+    @ApiOperation(value = "查询预览-费用分类列表")
+    public R<List<DictInfo>> getCostType(){
+        return R.data(budgetService.getCostType());
+    }
+
+    /**
+     * 查询预览-单位列表
+     */
+    @GetMapping("/getUnitType")
+    @ApiOperationSupport(order = 13)
+    @ApiOperation(value = "查询预览-单位列表")
+    public R<List<DictInfo>> getUnitType(){
+        return R.data(budgetService.getUnitType());
+    }
 
 }

+ 3 - 3
blade-service/blade-control/src/main/java/org/springblade/control/mapper/AnnualBudgetMapper.xml

@@ -56,11 +56,11 @@
     </select>
     <select id="getAllBudgetSubject" resultType="org.springblade.control.vo.DictInfoVO">
         select *
-        from c_dict_info di WHERE di.`type` = 1 AND di.parent_id = 0 ORDER BY sort
+        from c_dict_info di WHERE di.`type` = 1 AND di.parent_id = 0 and di.is_deleted = 0 ORDER BY sort
     </select>
     <select id="getAllSecondSubject" resultType="org.springblade.control.vo.DictInfoVO">
         select *
-        from c_dict_info di WHERE di.`type` = 1 AND di.parent_id > 0
+        from c_dict_info di WHERE di.`type` = 1 AND di.is_deleted = 0 and di.parent_id > 0
     </select>
     <select id="getThisYearBudget" resultType="org.springblade.control.entity.AnnualBudget">
         select   <include refid="budget_column" />
@@ -74,7 +74,7 @@
     <select id="yearList" resultType="java.lang.Integer">
         select DATE_FORMAT(start_time,'%Y')
         from c_control_project_info cpi
-        WHERE is_deleted = 0 order by start_time
+        WHERE is_deleted = 0 and start_time is not null order by start_time
             limit 1
     </select>
 

+ 3 - 0
blade-service/blade-control/src/main/java/org/springblade/control/mapper/ContractInfoMapper.xml

@@ -24,6 +24,9 @@
         (IFNULL(( select sum(cri.should_returned_money) from c_contract_returned_info cri where cri.should_returned_time &lt; NOW()  and cri.contract_id = ci.id and cri.is_deleted=0), 0) -
         IFNULL(( select sum(cri.practical_returned_money) from c_contract_returned_info cri where cri.contract_id = ci.id and cri.is_deleted=0), 0)) as unreturnedMoney
         from c_control_contract_info ci where ci.is_deleted = 0
+        <if test="dto.queryValue != null and dto.queryValue != ''">
+            and ci.name like concat('%', #{dto.queryValue}, '%')
+        </if>
     </select>
     <select id="getNoConnectionProject2" resultType="org.springblade.control.entity.ControlProjectInfo">
         select pi.id,pi.name from c_control_project_info pi WHERE pi.is_deleted = 0

+ 1 - 1
blade-service/blade-control/src/main/java/org/springblade/control/mapper/ContractReturnedInfoMapper.xml

@@ -34,7 +34,7 @@
         select * from c_contract_returned_info
         WHERE is_deleted = 0
         <if test="date != null and date != ''">
-            and DATE_FORMAT(practical_returned_time ,'%Y-%m') = #{date}
+            and DATE_FORMAT(practical_returned_time ,'%Y') = #{date}
         </if>
         and practical_returned_money is not null
     </select>

+ 2 - 1
blade-service/blade-control/src/main/java/org/springblade/control/mapper/DepartmentMonthPlanMapper.xml

@@ -24,7 +24,8 @@
                 (select COUNT(1)  from c_project_cost_budget pcb WHERE pcb.cost_type = dmp.department_type
                                                                    and pcb.task_approve = 0
                     and (pcb.plan_start_time BETWEEN dmp.plan_start_date AND dmp.plan_end_date
-                    or pcb.plan_end_time BETWEEN dmp.plan_start_date AND dmp.plan_end_date)) as 'beginPlanTotal'
+                    or pcb.plan_end_time BETWEEN dmp.plan_start_date AND dmp.plan_end_date)) as 'beginPlanTotal',
+                (select bu.name from blade_user bu WHERE bu.id = dmp.plan_designer) as 'planDesignerName'
         FROM c_department_month_plan dmp
         order by dmp.plan_start_date desc
     </select>

+ 4 - 0
blade-service/blade-control/src/main/java/org/springblade/control/mapper/ProjectCostBudgetMapper.java

@@ -75,4 +75,8 @@ public interface ProjectCostBudgetMapper extends BaseMapper<ProjectCostBudget> {
     List<User> getAllEmployees(@Param("tenantId") String tenantId,@Param("deptId") Long deptId,@Param("userId") Long userId);
 
     List<ProjectCostBudget> getPlanByDeptOrUserOrTime2(@Param("ids") Set<Long> ids, @Param("start") LocalDate start,@Param("end") LocalDate end);
+
+    List<DictInfo> getCostType();
+
+    List<DictInfo> getUnitType();
 }

+ 32 - 6
blade-service/blade-control/src/main/java/org/springblade/control/mapper/ProjectCostBudgetMapper.xml

@@ -94,28 +94,48 @@
     <select id="getUserALLPlan" resultType="org.springblade.control.vo.ProjectCostBudgetVO3">
         SELECT
             (select COUNT(1) FROM c_project_cost_budget pcb WHERE pcb.task_user = #{user}) as 'totalPlan',
-            (select COUNT(1) FROM c_project_cost_budget pcb WHERE pcb.task_user = #{user} and pcb.status = 4 ) as 'finishedPlan'
+            (select COUNT(1) FROM c_project_cost_budget pcb WHERE pcb.task_user = #{user} and pcb.status = 4 ) as 'finishedPlan',
+            (SELECT COUNT(1) from c_project_cost_budget pcb
+             WHERE pcb.task_user = #{user} and  date_add(NOW() , interval '3' DAY) > plan_end_time and  pcb.status in (2,3)) as 'riskPlan',
+            ( SELECT SUM(a) from (
+                SELECT COUNT(1) as a from c_project_cost_budget pcb
+                    WHERE pcb.task_user = #{user} and  NOW() > plan_end_time and  pcb.status in (2,3)
+                UNION ALL
+                SELECT COUNT(1) as a from c_project_cost_budget pcb
+                    WHERE pcb.task_user = #{user} and  practical_finish_time > plan_end_time and  pcb.task_approve = 1) xc) as 'postponePlan'
+
     </select>
     <select id="MonthPlanOverview" resultType="org.springblade.control.vo.ProjectCostBudgetVO3">
         select
             (select count(1) from c_project_cost_budget pcb WHERE pcb.task_user = #{user} and pcb.is_deleted = 0
                 and (pcb.plan_start_time BETWEEN #{startDate} AND #{endDate}
                 or pcb.plan_end_time BETWEEN #{startDate} AND #{endDate})) as 'totalPlan',
-            (select count(1) from c_project_cost_budget pcb WHERE pcb.task_user = #{user} and pcb.is_deleted = 0 and pcb.status in (1,2,3)
+            (select count(1) from c_project_cost_budget pcb WHERE pcb.task_user = #{user} and pcb.is_deleted = 0 and pcb.status in (2,3)
+                and (pcb.plan_start_time BETWEEN #{startDate} AND #{endDate}
+                or pcb.plan_end_time BETWEEN #{startDate} AND #{endDate})) as 'unfinishedPlan',
+            (select count(1) from c_project_cost_budget pcb WHERE pcb.task_user = #{user} and pcb.is_deleted = 0 and pcb.status in (3)
                 and (pcb.plan_start_time BETWEEN #{startDate} AND #{endDate}
-                or pcb.plan_end_time BETWEEN #{startDate} AND #{endDate})) as 'unfinishedPlan'
+                or pcb.plan_end_time BETWEEN #{startDate} AND #{endDate})) as 'cancelPlan',
+            ( SELECT SUM(a) from (
+                     SELECT COUNT(1) as a from c_project_cost_budget pcb
+                     WHERE pcb.task_user = #{user} and  NOW() > plan_end_time and  pcb.status in (2,3)
+                     and (pcb.plan_start_time BETWEEN #{startDate} AND #{endDate} or pcb.plan_end_time BETWEEN #{startDate} AND #{endDate})
+                     UNION ALL
+                     SELECT COUNT(1) as a from c_project_cost_budget pcb
+                     WHERE pcb.task_user = #{user} and  practical_finish_time > plan_end_time and  pcb.task_approve = 1
+                     and (pcb.plan_start_time BETWEEN #{startDate} AND #{endDate} or pcb.plan_end_time BETWEEN #{startDate} AND #{endDate})) xc) as 'postponePlan'
 
     </select>
     <select id="postponePlan" resultType="org.springblade.control.vo.ProjectCostBudgetVO3">
         select pcb.id,pcb.plan_task_desc,pcb.plan_end_time,
                (select cpi.name from c_control_project_info cpi WHERE cpi.id = pcb.project_id) as "projectName"
-        from c_project_cost_budget pcb where pcb.task_user = #{user} and pcb.is_deleted = 0 and pcb.plan_end_time &lt;= NOW() and pcb.status in (1,2,3)
+        from c_project_cost_budget pcb where pcb.task_user = #{user} and pcb.is_deleted = 0 and date_add(NOW() , interval '3' DAY) > pcb.plan_end_time and pcb.status in (2,3)
     </select>
     <select id="MonthOfYearPlanOverview" resultType="org.springblade.control.entity.ProjectCostBudget">
         select pcb.*
         from c_project_cost_budget pcb
         where pcb.task_user = #{user} and pcb.is_deleted = 0
-            and DATE_FORMAT(pcb.plan_start_time,'%Y') = #{year} or DATE_FORMAT(pcb.plan_end_time,'%Y') = #{year}
+            and (DATE_FORMAT(pcb.plan_start_time,'%Y') = #{year} or DATE_FORMAT(pcb.plan_end_time,'%Y') = #{year})
     </select>
     <select id="getPostMoney" resultType="java.lang.Integer">
         select dict_value
@@ -188,7 +208,7 @@
         from c_project_cost_budget pcb
         WHERE pcb.is_deleted = 0 and pcb.task_approve = 1
         <if test="date != null and date != ''">
-            and DATE_FORMAT(pcb.plan_start_time ,'%Y-%m') = #{date}
+            and DATE_FORMAT(pcb.plan_start_time ,'%Y') = #{date}
         </if>
     </select>
     <select id="getPlanByDeptOrUserOrTime" resultType="org.springblade.control.entity.ProjectCostBudget">
@@ -220,6 +240,12 @@
             #{id}
         </foreach>
     </select>
+    <select id="getCostType" resultType="org.springblade.control.entity.DictInfo">
+        select * from c_dict_info WHERE code = 'cost_type' order by sort
+    </select>
+    <select id="getUnitType" resultType="org.springblade.control.entity.DictInfo">
+        select * from c_dict_info WHERE code = 'unit_type' order by sort
+    </select>
 
 
 </mapper>

+ 4 - 0
blade-service/blade-control/src/main/java/org/springblade/control/service/IProjectCostBudgetService.java

@@ -71,4 +71,8 @@ public interface IProjectCostBudgetService extends BaseService<ProjectCostBudget
     List<ProjectCostBudget> getPlanPracticalCostByMonth(String date);
 
     PlanFinishedRatioVO planFinishedRatio(Long deptId, Long userId, String start, String end);
+
+    List<DictInfo> getCostType();
+
+    List<DictInfo> getUnitType();
 }

+ 1 - 0
blade-service/blade-control/src/main/java/org/springblade/control/service/IProjectInfoService.java

@@ -42,4 +42,5 @@ public interface IProjectInfoService extends BaseService<ControlProjectInfo> {
     List<ControlProjectInfo> listByYear(int year);
 
     List<User> getImplementUser();
+
 }

+ 33 - 11
blade-service/blade-control/src/main/java/org/springblade/control/service/impl/AnnualBudgetServiceImpl.java

@@ -339,13 +339,27 @@ public class AnnualBudgetServiceImpl extends BaseServiceImpl<AnnualBudgetMapper,
         if (vo3.getAnnualContractTarget() == null || vo3.getAnnualContractTarget().compareTo(BigDecimal.ZERO) == 0 || vo3.getYearReturned().compareTo(BigDecimal.ZERO) == 0){
             vo3.setContractSchedule(0);
         }else {
-            vo3.setContractSchedule(vo3.getYearReturned().divide(vo3.getAnnualContractTarget(),2,BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).intValue());
+            int value = vo3.getYearReturned().divide(vo3.getAnnualContractTarget(), 2, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).intValue();
+            if (value < 0){
+                value = 0;
+            }
+            if (value > 100){
+                value = 100;
+            }
+            vo3.setContractSchedule(value);
         }
         //利润进度统计
         if (vo3.getAnnualProfitTarget() == null || vo3.getAnnualProfitTarget().compareTo(BigDecimal.ZERO) == 0 || vo3.getYearProfit().compareTo(BigDecimal.ZERO) == 0){
             vo3.setProfitSchedule(0);
         }else {
-            vo3.setProfitSchedule(vo3.getYearProfit().divide(vo3.getAnnualProfitTarget(),2,BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).intValue());
+            int value = vo3.getYearProfit().divide(vo3.getAnnualProfitTarget(), 2, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).intValue();
+            if (value < 0){
+                value = 0;
+            }
+            if (value > 100){
+                value = 100;
+            }
+            vo3.setProfitSchedule(value);
         }
         return vo3;
     }
@@ -458,6 +472,8 @@ public class AnnualBudgetServiceImpl extends BaseServiceImpl<AnnualBudgetMapper,
         }
         //获取当月所有计划,和计划工资
         List<ProjectCostBudgetVO2> planByMonth = budgetService.getPlanByMonth(date);
+        planByMonth = planByMonth.stream().filter(l->l.getPlanCountMoney() != null).collect(Collectors.toList());
+        planByMonth = planByMonth.stream().filter(l->new BigDecimal(0).compareTo(l.getPlanCountMoney()) != 0).collect(Collectors.toList());
         if (planByMonth != null && planByMonth.size() > 0) {
             List<DeptMonthPlanRatioVO> vos = new ArrayList<>();
             //月计划包含的项目
@@ -500,12 +516,18 @@ public class AnnualBudgetServiceImpl extends BaseServiceImpl<AnnualBudgetMapper,
                 //设置投入比
                 if (new BigDecimal(0).compareTo(businessCount) != 0){
                     vo.setBusinessRatio(business.divide(businessCount, 2, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).intValue() + "%");
+                }else {
+                    vo.setBusinessRatio("0%");
                 }
                 if (new BigDecimal(0).compareTo(devCount) != 0) {
                     vo.setDevRatio(dev.divide(devCount, 2, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).intValue() + "%");
+                }else {
+                    vo.setDevRatio("0%");
                 }
                 if (new BigDecimal(0).compareTo(maintainCount) != 0) {
                     vo.setMaintainRatio(maintain.divide(maintainCount, 2, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).intValue() + "%");
+                }else {
+                    vo.setMaintainRatio("0%");
                 }
                 //插入结果集
                 vos.add(vo);
@@ -571,17 +593,17 @@ public class AnnualBudgetServiceImpl extends BaseServiceImpl<AnnualBudgetMapper,
      */
     @Override
     public List<ProjectIncomeCostRatioVO> portalProjectCostRatio(String date) {
-        if ("汇总所有".equals(date)){
-            date = "";
-        }
+//        if ("汇总所有".equals(date)){
+//            date = "";
+//        }
         //获取项目列表
-        List<ControlProjectInfo> list = projectInfoService.list();
+        List<ControlProjectInfo> list = projectInfoService.listByYear(Integer.parseInt(date.substring(0,4)));
         if (list == null || list.size() <= 0){
             return null;
         }
         List<ProjectIncomeCostRatioVO> vos = new ArrayList<>();
-        //按获取闭环任务,根据项目分组
-        List<ProjectCostBudget> costByMonth = budgetService.getPlanPracticalCostByMonth(date);
+        //按获取闭环任务,根据项目分组
+        List<ProjectCostBudget> costByMonth = budgetService.getPlanPracticalCostByMonth(date.substring(0,4));
         if (costByMonth == null || costByMonth.size() <= 0){
             //没有闭环任务,为每个项目设置为0
             for (ControlProjectInfo info : list) {
@@ -617,13 +639,13 @@ public class AnnualBudgetServiceImpl extends BaseServiceImpl<AnnualBudgetMapper,
             date = "";
         }
         //获取项目列表
-        List<ControlProjectInfo> list = projectInfoService.list();
+        List<ControlProjectInfo> list = projectInfoService.listByYear(Integer.parseInt(date.substring(0,4)));
         if (list == null || list.size() <= 0){
             return null;
         }
         //获取所有回款,根据项目分组
         List<ProjectIncomeCostRatioVO> vos = new ArrayList<>();
-        List<ContractReturnedInfo> returnedByMonth = returnedInfoService.getProjectReturnedByMonth(date);
+        List<ContractReturnedInfo> returnedByMonth = returnedInfoService.getProjectReturnedByMonth(date.substring(0,4));
         if (returnedByMonth == null || returnedByMonth.size() <= 0){
             //没有闭环任务,为每个项目设置为0
             for (ControlProjectInfo info : list) {
@@ -647,7 +669,7 @@ public class AnnualBudgetServiceImpl extends BaseServiceImpl<AnnualBudgetMapper,
                     big = big.add(returnedInfo.getPracticalReturnedMoney());
                 }
             }
-            vo.setProjectCost(big.intValue());
+            vo.setProjectIncome(big.intValue());
             vos.add(vo);
         }
         return vos;

+ 3 - 0
blade-service/blade-control/src/main/java/org/springblade/control/service/impl/DepartmentMonthPlanServiceImpl.java

@@ -19,6 +19,7 @@ import org.springblade.core.log.exception.ServiceException;
 import org.springblade.core.mp.base.BaseServiceImpl;
 import org.springblade.core.mp.support.Query;
 import org.springblade.core.secure.BladeUser;
+import org.springblade.core.secure.utils.SecureUtil;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -67,6 +68,8 @@ public class DepartmentMonthPlanServiceImpl extends BaseServiceImpl<DepartmentMo
         //获取部门名称
         String departmentName = baseMapper.getDepartmentName(plan.getDepartmentType());
         //新增部门月计划,并且设置名称和起止日期,制定人
+        Long userId = SecureUtil.getUserId();
+        plan.setPlanDesigner(userId);
         String planDate = plan.getPlanDate();
         String[] date = planDate.split("-");
         plan.setPlanName(date[0]+"年"+date[1]+"月"+departmentName+"预算计划");

+ 26 - 0
blade-service/blade-control/src/main/java/org/springblade/control/service/impl/ProjectCostBudgetServiceImpl.java

@@ -702,6 +702,32 @@ public class ProjectCostBudgetServiceImpl extends BaseServiceImpl<ProjectCostBud
         return null;
     }
 
+    /**
+     * 查询预览-费用分类列表
+     */
+    @Override
+    public List<DictInfo> getCostType() {
+        List<DictInfo> costType = baseMapper.getCostType();
+        DictInfo dictInfo = new DictInfo();
+        dictInfo.setDictName("所有");
+        dictInfo.setDictValue(-1);
+        costType.add(dictInfo);
+        return costType;
+    }
+
+    /**
+     * 查询预览-单位列表
+     */
+    @Override
+    public List<DictInfo> getUnitType() {
+        List<DictInfo> unitType = baseMapper.getUnitType();
+        DictInfo dictInfo = new DictInfo();
+        dictInfo.setDictName("所有");
+        dictInfo.setDictValue(-1);
+        unitType.add(dictInfo);
+        return unitType;
+    }
+
     /**
      * 统计一行的几个总金额
      */

+ 6 - 0
blade-service/blade-control/src/main/java/org/springblade/control/service/impl/ProjectCostBudgetStatsServiceImpl.java

@@ -117,6 +117,12 @@ public class ProjectCostBudgetStatsServiceImpl extends BaseServiceImpl<ProjectCo
         ProjectCostBudgetStatsVO vo = new ProjectCostBudgetStatsVO();
         ControlProjectInfo projectInfo = projectInfoService.getById(costBudget.getProjectId());
         vo.setProjectName(projectInfo.getName());
+        if (costBudget.getCostType() != null && costBudget.getCostType() == -1){
+            costBudget.setCostType(null);
+        }
+        if (costBudget.getUnitType() != null && costBudget.getUnitType() == -1){
+            costBudget.setUnitType(null);
+        }
         List<ProjectCostBudgetVO> list = budgetService.budgetList(costBudget);
         BigDecimal bigDecimal = new BigDecimal("0");
         for (ProjectCostBudgetVO l : list) {

+ 5 - 1
blade-service/blade-control/src/main/java/org/springblade/control/service/impl/ProjectInfoServiceImpl.java

@@ -108,7 +108,7 @@ public class ProjectInfoServiceImpl extends BaseServiceImpl<ProjectInfoMapper, C
             throw new ServiceException("项目存在合同,不能删除");
         }
         List<ProjectCostBudget> list = budgetService.list(new LambdaQueryWrapper<ProjectCostBudget>().eq(ProjectCostBudget::getProjectId, id));
-        if (list != null || list.size() > 0){
+        if (list != null && list.size() > 0){
             throw new ServiceException("项目已经做了预算,不能删除");
         }
         baseMapper.deleteById(id);
@@ -206,6 +206,10 @@ public class ProjectInfoServiceImpl extends BaseServiceImpl<ProjectInfoMapper, C
         return null;
     }
 
+    /**
+     * 获取当年的项目
+     * @return
+     */
     @Override
     public List<ControlProjectInfo> listByYear(int year) {
         return baseMapper.listByYear(year);

+ 30 - 1
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/WbsParamController.java

@@ -12,6 +12,8 @@ import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiParam;
 import lombok.AllArgsConstructor;
+import org.springblade.common.utils.BaseUtils;
+import org.springblade.core.mp.base.BaseService;
 import org.springblade.core.mp.support.Condition;
 import org.springblade.core.mp.support.Query;
 import org.springblade.core.tool.api.R;
@@ -32,6 +34,8 @@ import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.web.bind.annotation.*;
 import springfox.documentation.annotations.ApiIgnore;
 
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
 import java.util.*;
 import java.util.stream.Collectors;
 
@@ -82,6 +86,10 @@ public class WbsParamController {
     public R saveOrUpdateBatch(@RequestBody ParamBean pb) {
         try {
             List<WbsParamBean> wps = pb.getWps();
+            String names=checkRepeat(wps);
+            if(names!=null){
+                return R.success("存在重复参数【"+names+"】,删除多余项再保存");
+            }
             /*执行顺序,删>增>改*/
             if (Func.isNotEmpty(pb.getDelIds())) {
                 List<Long> delIds = pb.getDelIds().stream().filter(Func::isNotEmpty).collect(Collectors.toList());
@@ -187,6 +195,16 @@ public class WbsParamController {
 
     }
 
+    public String checkRepeat( List<WbsParamBean> wps){
+        if(Func.isNotEmpty(wps)){
+           List<List<WbsParamBean>> target=wps.stream().collect(Collectors.groupingBy(WbsParamBean::getK)).values().stream().filter(l->l.size()>1).collect(Collectors.toList());
+           if(target.size()>0){
+               return target.stream().map(l->l.get(0).getName()).collect(Collectors.joining(","));
+           }
+        }
+        return null;
+    }
+
     /**
      * /**
      * 删除
@@ -239,6 +257,7 @@ public class WbsParamController {
     @ApiOperation(value = "节点参数列表", notes = "节点参数列表")
     @GetMapping("/list")
     public R<List<WbsParamBean>> list3(@ApiParam(value = "节点id", required = true) Long wbsId) {
+        this.service.duplicate(wbsId);
         List<WbsParam> data = this.service.list(Wrappers.<WbsParam>lambdaQuery()
                 .select(WbsParam::getId, WbsParam::getName, WbsParam::getK, WbsParam::getV, WbsParam::getRemark, WbsParam::getNodeId, WbsParam::getProjectId)
                 .eq(WbsParam::getNodeId, wbsId)
@@ -410,7 +429,7 @@ public class WbsParamController {
         try {
             StopWatch stopWatch = new StopWatch();
             stopWatch.start("节点参数查重及删除");
-            List<Map<String, Object>> mapList = this.jdbcTemplate.queryForList("select  node_id nodeId,k,count(*) num from m_wbs_param  where is_deleted=0 and type=1 GROUP BY node_id,k HAVING count(*)>2");
+            List<Map<String, Object>> mapList = this.jdbcTemplate.queryForList("select  node_id nodeId,k,count(*) num from m_wbs_param  where is_deleted=0 and type=1 GROUP BY node_id,k HAVING count(*)>1");
             if (!mapList.isEmpty()) {
                 List<WbsParam> list = this.service.list(Wrappers.<WbsParam>lambdaQuery().in(WbsParam::getNodeId, mapList.stream().map(m -> m.get("nodeId")).collect(Collectors.toList())));
                 List<Long> removeWpIds = new ArrayList<>();
@@ -437,6 +456,9 @@ public class WbsParamController {
                 System.out.println("待删除参数" + removeWpIds.size() + "个");
                 System.out.println("待删除中间关联" + removeMapingIds.size() + "个");
                 System.out.println("待删除公式" + removeFormulaIds.size() + "个");
+//                    batchDel(this.service,removeWpIds);
+//                    batchDel(this.elementFormulaMappingService,removeMapingIds);
+//                    batchDel(this.formulaService,removeFormulaIds);
                 Map<String, Integer> result = new HashMap<>();
                 result.put("查找到重复参数", list.size());
                 result.put("待删除参数", removeWpIds.size());
@@ -453,4 +475,11 @@ public class WbsParamController {
         return R.fail("执行异常");
     }
 
+    public <T> void  batchDel(BaseService<T> sv,List<Long> list){
+        if(sv!=null&&Func.isNotEmpty(list)) {
+            List<List<Long>> removeWpIdsList = BaseUtils.splitList(list, 1000);
+            removeWpIdsList.forEach(sv::deleteLogic);
+        }
+    }
+
 }

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

@@ -29,5 +29,6 @@ public interface IWbsParamService extends BaseService<WbsParam> {
     List<WbsParam> findByNodeId(Long nodeId);
 
     List<WbsTreeContract> chain(Long contractId, Long id, Long pkId, WbsTreeContract wbsTreeContract);
-    public List<WbsTreeContract> tracing(@NotNull Long pkeyId);
+     List<WbsTreeContract> tracing(@NotNull Long pkeyId);
+    void duplicate(Long nodeId);
 }

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

@@ -1,11 +1,13 @@
 package org.springblade.manager.service.impl;
 
+import cn.hutool.core.date.StopWatch;
 import cn.hutool.log.StaticLog;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.mixsmart.utils.CustomFunction;
 import com.mixsmart.utils.StringUtils;
 import lombok.AllArgsConstructor;
 import org.springblade.common.utils.BaseUtils;
+import org.springblade.core.mp.base.BaseService;
 import org.springblade.core.mp.base.BaseServiceImpl;
 import org.springblade.core.tool.api.R;
 import org.springblade.core.tool.utils.Func;
@@ -14,9 +16,12 @@ import org.springblade.manager.entity.WbsParam;
 import org.springblade.manager.entity.WbsTreeContract;
 import org.springblade.manager.entity.WbsTreePrivate;
 import org.springblade.manager.mapper.WbsParamMapper;
+import org.springblade.manager.service.IElementFormulaMappingService;
+import org.springblade.manager.service.IFormulaService;
 import org.springblade.manager.service.IWbsParamService;
 import org.springblade.manager.service.IWbsTreeContractService;
 import org.springframework.cache.annotation.Cacheable;
+import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -33,6 +38,10 @@ import java.util.stream.Collectors;
 @AllArgsConstructor
 public class WbsParamServiceImpl extends BaseServiceImpl<WbsParamMapper, WbsParam> implements IWbsParamService {
     private final IWbsTreeContractService treeContractService;
+    private final IElementFormulaMappingService elementFormulaMappingService;
+    private final IFormulaService formulaService;
+    private final JdbcTemplate jdbcTemplate;
+
     private static final String NOT_SET = "还未配置提名规则";
     /**
      * 文件题名
@@ -44,7 +53,6 @@ public class WbsParamServiceImpl extends BaseServiceImpl<WbsParamMapper, WbsPara
     public String createFileTitle(Long nodeId, Long contractId, WbsTreeContract wbsTreeContract) {
         if (BaseUtils.isNotNull(nodeId, contractId)) {
             StaticLog.info("获取节点{}文件题名", nodeId);
-          //  List<WbsTreeContract> nodes = chain(contractId, nodeId, wbsTreeContract.getPKeyId(), wbsTreeContract);
             List<WbsTreeContract> nodes = tracing(wbsTreeContract.getPKeyId());
             if (Func.isNotEmpty(nodes)) {
                 /*优先取私有*/
@@ -82,6 +90,76 @@ public class WbsParamServiceImpl extends BaseServiceImpl<WbsParamMapper, WbsPara
         return new ArrayList<>();
     }
 
+    @Override
+    public void duplicate(Long nodeId) {
+        try {
+            StopWatch stopWatch = new StopWatch();
+            stopWatch.start("节点参数查重及删除");
+            List<Map<String, Object>> mapList = this.jdbcTemplate.queryForList("select  node_id nodeId,k,count(*) num from m_wbs_param  where is_deleted=0 and type=1 and node_id="+nodeId+" GROUP BY node_id,k HAVING count(*)>1");
+            if (!mapList.isEmpty()) {
+                List<WbsParam> list = this.list(Wrappers.<WbsParam>lambdaQuery().in(WbsParam::getNodeId, mapList.stream().map(m -> m.get("nodeId")).collect(Collectors.toList())));
+                List<Long> removeWpIds = new ArrayList<>();
+                List<Long> removeMapingIds = new ArrayList<>();
+                List<Long> removeFormulaIds = new ArrayList<>();
+                Map<Long, Map<String, List<WbsParam>>> group = list.stream().collect(Collectors.groupingBy(WbsParam::getNodeId, LinkedHashMap::new, Collectors.groupingBy(WbsParam::getK)));
+                group.values().forEach(m -> {
+                    m.forEach((k, v) -> {
+                        List<Map<String, Object>> relationMap = this.jdbcTemplate.queryForList("select a.id paramId,b.id mappingId,b.formula_id formulaId from m_wbs_param a join m_element_formula_mapping b on a.id=b.param_id where b.scope=35 and a.id in(" + v.stream().map(WbsParam::getId).map(String::valueOf).collect(Collectors.joining("','", "'", "'")) + ") order by  b.update_time desc");
+                        if (!relationMap.isEmpty()) {
+                            Object id = relationMap.get(0).get("paramId");
+                            removeWpIds.addAll(v.stream().map(WbsParam::getId).filter(eId -> !StringUtils.isNotEquals(id, eId)).collect(Collectors.toList()));
+                            /*同一道工序下,一个节点参数可能会关联多个元素,除了保留参数关联的以外全部添加到待删除列表*/
+                            relationMap.stream().filter(x -> StringUtils.isNotEquals(x.get("paramId"), id)).forEach(e -> {
+                                removeMapingIds.add(Long.parseLong(e.get("mappingId").toString()));
+                                removeFormulaIds.add(Long.parseLong(e.get("formulaId").toString()));
+                            });
+                        } else {
+                            removeWpIds.addAll(v.stream().skip(1).map(WbsParam::getId).collect(Collectors.toList()));
+                        }
+                    });
+                });
+                System.out.println("查找到重复参数" + list.size() + "个");
+                System.out.println("待删除参数" + removeWpIds.size() + "个");
+                System.out.println("待删除中间关联" + removeMapingIds.size() + "个");
+                System.out.println("待删除公式" + removeFormulaIds.size() + "个");
+                Map<String, Integer> result = new HashMap<>();
+                result.put("查找到重复参数", list.size());
+                result.put("待删除参数", removeWpIds.size());
+                result.put("待删除中间关联", removeMapingIds.size());
+                result.put("待删除公式", removeFormulaIds.size());
+//                if(removeWpIds.size()>0) {
+//                    this.deleteLogic(removeWpIds);
+//                }
+//                if(removeMapingIds.size()>0){
+//                    this.elementFormulaMappingService.deleteLogic(removeMapingIds);
+//                }
+//                if(removeFormulaIds.size()>0){
+//                    this.formulaService.deleteLogic(removeFormulaIds);
+//                }
+                if(removeWpIds.size()>0) {
+                    batchDel(this,removeWpIds);
+                }
+                if(removeMapingIds.size()>0){
+                    batchDel(this.elementFormulaMappingService,removeMapingIds);
+                }
+                if(removeFormulaIds.size()>0){
+                    batchDel(this.formulaService,removeFormulaIds);
+                }
+                stopWatch.stop();
+                Long totalTime = stopWatch.getTotalTimeMillis();
+                StaticLog.info("公式执行用时:{},删除情况:{}", totalTime,result);
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+    public <T> void  batchDel(BaseService<T> sv, List<Long> list){
+        if(sv!=null&&Func.isNotEmpty(list)) {
+            List<List<Long>> removeWpIdsList = BaseUtils.splitList(list, 1000);
+            removeWpIdsList.forEach(sv::deleteLogic);
+        }
+    }
+
     @Override
     public List<WbsParam> findByNodeId(Long nodeId) {
         if (nodeId != null) {

+ 45 - 38
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreePrivateServiceImpl.java

@@ -41,6 +41,8 @@ import org.springblade.system.cache.ParamCache;
 import org.springframework.beans.BeanUtils;
 import org.springframework.jdbc.core.BeanPropertyRowMapper;
 import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.SqlParameterValue;
+import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Service;
@@ -50,9 +52,12 @@ import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
+import java.sql.Timestamp;
+import java.sql.Types;
 import java.time.LocalDateTime;
 import java.io.*;
 import java.util.*;
+import java.util.function.BinaryOperator;
 import java.util.function.Function;
 import java.util.stream.Collectors;
 
@@ -897,7 +902,7 @@ public class WbsTreePrivateServiceImpl extends BaseServiceImpl<WbsTreePrivateMap
 
     @Override
     public boolean syncNodeParam(String projectId, String pKeyId) {
-        projectId = null;//暂不执行
+       // projectId = null;//暂不执行
         if (StringUtils.isNotEmpty(projectId) && StringUtils.isNotEmpty(pKeyId)) {
             ProjectInfo projectInfo = projectInfoMapper.selectById(projectId);
             //当前选择同步的节点信息
@@ -905,26 +910,31 @@ public class WbsTreePrivateServiceImpl extends BaseServiceImpl<WbsTreePrivateMap
             if (selectNodeNow == null) {
                 throw new ServiceException("未获取到当前选择同步的节点信息,请联系管理员");
             }
-
-            //获取当前选择的节点与它所有子节点
-            List<WbsTreePrivate> selectNodeAndChildNodes = Optional.ofNullable(this.getChildNodes(selectNodeNow)).orElse(new ArrayList<>());
-            selectNodeAndChildNodes.add(selectNodeNow);
-            List<Long> privateNodeIds = selectNodeAndChildNodes.stream().map(WbsTreePrivate::getId).collect(Collectors.toList());
-            List<Long> privateNodePKeyIds = selectNodeAndChildNodes.stream().map(WbsTreePrivate::getPKeyId).collect(Collectors.toList());
             if (("private").equals(projectInfo.getReferenceWbsTemplateType())) {
                 // ---------私有才需要引用同步---------节点参数nodeId绑定的是m_wbs_private 的p_key_id  ;同节点下mapping scope=35 共用一个formula;也就是说同一个节点下的同一个element都指向同一个公式
                 /*全部查出来,pkeyId-id-paramId  source:key  最后比较;同节点相同k的参数都指向同一个公式,mapping 对象除了elementId不一样其它都一样*/
                 /*同步的范围不一定是整棵树,可以是局部分支*/
                 //获取当前私有引用模板的根节点信息
-                WbsTreePrivate treePrivateRootNode = baseMapper.selectOne(Wrappers.<WbsTreePrivate>query().lambda()
-                        .select(WbsTreePrivate::getWbsId, WbsTreePrivate::getProjectId)
+                WbsTreePrivate sourceRootNode = baseMapper.selectOne(Wrappers.<WbsTreePrivate>query().lambda().select(WbsTreePrivate::getWbsId, WbsTreePrivate::getProjectId)
                         .eq(WbsTreePrivate::getPKeyId, selectNodeNow.getWbsId()).eq(WbsTreePrivate::getParentId, 0L).eq(WbsTreePrivate::getStatus, 1).eq(WbsTreePrivate::getType, 1));
-                List<Map<String, Object>> sourceListMap = this.jdbcTemplate.queryForList("select a.id,a.k,a.v,a.remark,a.node_id nodeId ,b.id privateId,a.update_time updateTime  " +
-                        "from m_wbs_param a join m_wbs_tree_private b on a.node_id = b.p_key_id   where  b.project_id in(?) and b.id in(?) and a.is_deleted=0  and a.type=1 ", treePrivateRootNode.getProjectId(), privateNodeIds.stream().map(Object::toString).collect(Collectors.joining(",")));
-                List<Map<String, Object>> distListMap = this.jdbcTemplate.queryForList("select a.id,a.k,a.v,a.remark,a.node_id nodeId ,b.id privateId,a.update_time updateTime  " +
-                        "from m_wbs_param a join m_wbs_tree_private b on a.node_id = b.p_key_id   where  b.project_id in(?) and b.p_key_id in(?) and a.is_deleted=0  and a.type=1 ", projectId, privateNodePKeyIds.stream().map(Object::toString).collect(Collectors.joining(",")));
-                Map<String, Map<String, Object>> sourceMap = sourceListMap.stream().collect(Collectors.toMap(m -> m.get("privateId").toString() + m.get("k"), m -> m));
-                Map<String, Map<String, Object>> distMap = distListMap.stream().collect(Collectors.toMap(m -> m.get("privateId").toString() + m.get("k"), m -> m));
+
+                List<WbsTreePrivate> selectNodeAndChildNodes = Optional.ofNullable(this.getChildNodes(selectNodeNow)).orElse(new ArrayList<>());
+                selectNodeAndChildNodes.add(selectNodeNow);
+                List<Long> sourceNodeIds = jdbcTemplate.queryForList("select p_key_id from m_wbs_tree_private where id in("+selectNodeAndChildNodes.stream().map(WbsTreePrivate::getId).map(Object::toString).collect(Collectors.joining(","))+") and  is_deleted=0 and project_id ="+sourceRootNode.getProjectId(),Long.class);
+                List<Long> distNodeIds = selectNodeAndChildNodes.stream().map(WbsTreePrivate::getPKeyId).collect(Collectors.toList());
+                List<Map<String, Object>> sourceListMap = this.jdbcTemplate.queryForList("select a.id,a.name ,a.k,a.v,a.remark,a.node_id nodeId ,b.id privateId,a.update_time updateTime  " +
+                        "from m_wbs_param a join m_wbs_tree_private b on a.node_id = b.p_key_id   where  b.project_id in(?) and b.p_key_id in("+sourceNodeIds.stream().map(Object::toString).collect(Collectors.joining(","))+") and a.is_deleted=0  and a.type=1 ",  Long.parseLong(sourceRootNode.getProjectId()));
+                List<Map<String, Object>> distListMap = this.jdbcTemplate.queryForList("select a.id,a.name,a.k,a.v,a.remark,a.node_id nodeId ,b.id privateId,a.update_time updateTime  " +
+                        "from m_wbs_param a join m_wbs_tree_private b on a.node_id = b.p_key_id   where  b.project_id in(?) and b.p_key_id in("+distNodeIds.stream().map(Object::toString).collect(Collectors.joining(","))+") and a.is_deleted=0  and a.type=1 ", Long.parseLong(projectId));
+
+                /*存在多个同名参数;保留日期最新那个参数*/
+                BinaryOperator<Map<String,Object>> mapBinaryOperator= (m1, m2) -> {
+                    LocalDateTime sldt = ((Timestamp)m1.get("updateTime")).toLocalDateTime();
+                    LocalDateTime tldt = ((Timestamp)m2.get("updateTime")).toLocalDateTime();
+                    return sldt.isAfter(tldt)?m1:m2;
+                };
+                Map<String, Map<String, Object>> sourceMap = sourceListMap.stream().collect(Collectors.toMap(m -> m.get("privateId").toString() + m.get("k"), m -> m,mapBinaryOperator));
+                Map<String, Map<String, Object>> distMap = distListMap.stream().collect(Collectors.toMap(m -> m.get("privateId").toString() + m.get("k"), m -> m,mapBinaryOperator));
                 /*比较的结果*/
                 Map<String, Map<String, Object>> updateMap = new HashMap<>();
                 Map<String, Map<String, Object>> insertMap = new HashMap<>();
@@ -934,8 +944,8 @@ public class WbsTreePrivateServiceImpl extends BaseServiceImpl<WbsTreePrivateMap
                         Map<String, Object> u = distMap.get(k);
                         String t = Func.toStr(u.get("v"));
                         if (!s.equals(t)) {
-                            LocalDateTime sldt = LocalDateTime.parse(Func.toStr(v.get("updateTime")));
-                            LocalDateTime tldt = LocalDateTime.parse(Func.toStr(u.get("updateTime")));
+                            LocalDateTime sldt = ((Timestamp)v.get("updateTime")).toLocalDateTime();
+                            LocalDateTime tldt = ((Timestamp)u.get("updateTime")).toLocalDateTime();
                             /*假如内容不一样,且模版最后更新时间更晚,则覆盖*/
                             if (sldt.isAfter(tldt)) {
                                 u.put("v", s);
@@ -959,7 +969,7 @@ public class WbsTreePrivateServiceImpl extends BaseServiceImpl<WbsTreePrivateMap
                 }
                 List<WbsParam> insertList = new ArrayList<>();
                 if (!insertMap.isEmpty()) {
-                    List<WbsTreePrivate> targetList = Optional.ofNullable(this.list(Wrappers.<WbsTreePrivate>lambdaQuery().in(WbsTreePrivate::getId, insertMap.values().stream().map(m -> m.get("privateId")).collect(Collectors.toList())))).orElse(new ArrayList<>());
+                    List<WbsTreePrivate> targetList = Optional.ofNullable(this.list(Wrappers.<WbsTreePrivate>lambdaQuery().eq(WbsTreePrivate::getProjectId,projectId).in(WbsTreePrivate::getId, insertMap.values().stream().map(m -> m.get("privateId")).collect(Collectors.toList())))).orElse(new ArrayList<>());
                     targetList.forEach(e -> {
                         Map<String, Object> kmp = insertMap.get(e.getId().toString());
                         if (kmp != null) {
@@ -998,32 +1008,26 @@ public class WbsTreePrivateServiceImpl extends BaseServiceImpl<WbsTreePrivateMap
                                 "select c.e_name as name ,c.id,a.p_key_id pKeyId from m_wbs_tree_private a " +
                                         "inner join m_wbs_tree_private b on (a.id=b.parent_id and a.wbs_id=b.wbs_id) " +
                                         "inner join m_wbs_form_element c on  b.init_table_id=c.f_id " +
-                                        "where  b.project_id=" + projectId + " and a.p_key_id in(?)  and b.is_deleted=0 and c.is_deleted=0 ", nodeIds);
+                                        "where  b.project_id=" + projectId + " and a.p_key_id in("+String.join(",",nodeIds)+")  and b.is_deleted=0 and c.is_deleted=0 ");
 
                         Map<String, List<Map<String, Object>>> groupElementNode = listMaps.stream().collect(Collectors.groupingBy(e -> Func.toStr(e.get("pKeyId"))));
                         List<ElementFormulaMapping> insertEfm = new ArrayList<>();
                         insertList.forEach(p -> {
                             List<Map<String, Object>> elementMap = groupElementNode.get(p.getNodeId().toString());
                             Formula formula = insertFormulaMap.get(p.getId());
-                            elementMap.forEach(m -> {
-                                if (com.mixsmart.utils.StringUtils.handleNull(m.get("name")).contains(p.getName())) {
-                                    /*匹配名称,且该元素没有绑定任何节点参数公式*/
-//                                    if (longList.stream().noneMatch(k -> com.mixsmart.utils.StringUtils.isEquals(k, m.get("id")))) {
-//                                        ElementFormulaMapping efm = new ElementFormulaMapping();
-//                                        efm.setScope(FormulaBean.PARAM);
-//                                        efm.setParamId(e.getId());
-//                                        efm.setElementId(Long.parseLong(m.get("id").toString()));
-//                                        efm.setFormulaId(finalFormula.getId());
-//                                        this.elementFormulaMappingService.save(efm);
-//                                    }
-                                    ElementFormulaMapping efm = new ElementFormulaMapping();
-                                    efm.setScope(FormulaBean.PARAM);
-                                    efm.setParamId(p.getId());
-                                    efm.setElementId(Long.parseLong(m.get("id").toString()));
-                                    efm.setFormulaId(formula.getId());
-                                    insertEfm.add(efm);
-                                }
-                            });
+                           if(Func.isNotEmpty(elementMap)) {
+                               elementMap.forEach(m -> {
+                                   if (com.mixsmart.utils.StringUtils.handleNull(m.get("name")).contains(p.getName())) {
+                                       /*匹配名称,且该元素没有绑定任何节点参数公式*/
+                                       ElementFormulaMapping efm = new ElementFormulaMapping();
+                                       efm.setScope(FormulaBean.PARAM);
+                                       efm.setParamId(p.getId());
+                                       efm.setElementId(Long.parseLong(m.get("id").toString()));
+                                       efm.setFormulaId(formula.getId());
+                                       insertEfm.add(efm);
+                                   }
+                               });
+                           }
                         });
                         if (insertFormulaMap.size() > 0) {
                             this.formulaService.saveBatch(insertFormulaMap.values(), 1000);
@@ -1039,6 +1043,9 @@ public class WbsTreePrivateServiceImpl extends BaseServiceImpl<WbsTreePrivateMap
         return false;
     }
 
+
+
+
     @Override
     public R<String> syncPrivateProjectFormula(Long projectId, Long pKeyId) {
         if (projectId != null && pKeyId != null) {