瀏覽代碼

Merge branch 'master' of http://47.110.251.215:3000/java_org/bladex

huangtf 2 年之前
父節點
當前提交
fecb6dce6f
共有 55 個文件被更改,包括 2087 次插入1134 次删除
  1. 6 0
      blade-service-api/blade-control-api/src/main/java/org/springblade/control/entity/ControlContractInfo.java
  2. 2 0
      blade-service-api/blade-control-api/src/main/java/org/springblade/control/vo/UserFilesInfoVO.java
  3. 4 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/dto/FormData.java
  4. 12 1
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/dto/LocalVariable.java
  5. 6 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/dto/RangeInfo.java
  6. 6 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/ExcelTab.java
  7. 2 0
      blade-service-api/blade-user-api/src/main/java/org/springblade/system/user/entity/User.java
  8. 2 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchiveOfflineVersionInfoController.java
  9. 2 2
      blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchivesAutoController.java
  10. 10 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ArchiveOfflineVersionInfoMapper.java
  11. 18 1
      blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ArchiveOfflineVersionInfoMapper.xml
  12. 2 2
      blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ArchivesAutoMapper.java
  13. 2 2
      blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ArchivesAutoMapper.xml
  14. 2 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/IArchiveOfflineVersionInfoService.java
  15. 1 1
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/IArchivesAutoService.java
  16. 176 36
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ArchiveOfflineVersionInfoServiceImpl.java
  17. 5 3
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ArchivesAutoServiceImpl.java
  18. 83 33
      blade-service/blade-business/src/main/java/org/springblade/business/controller/InformationWriteQueryController.java
  19. 1 1
      blade-service/blade-business/src/main/java/org/springblade/business/controller/MileageController.java
  20. 18 13
      blade-service/blade-business/src/main/java/org/springblade/business/feignClient/MileageClientImpl.java
  21. 5 2
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/InformationQueryMapper.xml
  22. 6 5
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/InformationQueryServiceImpl.java
  23. 1 2
      blade-service/blade-control/src/main/java/org/springblade/control/controller/CorporationInfoController.java
  24. 3 0
      blade-service/blade-control/src/main/java/org/springblade/control/mapper/AnnualBudgetMapper.java
  25. 3 0
      blade-service/blade-control/src/main/java/org/springblade/control/mapper/AnnualBudgetMapper.xml
  26. 1 1
      blade-service/blade-control/src/main/java/org/springblade/control/mapper/ProjectCostBudgetMapper.xml
  27. 5 0
      blade-service/blade-control/src/main/java/org/springblade/control/service/IProjectInfoService.java
  28. 468 376
      blade-service/blade-control/src/main/java/org/springblade/control/service/impl/AnnualBudgetServiceImpl.java
  29. 1 1
      blade-service/blade-control/src/main/java/org/springblade/control/service/impl/DictInfoServiceImpl.java
  30. 6 6
      blade-service/blade-control/src/main/java/org/springblade/control/service/impl/LogHistoryServiceImpl.java
  31. 23 4
      blade-service/blade-control/src/main/java/org/springblade/control/service/impl/ProjectCostBudgetServiceImpl.java
  32. 10 0
      blade-service/blade-control/src/main/java/org/springblade/control/service/impl/ProjectInfoServiceImpl.java
  33. 6 3
      blade-service/blade-manager/src/main/java/com/mixsmart/utils/CustomFunction.java
  34. 45 0
      blade-service/blade-manager/src/main/java/com/mixsmart/utils/FormulaUtils.java
  35. 36 24
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ContractInfoController.java
  36. 11 8
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ExcelTabController.java
  37. 133 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/FormulaController.java
  38. 7 2
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ProjectInfoController.java
  39. 1 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/TextdictInfoController.java
  40. 165 71
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/WbsParamController.java
  41. 17 28
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/WbsTreeContractController.java
  42. 1 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/TableElementConverter.java
  43. 1 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/ExcelTabMapper.xml
  44. 1 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsTreeContractMapper.xml
  45. 2 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsTreePrivateMapper.xml
  46. 1 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/IContractInfoService.java
  47. 10 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/IWbsParamService.java
  48. 226 98
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ContractInfoServiceImpl.java
  49. 225 199
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ExcelTabServiceImpl.java
  50. 40 11
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/FormulaServiceImpl.java
  51. 9 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsFormElementServiceImpl.java
  52. 42 4
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsParamServiceImpl.java
  53. 159 122
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreeContractServiceImpl.java
  54. 19 10
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreePrivateServiceImpl.java
  55. 38 56
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreeServiceImpl.java

+ 6 - 0
blade-service-api/blade-control-api/src/main/java/org/springblade/control/entity/ControlContractInfo.java

@@ -88,9 +88,15 @@ public class ControlContractInfo extends BaseEntity {
     @ApiModelProperty(value = "联系电话")
     private String addresseePhone;
 
+    @ApiModelProperty(value = "单位电话")
+    private String unitPhone;
+
     @ApiModelProperty(value = "邮寄地址")
     private String mailingAddress;
 
+    @ApiModelProperty(value = "单位地址")
+    private String unitAddr;
+
     @ApiModelProperty(value = "合同附件")
     private String contractAccessory;
 

+ 2 - 0
blade-service-api/blade-control-api/src/main/java/org/springblade/control/vo/UserFilesInfoVO.java

@@ -16,6 +16,7 @@
  */
 package org.springblade.control.vo;
 
+import com.fasterxml.jackson.annotation.JsonFormat;
 import io.swagger.annotations.ApiModelProperty;
 import org.springblade.control.entity.UserFilesInfo;
 import lombok.Data;
@@ -56,6 +57,7 @@ public class UserFilesInfoVO extends UserFilesInfo {
 	@ApiModelProperty(value = "身份证号码")
 	private String idNumber;
 
+	@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
 	@ApiModelProperty(value = "出生日期")
 	private String birthday;
 

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

@@ -18,6 +18,10 @@ import java.util.stream.Stream;
  */
 @Data
 public class FormData {
+    /**
+     * 元素id
+     */
+    private Long id;
     /**
      * 元素码:表名_字段名
      */

+ 12 - 1
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/dto/LocalVariable.java

@@ -1,7 +1,9 @@
 package org.springblade.manager.dto;
 
+import io.jsonwebtoken.lang.Objects;
 import lombok.Data;
-
+import org.springframework.util.ObjectUtils;
+import java.util.HashMap;
 import java.util.Map;
 
 /**
@@ -23,4 +25,13 @@ public class LocalVariable {
         this.formula = formula;
         this.currentMap = currentMap;
     }
+
+    public Boolean hasEmptyElementValue(){
+        @SuppressWarnings("unchecked")
+        Map<String,Object> mapE= (Map<String, Object>) currentMap.getOrDefault("E",new HashMap<>());
+        if(mapE.size()>0){
+            return mapE.values().stream().anyMatch(ObjectUtils::isEmpty);
+        }
+        return true;
+    }
 }

+ 6 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/dto/RangeInfo.java

@@ -2,6 +2,7 @@ package org.springblade.manager.dto;
 
 import com.alibaba.fastjson.annotation.JSONField;
 import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
 import org.springblade.common.utils.BaseUtils;
 import org.springblade.core.tool.utils.Func;
 
@@ -14,7 +15,12 @@ import java.util.stream.Collectors;
  * @Date 2022/9/22 17:52
  * @description TODO
  */
+@Data
 public class RangeInfo {
+
+    @ApiModelProperty( value = "方向",required = true)
+    private String direction;
+
     @ApiModelProperty(
             value = "设计值",
             required = true

+ 6 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/ExcelTab.java

@@ -119,4 +119,10 @@ public class ExcelTab extends BaseEntity {
     @ApiModelProperty(value = "html路径")
     private String templateFileUrl;
 
+    /**
+     * 实体表ID
+     */
+    @ApiModelProperty(value = "实体表ID")
+    private String tabId;
+
 }

+ 2 - 0
blade-service-api/blade-user-api/src/main/java/org/springblade/system/user/entity/User.java

@@ -17,6 +17,7 @@
 package org.springblade.system.user.entity;
 
 import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.AllArgsConstructor;
 import lombok.Data;
@@ -97,6 +98,7 @@ public class User extends TenantEntity {
      * 生日
      */
     @ApiModelProperty(value = "生日")
+    @JsonFormat
     private Date birthday;
     /**
      * 性别

+ 2 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchiveOfflineVersionInfoController.java

@@ -44,6 +44,8 @@ public class ArchiveOfflineVersionInfoController {
     @ApiOperation(value = "打包数据")
     @GetMapping("/packData")
     public R<String> packData(Long projectId) throws Exception {
+        //先获取状态,同时只能有一个项目打包
+        offlineVersionInfoService.getPackStatus();
         //异步调用自动打包上传,完成后修改数据库信息
         offlineVersionInfoService.packData(projectId);
         return R.data("最新数据后台自动打包中,打包完成后会更新打包日期");

+ 2 - 2
blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchivesAutoController.java

@@ -541,8 +541,8 @@ public class ArchivesAutoController extends BladeController {
 	@GetMapping("/getArchiveDestroyUser")
 	@ApiOperationSupport(order = 7)
 	@ApiOperation(value = "获取档案销毁人列表", notes = "获取档案销毁人列表")
-	public R getArchiveDestroyUser(){
-		return R.data(archivesAutoService.getArchiveDestroyUser());
+	public R getArchiveDestroyUser(Long projectId){
+		return R.data(archivesAutoService.getArchiveDestroyUser(projectId));
 	}
 
 

+ 10 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ArchiveOfflineVersionInfoMapper.java

@@ -3,6 +3,8 @@ package org.springblade.archive.mapper;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import org.apache.ibatis.annotations.Param;
 import org.springblade.archive.entity.ArchiveOfflineVersionInfo;
+import org.springblade.business.entity.MetadataClassification;
+import org.springblade.manager.entity.ArchiveTreeContract;
 
 import java.util.HashMap;
 import java.util.List;
@@ -16,4 +18,12 @@ public interface ArchiveOfflineVersionInfoMapper extends BaseMapper<ArchiveOffli
     ArchiveOfflineVersionInfo selectVersionInfo(@Param("projectId") Long projectId);
 
     List<HashMap<String, Object>> getProjectAllMetadata(@Param("projectId") Long projectId);
+
+    List<MetadataClassification> getProjectAllMetadataField();
+
+    ArchiveOfflineVersionInfo getPackStatus();
+
+    void updateById2(@Param("info") ArchiveOfflineVersionInfo info);
+
+    List<ArchiveTreeContract> getListByProjectId(@Param("projectId") Long projectId);
 }

+ 18 - 1
blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ArchiveOfflineVersionInfoMapper.xml

@@ -10,14 +10,31 @@
         <result column="file_name" property="fileName"/>
         <result column="file_size" property="fileSize"/>
     </resultMap>
+    <update id="updateById2">
+        UPDATE u_archive_offline_version_info
+        SET upload_date = #{info.uploadDate}, file_url = #{info.fileUrl},
+            file_name = #{info.fileName}, file_size = #{info.fileSize} WHERE id = #{info.id}
+    </update>
     <select id="selectVersionInfo" resultMap="ResultMap">
         SELECT id, project_id, upload_date, file_url, file_name, file_size
         FROM u_archive_offline_version_info
-        where project_id = #{projectId}
+        where project_id = #{projectId} and file_url is not null
         order by upload_date desc limit 1;
     </select>
     <select id="getProjectAllMetadata" resultType="java.util.HashMap">
         SELECT umf.*  from u_metadata_file umf
         WHERE umf.is_deleted = 0 and umf.contract_id in (select id from m_contract_info mci WHERE mci.p_id = #{projectId} and mci.is_deleted = 0)
     </select>
+    <select id="getProjectAllMetadataField"
+            resultType="org.springblade.business.entity.MetadataClassification">
+        select * from u_metadata_classification where is_deleted = 0
+    </select>
+    <select id="getPackStatus" resultType="org.springblade.archive.entity.ArchiveOfflineVersionInfo">
+        select * from u_archive_offline_version_info order by upload_date desc limit 1
+    </select>
+    <select id="getListByProjectId" resultType="org.springblade.manager.entity.ArchiveTreeContract">
+        select *
+        from m_archive_tree_contract
+        where project_id=#{projectId} and is_deleted = 0 order by tree_sort asc;
+    </select>
 </mapper>

+ 2 - 2
blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ArchivesAutoMapper.java

@@ -130,9 +130,9 @@ public interface ArchivesAutoMapper extends BaseMapper<ArchivesAuto> {
 
 	List<DictBiz> getCarrierTypeByDict();
 
-	void batchDestroyByIds(@Param("ids")List<String> ids);
+	void batchDestroyByIds(@Param("ids")List<String> ids,@Param("userId") Long userId);
 
-	List<User> getArchiveDestroyUser();
+	List<User> getArchiveDestroyUser(@Param("projectId") Long projectId);
 
     String getUserRoleName(@Param("projectId") Long projectId, @Param("contractId") Long contractId, @Param("userId") Long userId);
 

+ 2 - 2
blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ArchivesAutoMapper.xml

@@ -919,7 +919,7 @@
     </select>
     <select id="getArchiveDestroyUser" resultType="org.springblade.system.user.entity.User">
         SELECT id,real_name  FROM blade_user WHERE id IN (SELECT uaa.update_user  FROM u_archives_auto uaa
-                                                          WHERE uaa.is_deleted = 1 AND  uaa.is_destroy = 1
+                                                          WHERE uaa.is_deleted = 1 AND  uaa.is_destroy = 1 and project_id = #{projectId}
                                                           GROUP BY uaa.update_user )
     </select>
     <select id="getAllArchiveFileSize" resultType="java.lang.Long">
@@ -939,7 +939,7 @@
         </foreach>
     </update>
     <update id="batchDestroyByIds">
-        update u_archives_auto set is_deleted = 1 ,is_destroy = 1 where
+        update u_archives_auto set is_deleted = 1 ,is_destroy = 1 ,update_user = #{userId} where
         id in
         <foreach collection="ids" item="id" open="(" separator="," close=")">
             #{id}

+ 2 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/service/IArchiveOfflineVersionInfoService.java

@@ -12,4 +12,6 @@ public interface IArchiveOfflineVersionInfoService extends BaseService<ArchiveOf
     void packData(Long projectId) throws Exception;
 
     public void metadataToSqlite(Long projectId) ;
+
+    int getPackStatus();
 }

+ 1 - 1
blade-service/blade-archive/src/main/java/org/springblade/archive/service/IArchivesAutoService.java

@@ -86,7 +86,7 @@ public interface IArchivesAutoService extends BaseService<ArchivesAuto> {
 
 	void archiveAutoMethodThread(Long projectId, Long contractId, Long nodeId);
 
-	List<User> getArchiveDestroyUser();
+	List<User> getArchiveDestroyUser(Long projectId);
 
 	List<Map<String, List<Map<String, String>>>> getArchivesCabinet(ArchivesAutoVO archivesAuto);
 

+ 176 - 36
blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ArchiveOfflineVersionInfoServiceImpl.java

@@ -9,9 +9,11 @@ import org.springblade.archive.mapper.ArchivesAutoMapper;
 import org.springblade.archive.service.IArchiveOfflineVersionInfoService;
 import org.springblade.archive.utils.FileUtils;
 import org.springblade.business.entity.ArchiveFile;
+import org.springblade.business.entity.MetadataClassification;
 import org.springblade.business.feign.ArchiveFileClient;
 import org.springblade.common.utils.CommonUtil;
 import org.springblade.common.utils.SnowFlakeUtil;
+import org.springblade.core.log.exception.ServiceException;
 import org.springblade.core.mp.base.BaseServiceImpl;
 import org.springblade.core.oss.model.BladeFile;
 import org.springblade.core.tool.utils.ResourceUtil;
@@ -21,10 +23,9 @@ import org.springblade.manager.feign.ArchiveTreeContractClient;
 import org.springblade.resource.feign.NewIOSSClient;
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.InputStream;
+import java.io.*;
 import java.sql.Connection;
 import java.sql.PreparedStatement;
 import java.sql.Statement;
@@ -32,8 +33,12 @@ import java.text.SimpleDateFormat;
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
+import java.util.zip.ZipOutputStream;
+
+import static org.springblade.common.utils.CommonUtil.isDirectory;
 
 /**
  * @Param
@@ -54,11 +59,16 @@ public class ArchiveOfflineVersionInfoServiceImpl extends BaseServiceImpl<Archiv
     @Override
     @Async
     public void packData(Long projectId) throws Exception {
+        ArchiveOfflineVersionInfo info = new ArchiveOfflineVersionInfo();
+        info.setId(SnowFlakeUtil.getId());
+        info.setProjectId(projectId);
+        info.setUploadDate(LocalDateTime.now());
+        infoMapper.insert(info);
 //        String localUrl = "/www/wwwroot/localClient/local_archives/alilib";
 //        String packUrl = "/www/wwwroot/localClient";
 //        String zipUrl = "/www/wwwroot/localClient.zip";
         String localUrl = "/www/wwwroot/Users/hongchuangyanfa/Desktop/localArchive/localClient/local_archives/alilib";
-        String packUrl = "/www/wwwroot/Users/hongchuangyanfa/Desktop/localArchive/localClient";
+        String packUrl = "/www/wwwroot/Users/hongchuangyanfa/Desktop/localArchive";
         String zipUrl = "/www/wwwroot/Users/hongchuangyanfa/Desktop/localArchive/"+projectId;
         //清空url的文件夹
         CommonUtil.deleteDir(localUrl);
@@ -74,23 +84,89 @@ public class ArchiveOfflineVersionInfoServiceImpl extends BaseServiceImpl<Archiv
         //导入元数据
         this.metadataToSqlite(projectId);
         System.out.println("导入元数据");
+        //导入元数据通用字段
+        this.metadataFieldToSqlite();
+        System.out.println("导入元数据通用字段");
         //打包文件
-        CommonUtil.packageZip(packUrl,zipUrl);
-        System.out.println("打包文件");
+//        CommonUtil.packageZip(packUrl,zipUrl);
+        this.packageZip2(zipUrl,packUrl);
+        System.out.println("打包文件完成");
         //上传文件
 //        File zipFile = ResourceUtil.getFile(zipUrl);
         //BladeFile bladeFile = ossBuilder.template().putFile("localClient.zip",new FileInputStream(zipFile));
 //        BladeFile bladeFile = newIOSSClient.uploadFile("localClient.zip", zipUrl);
-        ArchiveOfflineVersionInfo info = new ArchiveOfflineVersionInfo();
-        info.setId(SnowFlakeUtil.getId());
         info.setFileUrl("http://fileinfo.hczcxx.cn/localArchive/"+projectId+"/localArchive.zip");
         info.setFileName("localArchive.zip");
         info.setUploadDate(LocalDateTime.now());
-        info.setProjectId(projectId);
         File file = new File(zipUrl+"/localArchive.zip");
         info.setFileSize(file.length()+"");
-        infoMapper.insert(info);
+        baseMapper.updateById2(info);
+    }
 
+    /**
+     * 压缩指定路径下的文件夹-直接执行linux命令,多线程,速度快几十倍
+     *
+     * @param
+     * @throws Exception
+     */
+    public static void packageZip2(String zipUrl,String packUrl) throws Exception {
+        // 要被压缩的文件夹
+        File folder = new File(zipUrl);
+        if (!folder.exists() && !folder.isDirectory()) {
+            folder.mkdirs();
+        }
+        // 执行脚本文件
+        // 多条命令执行
+        String[] cmds = {"/bin/sh", "-c", "cd "+packUrl+" && zip -q -r "+zipUrl+"/localArchive.zip localClient"};
+        System.out.println("开始执行命令:" + Arrays.toString(cmds));
+        //主要在这步写入后调用命令
+        Process process = Runtime.getRuntime().exec(cmds);
+        process.waitFor();
+    }
+
+    public void metadataFieldToSqlite() {
+        List<MetadataClassification> list = baseMapper.getProjectAllMetadataField();
+        if (list != null && list.size() > 0){
+            try {
+                Connection conn = data.dataSource().getConnection();
+                Statement statement = conn.createStatement();
+                statement.execute("DELETE FROM u_metadata_classification");
+                statement.close();
+                //获取执行对象
+                String sql = "INSERT INTO u_metadata_classification(id, container_name, field_type, code, container_type,capture_mode,mandatory_type,file_storage_type,container_init_tab_name,field_key,is_type)" +
+                        "VALUES(?,?,?,?,?,?,?,?,?,?,?)";
+                PreparedStatement pstm = conn.prepareStatement(sql);
+                //pstm 绑定数据
+                int i = 0;
+                for (MetadataClassification m : list) {
+                    i++;
+                    pstm.setLong(1, m.getId());
+                    pstm.setString(2, m.getContainerName());
+                    pstm.setString(3, m.getFieldType());
+                    pstm.setString(4, m.getCode());
+                    pstm.setLong(5, m.getContainerType());
+                    pstm.setLong(6, m.getCaptureMode());
+                    pstm.setLong(7, m.getMandatoryType());
+                    pstm.setString(8, m.getFileStorageType());
+                    pstm.setString(9, m.getContainerInitTabName());
+                    pstm.setString(10, m.getFieldKey());
+                    pstm.setLong(11, m.getIsType());
+                    //添加批处理
+                    pstm.addBatch();
+                    if (i % 1000 == 0) {
+                        pstm.executeBatch();
+                        pstm.clearBatch();
+                    }
+                }
+                //将批处理余下的语句执行完毕
+                pstm.executeBatch();
+                //释放资源
+                pstm.close();
+                conn.close();
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
     }
 
     public void metadataToSqlite(Long projectId) {
@@ -102,8 +178,11 @@ public class ArchiveOfflineVersionInfoServiceImpl extends BaseServiceImpl<Archiv
                 statement.execute("DELETE FROM u_metadata_file");
                 statement.close();
                 //获取执行对象
-                String sql = "INSERT INTO u_metadata_file(id, file_id, file_key_m1, file_key_m4, file_key_m11,file_key_m13,file_key_m14,file_key_m16,file_key_m17,file_key_m18,file_key_m19,file_key_m22,file_key_m34,file_key_m36,file_key_m37,file_key_m38,file_key_m40,file_key_m41,file_key_m60)" +
-                        "VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
+                String sql = "INSERT INTO u_metadata_file(id, file_id, file_key_m1, file_key_m2, file_key_m3, file_key_m4, file_key_m5, file_key_m6, file_key_m7, file_key_m8, file_key_m9, file_key_m10, file_key_m11, file_key_m12, file_key_m13, " +
+                        "file_key_m14,file_key_m15,file_key_m16,file_key_m17,file_key_m18,file_key_m19,file_key_m20,file_key_m21,file_key_m22,file_key_m23,file_key_m24,file_key_m25,file_key_m26,file_key_m27,file_key_m28,file_key_m29,file_key_m30,file_key_m31,file_key_m32," +
+                        "file_key_m33,file_key_m34,file_key_m35,file_key_m36,file_key_m37,file_key_m38,file_key_m39,file_key_m40,file_key_m41,file_key_m42,file_key_m43,file_key_m44,file_key_m45,file_key_m46,file_key_m47,file_key_m48,file_key_m49,file_key_m50," +
+                        "file_key_m51, file_key_m52,file_key_m53,file_key_m54,file_key_m55,file_key_m56,file_key_m57,file_key_m58,file_key_m59,file_key_m60,file_key_m61,file_key_m62,file_key_m63 )" +
+                        "VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
                 PreparedStatement pstm = conn.prepareStatement(sql);
                 //pstm 绑定数据
                 int i = 0;
@@ -112,25 +191,71 @@ public class ArchiveOfflineVersionInfoServiceImpl extends BaseServiceImpl<Archiv
                     pstm.setLong(1, (Long) Map.get("id"));
                     pstm.setLong(2, (Long) Map.get("file_id"));
                     pstm.setString(3, Map.get("file_key_m1") == null ? null : Map.get("file_key_m1")+"");
-                    pstm.setString(4, Map.get("file_key_m4") == null ? null : Map.get("file_key_m4")+"");
-                    pstm.setString(5, Map.get("file_key_m11") == null ? null : Map.get("file_key_m11")+"");
-                    pstm.setString(6, Map.get("file_key_m13") == null ? null : Map.get("file_key_m13")+"");
-                    pstm.setString(7, Map.get("file_key_m14") == null ? null : Map.get("file_key_m14")+"");
-                    pstm.setString(8, Map.get("file_key_m16") == null ? null : Map.get("file_key_m16")+"");
-                    pstm.setString(9, Map.get("file_key_m17") == null ? null : Map.get("file_key_m17")+"");
-                    pstm.setString(10, Map.get("file_key_m18") == null ? null : Map.get("file_key_m18")+"");
-                    pstm.setString(11, Map.get("file_key_m19") == null ? null : Map.get("file_key_m19")+"");
-                    pstm.setString(12, Map.get("file_key_m22") == null ? null : Map.get("file_key_m22")+"");
-                    pstm.setString(13, Map.get("file_key_m34") == null ? null : Map.get("file_key_m34")+"");
-                    pstm.setString(14, Map.get("file_key_m36") == null ? null : Map.get("file_key_m36")+"");
-                    pstm.setString(15, Map.get("file_key_m37") == null ? null : Map.get("file_key_m37")+"");
-                    pstm.setString(16, Map.get("file_key_m38") == null ? null : Map.get("file_key_m38")+"");
-                    pstm.setString(17, Map.get("file_key_m40") == null ? null : Map.get("file_key_m40")+"");
-                    pstm.setString(18, Map.get("file_key_m41") == null ? null : Map.get("file_key_m41")+"");
-                    pstm.setString(19, Map.get("file_key_m60") == null ? null : Map.get("file_key_m60")+"");
+                    pstm.setString(4, Map.get("file_key_m2") == null ? null : Map.get("file_key_m2")+"");
+                    pstm.setString(5, Map.get("file_key_m3") == null ? null : Map.get("file_key_m3")+"");
+                    pstm.setString(6, Map.get("file_key_m4") == null ? null : Map.get("file_key_m4")+"");
+                    pstm.setString(7, Map.get("file_key_m5") == null ? null : Map.get("file_key_m5")+"");
+                    pstm.setString(8, Map.get("file_key_m6") == null ? null : Map.get("file_key_m6")+"");
+                    pstm.setString(9, Map.get("file_key_m7") == null ? null : Map.get("file_key_m7")+"");
+                    pstm.setString(10, Map.get("file_key_m8") == null ? null : Map.get("file_key_m8")+"");
+                    pstm.setString(11, Map.get("file_key_m9") == null ? null : Map.get("file_key_m9")+"");
+                    pstm.setString(12, Map.get("file_key_m10") == null ? null : Map.get("file_key_m10")+"");
+                    pstm.setString(13, Map.get("file_key_m11") == null ? null : Map.get("file_key_m11")+"");
+                    pstm.setString(14, Map.get("file_key_m12") == null ? null : Map.get("file_key_m12")+"");
+                    pstm.setString(15, Map.get("file_key_m13") == null ? null : Map.get("file_key_m13")+"");
+                    pstm.setString(16, Map.get("file_key_m14") == null ? null : Map.get("file_key_m14")+"");
+                    pstm.setString(17, Map.get("file_key_m15") == null ? null : Map.get("file_key_m15")+"");
+                    pstm.setString(18, Map.get("file_key_m16") == null ? null : Map.get("file_key_m16")+"");
+                    pstm.setString(19, Map.get("file_key_m17") == null ? null : Map.get("file_key_m17")+"");
+                    pstm.setString(20, Map.get("file_key_m18") == null ? null : Map.get("file_key_m18")+"");
+                    pstm.setString(21, Map.get("file_key_m19") == null ? null : Map.get("file_key_m19")+"");
+                    pstm.setString(22, Map.get("file_key_m20") == null ? null : Map.get("file_key_m20")+"");
+                    pstm.setString(23, Map.get("file_key_m21") == null ? null : Map.get("file_key_m21")+"");
+                    pstm.setString(24, Map.get("file_key_m22") == null ? null : Map.get("file_key_m22")+"");
+                    pstm.setString(25, Map.get("file_key_m23") == null ? null : Map.get("file_key_m23")+"");
+                    pstm.setString(26, Map.get("file_key_m24") == null ? null : Map.get("file_key_m24")+"");
+                    pstm.setString(27, Map.get("file_key_m25") == null ? null : Map.get("file_key_m25")+"");
+                    pstm.setString(28, Map.get("file_key_m26") == null ? null : Map.get("file_key_m26")+"");
+                    pstm.setString(29, Map.get("file_key_m27") == null ? null : Map.get("file_key_m27")+"");
+                    pstm.setString(30, Map.get("file_key_m28") == null ? null : Map.get("file_key_m28")+"");
+                    pstm.setString(31, Map.get("file_key_m29") == null ? null : Map.get("file_key_m29")+"");
+                    pstm.setString(32, Map.get("file_key_m30") == null ? null : Map.get("file_key_m30")+"");
+                    pstm.setString(33, Map.get("file_key_m31") == null ? null : Map.get("file_key_m31")+"");
+                    pstm.setString(34, Map.get("file_key_m32") == null ? null : Map.get("file_key_m32")+"");
+                    pstm.setString(35, Map.get("file_key_m33") == null ? null : Map.get("file_key_m33")+"");
+                    pstm.setString(36, Map.get("file_key_m34") == null ? null : Map.get("file_key_m34")+"");
+                    pstm.setString(37, Map.get("file_key_m35") == null ? null : Map.get("file_key_m35")+"");
+                    pstm.setString(38, Map.get("file_key_m36") == null ? null : Map.get("file_key_m36")+"");
+                    pstm.setString(39, Map.get("file_key_m37") == null ? null : Map.get("file_key_m37")+"");
+                    pstm.setString(40, Map.get("file_key_m38") == null ? null : Map.get("file_key_m38")+"");
+                    pstm.setString(41, Map.get("file_key_m39") == null ? null : Map.get("file_key_m39")+"");
+                    pstm.setString(42, Map.get("file_key_m40") == null ? null : Map.get("file_key_m40")+"");
+                    pstm.setString(43, Map.get("file_key_m41") == null ? null : Map.get("file_key_m41")+"");
+                    pstm.setString(44, Map.get("file_key_m42") == null ? null : Map.get("file_key_m42")+"");
+                    pstm.setString(45, Map.get("file_key_m43") == null ? null : Map.get("file_key_m43")+"");
+                    pstm.setString(46, Map.get("file_key_m44") == null ? null : Map.get("file_key_m44")+"");
+                    pstm.setString(47, Map.get("file_key_m45") == null ? null : Map.get("file_key_m45")+"");
+                    pstm.setString(48, Map.get("file_key_m46") == null ? null : Map.get("file_key_m46")+"");
+                    pstm.setString(49, Map.get("file_key_m47") == null ? null : Map.get("file_key_m47")+"");
+                    pstm.setString(50, Map.get("file_key_m48") == null ? null : Map.get("file_key_m48")+"");
+                    pstm.setString(51, Map.get("file_key_m49") == null ? null : Map.get("file_key_m49")+"");
+                    pstm.setString(52, Map.get("file_key_m50") == null ? null : Map.get("file_key_m50")+"");
+                    pstm.setString(53, Map.get("file_key_m51") == null ? null : Map.get("file_key_m51")+"");
+                    pstm.setString(54, Map.get("file_key_m52") == null ? null : Map.get("file_key_m52")+"");
+                    pstm.setString(55, Map.get("file_key_m53") == null ? null : Map.get("file_key_m53")+"");
+                    pstm.setString(56, Map.get("file_key_m54") == null ? null : Map.get("file_key_m54")+"");
+                    pstm.setString(57, Map.get("file_key_m55") == null ? null : Map.get("file_key_m55")+"");
+                    pstm.setString(58, Map.get("file_key_m56") == null ? null : Map.get("file_key_m56")+"");
+                    pstm.setString(59, Map.get("file_key_m57") == null ? null : Map.get("file_key_m57")+"");
+                    pstm.setString(60, Map.get("file_key_m58") == null ? null : Map.get("file_key_m58")+"");
+                    pstm.setString(61, Map.get("file_key_m59") == null ? null : Map.get("file_key_m59")+"");
+                    pstm.setString(62, Map.get("file_key_m60") == null ? null : Map.get("file_key_m60")+"");
+                    pstm.setString(63, Map.get("file_key_m61") == null ? null : Map.get("file_key_m61")+"");
+                    pstm.setString(64, Map.get("file_key_m62") == null ? null : Map.get("file_key_m62")+"");
+                    pstm.setString(65, Map.get("file_key_m63") == null ? null : Map.get("file_key_m63")+"");
                     //添加批处理
                     pstm.addBatch();
-                    if (i % 1000 == 0) {
+                    if (i % 500 == 0) {
                         pstm.executeBatch();
                         pstm.clearBatch();
                     }
@@ -146,6 +271,20 @@ public class ArchiveOfflineVersionInfoServiceImpl extends BaseServiceImpl<Archiv
         }
     }
 
+    /**
+     * 获取当前打包状态,如果正在进行打包则提示
+     * @return
+     */
+    @Override
+    public int getPackStatus() {
+        ArchiveOfflineVersionInfo info = baseMapper.getPackStatus();
+        if (info == null || info.getFileUrl() != null){
+            return 0;
+        }else {
+            throw new ServiceException("有项目正在打包中,请稍后再试");
+        }
+    }
+
     public void fileToSqlite(Long projectId) throws Exception {
         List<ArchiveFile> list = fileClient.getListByProjectId(projectId);
         if (list != null && list.size() > 0) {
@@ -192,8 +331,8 @@ public class ArchiveOfflineVersionInfoServiceImpl extends BaseServiceImpl<Archiv
                     pstm.setString(6, file.getFileTime());
                     pstm.setString(7, file.getFileUrl() == null ? "" : file.getFileUrl());
                     pstm.setString(8, file.getPdfFileUrl() == null ? "" : file.getPdfFileUrl());
-                    pstm.setInt(9, file.getStatus());
-                    pstm.setInt(10, file.getIsDeleted());
+                    pstm.setLong(9, file.getStatus());
+                    pstm.setLong(10, file.getIsDeleted());
                     pstm.setLong(11, file.getArchiveId() == null ? -1 : file.getArchiveId());
                     pstm.setString(12, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(file.getCreateTime()));
                     pstm.setString(13, file.getDutyUser());
@@ -216,7 +355,7 @@ public class ArchiveOfflineVersionInfoServiceImpl extends BaseServiceImpl<Archiv
     }
 
     public void contractToSqlite(Long projectId) {
-        List<ArchiveTreeContract> list = contractClient.getListByProjectId(projectId);
+        List<ArchiveTreeContract> list = baseMapper.getListByProjectId(projectId);
         if (list != null && list.size() > 0) {
             try {
                 Connection conn = data.dataSource().getConnection();
@@ -224,8 +363,8 @@ public class ArchiveOfflineVersionInfoServiceImpl extends BaseServiceImpl<Archiv
                 statement.execute("DELETE FROM m_archive_tree_contract");
                 statement.close();
                 //获取执行对象
-                String sql = "INSERT INTO m_archive_tree_contract(id, project_id, parent_id, ancestors, node_name,status,is_deleted,create_time)" +
-                        "VALUES(?, ?, ?, ?, ?,?,?,?)";
+                String sql = "INSERT INTO m_archive_tree_contract(id, project_id, parent_id, ancestors, node_name,status,is_deleted,create_time,storage_type)" +
+                        "VALUES(?, ?, ?, ?, ?,?,?,?,?)";
                 PreparedStatement pstm = conn.prepareStatement(sql);
                 //pstm 绑定数据
                 int i = 0;
@@ -236,9 +375,10 @@ public class ArchiveOfflineVersionInfoServiceImpl extends BaseServiceImpl<Archiv
                     pstm.setLong(3, contract.getParentId());
                     pstm.setString(4, contract.getAncestors());
                     pstm.setString(5, contract.getNodeName());
-                    pstm.setInt(6, contract.getStatus());
-                    pstm.setInt(7, contract.getIsDeleted());
+                    pstm.setLong(6, contract.getStatus());
+                    pstm.setLong(7, contract.getIsDeleted());
                     pstm.setString(8, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(contract.getCreateTime()));
+                    pstm.setString(9, contract.getStorageType() == null ? null : contract.getStorageType()+"");
                     //添加批处理
                     pstm.addBatch();
                     if (i % 1000 == 0) {

+ 5 - 3
blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ArchivesAutoServiceImpl.java

@@ -53,6 +53,7 @@ import org.springblade.core.mp.support.Query;
 import org.springblade.core.oss.model.BladeFile;
 import org.springblade.core.secure.BladeUser;
 import org.springblade.core.secure.utils.AuthUtil;
+import org.springblade.core.secure.utils.SecureUtil;
 import org.springblade.core.tool.api.R;
 import org.springblade.core.tool.utils.FileUtil;
 import org.springblade.core.tool.utils.Func;
@@ -771,7 +772,8 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 			archiveFileClient.batchDeleteArchiveFile(collect);
 		}
 		//销毁案卷
-		baseMapper.batchDestroyByIds(list);
+		Long userId = SecureUtil.getUserId();
+		baseMapper.batchDestroyByIds(list,userId);
 	}
 
 
@@ -2077,8 +2079,8 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 	}
 
 	@Override
-	public List<User> getArchiveDestroyUser() {
-		return autoMapper.getArchiveDestroyUser();
+	public List<User> getArchiveDestroyUser(Long projectId) {
+		return autoMapper.getArchiveDestroyUser(projectId);
 	}
 
 

+ 83 - 33
blade-service/blade-business/src/main/java/org/springblade/business/controller/InformationWriteQueryController.java

@@ -50,6 +50,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.redis.core.StringRedisTemplate;
 import org.springframework.jdbc.core.BeanPropertyRowMapper;
 import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.RowMapper;
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.transaction.annotation.Propagation;
 import org.springframework.transaction.annotation.Transactional;
@@ -59,8 +60,13 @@ import org.springframework.web.bind.annotation.*;
 import javax.servlet.http.HttpServletResponse;
 import javax.validation.Valid;
 import java.io.IOException;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
 import java.util.*;
 import java.util.function.Function;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 
 /**
@@ -1347,6 +1353,9 @@ public class InformationWriteQueryController extends BladeController {
 
     /**
      * 复制节点
+     *
+     * @author liuyc
+     * @date 2023年4月10日18:06:53
      */
     @PostMapping("/copyContractTreeNode")
     @ApiOperationSupport(order = 15)
@@ -1393,7 +1402,7 @@ public class InformationWriteQueryController extends BladeController {
             List<QueryProcessDataVO> nodeTabCols = informationQueryService.getNodeChildTabColsAllByNodeId(needCopyNode.getId() + "", needCopyNode.getContractId());
             //转化为map
             Map<String, String> nodeTabColsMap = nodeTabCols.stream().collect(Collectors.toMap(QueryProcessDataVO::getQueryType, QueryProcessDataVO::getAncestors, (key1, key2) -> key2));
-            StringBuilder copeSql = new StringBuilder();
+            StringBuilder copySql = new StringBuilder();
 
             if (StringUtils.isNotEmpty(vo.getNeedCopyPrimaryKeyId())) {
                 WbsTreeContract parent = this.wbsTreeContractClient.getContractNodeByPrimaryKeyId(vo.getParentPrimaryKeyId());
@@ -1457,16 +1466,70 @@ public class InformationWriteQueryController extends BladeController {
                         this.createLedger(newData, saveLedger, nodeMap, null);
                     }
                     //表单所属方,只有勾选了对应的所属方权限才复制数据;勾选了复制数据才能复制,否则只是创建节点、表
-                    //组织复制值Sql
                     if (nodeOld.getType() == 2 && StringUtils.isNotEmpty(newData.getInitTableName()) && tabOwner.contains(nodeOld.getTableOwner()) && vo.getIsCopyData() == 1) {
                         String tableName = newData.getInitTableName();
                         String col = nodeTabColsMap.get(tableName);
-                        String colVal = nodeTabColsMap.get(tableName);
-                        colVal = colVal.replaceAll("id,p_key_id,", "'" + SnowFlakeUtil.getId() + "' as id,'" + newData.getPKeyId() + "' as p_key_id,");
+                        List<String> filteredList = Arrays.stream(col.split(","))
+                                .filter(value -> !value.equals("id") && !value.equals("p_key_id") && !value.equals("group_id"))
+                                .collect(Collectors.toList());
+                        String keys = StringUtils.join(filteredList, ",");
+
+                        //构造入参
+                        String dataSql = "SELECT " + keys + " FROM " + tableName + " WHERE p_key_id= " + nodeOld.getPKeyId() + " LIMIT 1;";
+                        List<LinkedHashMap<String, Object>> resultList = jdbcTemplate.query(dataSql, new RowMapper<LinkedHashMap<String, Object>>() {
+                            @Override
+                            public LinkedHashMap<String, Object> mapRow(@NotNull ResultSet rs, int rowNum) throws SQLException {
+                                ResultSetMetaData metaData = rs.getMetaData();
+                                int columnCount = metaData.getColumnCount();
+                                LinkedHashMap<String, Object> resultMap = new LinkedHashMap<>();
+                                for (int i = 1; i <= columnCount; i++) {
+                                    String columnName = metaData.getColumnName(i);
+                                    Object columnValue = rs.getObject(i);
+                                    resultMap.put(columnName, columnValue);
+                                }
+                                return resultMap;
+                            }
+                        });
+                        StringBuilder newString = new StringBuilder();
+                        if (!resultList.isEmpty()) {
+                            LinkedHashMap<String, Object> resultMap = resultList.get(0);
+                            for (Map.Entry<String, Object> entry : resultMap.entrySet()) {
+                                Object value = entry.getValue();
+                                if (value != null) {
+                                    if (value.toString().contains("\n")) {
+                                        //如果值中包含换行符,则将换行符替换
+                                        value = value.toString().replace("\n", "\\n");
+                                    }
+                                    newString.append("'").append(value).append("',");
+                                } else {
+                                    newString.append("null,");
+                                }
+                            }
+                        }
+
+                        if (newString.length() <= 0) {
+                            //如果没值,那么根据keys构造keys数位的null值字符串
+                            int size = filteredList.size();
+                            for (int i = 0; i < size; i++) {
+                                newString.append("null,");
+                            }
+                        }
+                        //去除末尾的逗号
+                        newString.deleteCharAt(newString.length() - 1);
+                        //首位拼接逗号
+                        newString.insert(0, ",");
+
                         //delete SQL (先删除旧数据,再新增)
-                        String delSql = "delete from " + tableName + " where p_key_id = " + newData.getPKeyId() + " ; ";
+                        String delSql = "DELETE FROM " + tableName + " WHERE p_key_id = " + newData.getPKeyId() + " ; ";
+
                         //insert into SQL
-                        copeSql.append(delSql).append("insert into ").append(tableName).append(" (").append(col).append(") select ").append(colVal).append(" from ").append(tableName).append(" where p_key_id='").append(nodeOld.getPKeyId()).append("' ;");
+                        copySql.append(delSql).append("INSERT INTO ").append(tableName)
+                                .append(" (id,p_key_id,group_id,")
+                                .append(keys)
+                                .append(") VALUES (")
+                                .append(SnowFlakeUtil.getId()).append(",")
+                                .append(newData.getPKeyId()).append(",null")
+                                .append(newString).append(") ; ");
                     }
                 }
             }
@@ -1477,8 +1540,8 @@ public class InformationWriteQueryController extends BladeController {
 
             try {
                 //复制表单数据
-                if (copeSql.length() >= 10 && booleanR.getData()) {
-                    jdbcTemplate.execute(copeSql.toString());
+                if (copySql.length() >= 10 && booleanR.getData()) {
+                    jdbcTemplate.execute(copySql.toString());
                 }
             } catch (Exception e) {
                 //手动回滚,删除节点、表
@@ -1503,9 +1566,6 @@ public class InformationWriteQueryController extends BladeController {
 
         } else if (("2").equals(vo.getCopyType())) {
             /** TODO 多份复制
-             * @Author liuYC
-             * @Date 2023年4月10日18:06:53
-             * @Description
              *  解析复制节点位置信息:
              *  1:同节点复制(同一个父级下)
              *      1.1 如果点击选择的是当前复制节点的父级,那么就新增一个当前需要复制的节点-新的子级-新的表-新的表数据(根据所属方查询对应数据)。
@@ -1836,7 +1896,7 @@ public class InformationWriteQueryController extends BladeController {
                                 //delete SQL (先删除旧数据,再新增)
                                 String delSql = "delete from " + tableName + " where p_key_id = " + toCopyNodeTab.getPKeyId() + " ; ";
                                 //insert into SQL
-                                copyDataSql.append(delSql).append("insert into ").append(tableName).append("  (").append(col).append(") select ").append(colVal).append(" from ").append(tableName).append(" where p_key_id='").append(oldPKeyId).append("' ;");
+                                copyDataSql.append(delSql).append("insert into ").append(tableName).append("  (").append(col).append(") select ").append(colVal).append(" from ").append(tableName).append(" where p_key_id='").append(oldPKeyId).append("' LIMIT 1;");
                                 resultTablesData.add(copyDataSql.toString());
                             }
                         }
@@ -1881,7 +1941,7 @@ public class InformationWriteQueryController extends BladeController {
                                     //delete SQL (先删除旧数据,再新增)
                                     String delSql = "delete from " + tableName + " where p_key_id = " + objTab.getPKeyId() + " ; ";
                                     //insert into SQL
-                                    copyDataSql.append(delSql).append("insert into ").append(tableName).append("  (").append(col).append(") select ").append(colVal).append(" from ").append(tableName).append(" where p_key_id='").append(oldPKeyId).append("' ;");
+                                    copyDataSql.append(delSql).append("insert into ").append(tableName).append("  (").append(col).append(") select ").append(colVal).append(" from ").append(tableName).append(" where p_key_id='").append(oldPKeyId).append("' LIMIT 1;");
                                     resultTablesData.add(copyDataSql.toString());
                                 }
                             }
@@ -1974,7 +2034,7 @@ public class InformationWriteQueryController extends BladeController {
                             //delete SQL (先删除旧数据,再新增)
                             String delSql = "delete from " + tableName + " where p_key_id = " + obj.getPKeyId() + " ; ";
                             //insert into SQL
-                            copyDataSql.append(delSql).append("insert into ").append(tableName).append("  (").append(col).append(") select ").append(colVal).append(" from ").append(tableName).append(" where p_key_id='").append(oldPKeyId).append("' ;");
+                            copyDataSql.append(delSql).append("insert into ").append(tableName).append("  (").append(col).append(") select ").append(colVal).append(" from ").append(tableName).append(" where p_key_id='").append(oldPKeyId).append("' LIMIT 1;");
                             resultTablesData.add(copyDataSql.toString());
                         }
                     }
@@ -2071,7 +2131,7 @@ public class InformationWriteQueryController extends BladeController {
                                         //delete SQL (先删除旧数据,再新增)
                                         String delSql = "delete from " + tableName + " where p_key_id = " + needTab.getPKeyId() + " ; ";
                                         //insert into SQL
-                                        copyDataSql.append(delSql).append("insert into ").append(tableName).append("  (").append(col).append(") select ").append(colVal).append(" from ").append(tableName).append(" where p_key_id='").append(oldPKeyId).append("' ;");
+                                        copyDataSql.append(delSql).append("insert into ").append(tableName).append("  (").append(col).append(") select ").append(colVal).append(" from ").append(tableName).append(" where p_key_id='").append(oldPKeyId).append("' LIMIT 1;");
                                         resultTablesData.add(copyDataSql.toString());
                                     }
                                 }
@@ -2721,22 +2781,6 @@ public class InformationWriteQueryController extends BladeController {
                         Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(WbsTreePrivate::getId))),
                         ArrayList::new
                 ));
-
-                /*if (childList.size() > 0) {
-                    Iterator<WbsTreePrivate> iterator = childList.iterator();
-                    while (iterator.hasNext()) {
-                        WbsTreePrivate next = iterator.next();
-                        for (WbsTreePrivate wbsTreePrivate : selectedNodeList) {
-                            if (wbsTreePrivate.getPKeyId().equals(next.getPKeyId())) {
-                                //删掉重复数据
-                                iterator.remove();
-                                break;
-                            }
-                        }
-                    }
-                }*/
-                //处理完重复数据后,设置进集合中
-                //selectedNodeList.addAll(childList);
             }
             //处理半选
             this.disposeHalfSelectList(treeContract, halfSelectedNodeList, selectedNodeList, query);
@@ -2864,6 +2908,8 @@ public class InformationWriteQueryController extends BladeController {
                 newData.setCreateTime(new Date());
                 if (half.getType() != null && new Integer("2").equals(half.getType())) {
                     newData.setIsTypePrivatePid(half.getPKeyId());
+                    //2023年8月1日14:41:03更改需求,isBussShow默认=1
+                    newData.setIsBussShow(1);
                 }
 
                 //获取当前所有复制的节点的最大sort
@@ -2965,7 +3011,9 @@ public class InformationWriteQueryController extends BladeController {
     }
 
     @NotNull
-    public R<Boolean> saveOrCopyNodeTree(List<WbsTreeContract> saveList, List<ConstructionLedger> saveLedger, Integer operationType, WbsTreeContract currentNode) {
+    public R<Boolean> saveOrCopyNodeTree
+            (List<WbsTreeContract> saveList, List<ConstructionLedger> saveLedger, Integer
+                    operationType, WbsTreeContract currentNode) {
         if (saveList.size() > 0) {
             //StringBuilder str = new StringBuilder();
             //str.append("-" + saveList.get(0).getFullName());
@@ -3009,7 +3057,9 @@ public class InformationWriteQueryController extends BladeController {
     }
 
     @NotNull
-    private R<Boolean> saveOrCopyNodeTree2(List<WbsTreeContract> saveList, List<ConstructionLedger> saveLedger, Integer operationType, WbsTreeContract currentNode) {
+    private R<Boolean> saveOrCopyNodeTree2
+            (List<WbsTreeContract> saveList, List<ConstructionLedger> saveLedger, Integer
+                    operationType, WbsTreeContract currentNode) {
         if (saveList.size() > 0) {
             //StringBuilder str = new StringBuilder();
             //str.append("-" + saveList.get(0).getFullName());

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

@@ -192,7 +192,7 @@ public class MileageController {
                 BeanUtils.copyProperties(mileagexy, m);
                 m.setValueEnd(mileagexy.getValue() + mileagexy.getL());
                 //必须要设置angle
-                mileagexy.setAngle(m.getDu() + Double.valueOf(m.getFen()) / 60 + m.getMiao() / 3600);
+                m.setAngle(m.getDu() + Double.valueOf(m.getFen()) / 60 + m.getMiao() / 3600);
                 return R.status(this.service.updateById(m));
             }
         }

+ 18 - 13
blade-service/blade-business/src/main/java/org/springblade/business/feignClient/MileageClientImpl.java

@@ -2,6 +2,7 @@ package org.springblade.business.feignClient;
 
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import lombok.AllArgsConstructor;
+import org.springblade.business.entity.MileagePart;
 import org.springblade.business.entity.Mileagexy;
 import org.springblade.business.feign.MileageClient;
 import org.springblade.business.service.impl.MileagePartService;
@@ -25,6 +26,7 @@ import java.util.stream.Collectors;
 @AllArgsConstructor
 public class MileageClientImpl implements MileageClient {
     private final MileagexyService service;
+    private final MileagePartService partService;
 
 
     @Override
@@ -33,20 +35,23 @@ public class MileageClientImpl implements MileageClient {
         Map<String, List<String>> group = mileages.stream().collect(Collectors.groupingBy(e -> e.replaceAll("K.+", StringPool.EMPTY)));
         for (Map.Entry<String, List<String>> entry : group.entrySet()) {
             String part = entry.getKey();
-            List<Mileagexy> target = this.service.list(Wrappers.<Mileagexy>lambdaQuery().eq(Mileagexy::getContractId, contractId.toString()).eq(Mileagexy::getPartNo, part).orderByAsc(Mileagexy::getValue));
-            if (CollectionUtil.isNotEmpty(target)) {
-                entry.getValue().forEach(e -> {
-                    String[] r = new String[]{StringPool.EMPTY, StringPool.EMPTY};
-                    if (Func.isNotBlank(e)) {
-                        String[] arr = e.split(StringPool.AT);
-                        double[] db = MileageUtill.azimuthZbXy(BaseUtils.k2d(arr[0]), Double.parseDouble(arr[1]), 90, target);
-                        if (db != null && db.length == 3) {
-                            r[0] = String.valueOf(db[0]);
-                            r[1] = String.valueOf(db[1]);
-                            result.put(e, r);
+            MileagePart mileagePart=this.partService.getOne(Wrappers.<MileagePart>lambdaQuery().eq(MileagePart::getContractId,contractId.toString()).eq(MileagePart::getPrefix,part).last(" limit 1 "));
+            if(mileagePart!=null) {
+                List<Mileagexy> target = this.service.list(Wrappers.<Mileagexy>lambdaQuery().eq(Mileagexy::getPartId, mileagePart.getId()).orderByAsc(Mileagexy::getValue));
+                if (CollectionUtil.isNotEmpty(target)) {
+                    entry.getValue().forEach(e -> {
+                        String[] r = new String[]{StringPool.EMPTY, StringPool.EMPTY};
+                        if (Func.isNotBlank(e)) {
+                            String[] arr = e.split(StringPool.AT);
+                            double[] db = MileageUtill.azimuthZbXy(BaseUtils.k2d(arr[0]), Double.parseDouble(arr[1]), 90, target);
+                            if (db != null && db.length == 3) {
+                                r[0] = String.valueOf(db[0]);
+                                r[1] = String.valueOf(db[1]);
+                                result.put(e, r);
+                            }
                         }
-                    }
-                });
+                    });
+                }
             }
         }
         /*坐标集合*/

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

@@ -305,8 +305,11 @@
                 wtc1.is_deleted = 0 and wtc1.contract_id = wtc.contract_id AND wtc1.major_data_type IN(1,2,3,4)
             </otherwise>
         </choose>
-        LEFT JOIN u_information_query AS iq ON (iq.wbs_id = wtc1.p_key_id OR iq.wbs_id = wtc.p_key_id) AND classify =
-        #{classify} AND iq.type != 3
+        LEFT JOIN u_information_query AS iq ON (iq.wbs_id = wtc1.p_key_id OR iq.wbs_id = wtc.p_key_id)
+        <if test=" classify != null and classify!='' ">
+            AND classify = #{classify}
+        </if>
+        AND iq.type != 3
         WHERE
         wtc.contract_id IN
         <foreach collection="contractIds" item="contractId" open="(" separator="," close=")">

+ 6 - 5
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/InformationQueryServiceImpl.java

@@ -149,6 +149,7 @@ public class InformationQueryServiceImpl extends BaseServiceImpl<InformationQuer
         }
         return result;
     }
+
     //删除节点用
     @Override
     public List<QueryProcessDataVO> queryProcessDataByParentIdAndContractId2(String parentId, Integer classify, String contractId) {
@@ -812,14 +813,14 @@ public class InformationQueryServiceImpl extends BaseServiceImpl<InformationQuer
             if (contractIds.size() > 0) {
                 if (StringUtils.isNotEmpty(parentId)) {
                     //子节点
-                    rootTreeNode = this.queryContractTreeSupervision(contractIds, parentId, Integer.parseInt(classifyType));
+                    rootTreeNode = this.queryContractTreeSupervision(contractIds, parentId, classifyType != null && ObjectUtil.isNotEmpty(classifyType) ? Integer.parseInt(classifyType) : null);
                 } else {
                     //根节点
-                    rootTreeNode = this.queryContractTreeSupervision(contractIds, "0", Integer.parseInt(classifyType));
+                    rootTreeNode = this.queryContractTreeSupervision(contractIds, "0", classifyType != null && ObjectUtil.isNotEmpty(classifyType) ? Integer.parseInt(classifyType) : null);
 
                     //设置根节点数量统计
                     for (WbsTreeContractTreeVOS root : rootTreeNode) {
-                        List<WbsTreeContractTreeVOS> rootZi = this.queryContractTreeSupervision(Func.toStrList(root.getContractIdRelation()), root.getId().toString(), Integer.parseInt(classifyType));
+                        List<WbsTreeContractTreeVOS> rootZi = this.queryContractTreeSupervision(Func.toStrList(root.getContractIdRelation()), root.getId().toString(), classifyType != null && ObjectUtil.isNotEmpty(classifyType) ? Integer.parseInt(classifyType) : null);
                         List<Long> collect = rootZi.stream().map(WbsTreeContractTreeVOS::getSubmitCounts).collect(Collectors.toList());
                         Long reduce = collect.stream().reduce(0L, Long::sum);
                         root.setSubmitCounts(reduce);
@@ -885,8 +886,8 @@ public class InformationQueryServiceImpl extends BaseServiceImpl<InformationQuer
     }
 
     @Override
-    public List<QueryProcessDataVO> getNodeChildTabColsWithValueByTabName(String initTabName,String pKeyId) {
-        return baseMapper.getNodeChildTabColsWithValueByTabName(initTabName,pKeyId);
+    public List<QueryProcessDataVO> getNodeChildTabColsWithValueByTabName(String initTabName, String pKeyId) {
+        return baseMapper.getNodeChildTabColsWithValueByTabName(initTabName, pKeyId);
     }
 
     @Override

+ 1 - 2
blade-service/blade-control/src/main/java/org/springblade/control/controller/CorporationInfoController.java

@@ -166,6 +166,7 @@ public class CorporationInfoController extends BladeController {
             //获取PDF文件
             BladeFile bladeFile = this.newIOSSClient.updateFile(file.getBytes(), file.getOriginalFilename());
             BeanUtils.copyProperties(bladeFile, newBladeFile);
+            newBladeFile.setPdfUrl(bladeFile.getLink());
         }
         String fileExtension = FileUtil.getFileExtension(newBladeFile.getOriginalName());
         if (StringUtils.isNotEmpty(id)) {
@@ -188,7 +189,6 @@ public class CorporationInfoController extends BladeController {
             corporationInfo.setAttachSize(newBladeFile.getFileSize());
             corporationInfo.setExtension(fileExtension);
         }
-
         boolean b = corporationInfoService.saveOrUpdate(corporationInfo);
         if (b){
            return R.success("操作成功");
@@ -196,5 +196,4 @@ public class CorporationInfoController extends BladeController {
             return  R.fail("操作失败");
         }
     }
-
 }

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

@@ -8,6 +8,7 @@ import org.springblade.control.entity.ContractReturnedInfo;
 import org.springblade.control.entity.DepartmentMonthPlan;
 import org.springblade.control.entity.DictInfo;
 import org.springblade.control.vo.*;
+import org.springblade.system.entity.Dept;
 
 import java.util.List;
 import java.util.Map;
@@ -41,4 +42,6 @@ public interface AnnualBudgetMapper extends BaseMapper<AnnualBudget> {
     List<AnnualBudget> getAllYearBudget(@Param("year") int year);
 
     Integer yearList();
+
+    List<Dept> getAllDept();
 }

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

@@ -86,6 +86,9 @@
         WHERE is_deleted = 0 and start_time is not null order by start_time
             limit 1
     </select>
+    <select id="getAllDept" resultType="org.springblade.system.entity.Dept">
+        select * from blade_dept WHERE dept_type = 2 and is_deleted = 0
+    </select>
 
 
 </mapper>

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

@@ -162,7 +162,7 @@
         select * from c_project_cost_budget pcb WHERE  pcb.is_deleted =0 and pcb.project_id = #{id} and pcb.parent_id = 0
     </select>
     <select id="getProjectAllFinishedTask" resultType="org.springblade.control.entity.ProjectCostBudget">
-        select * from c_project_cost_budget pcb WHERE  pcb.is_deleted =0 and pcb.project_id = #{projectId}
+        select * from c_project_cost_budget pcb WHERE  pcb.is_deleted =0 and pcb.project_id = #{projectId}  and (select cdi.dict_value from c_dict_info cdi WHERE cdi.id = pcb.plan_task_type) = 1
         <if test="costType != null and costType != ''">
             and cost_type = #{costType}
         </if>

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

@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
 import org.springblade.control.dto.ControlProjectInfoDTO;
 import org.springblade.control.entity.ControlProjectInfo;
 import org.springblade.control.entity.DictInfo;
+import org.springblade.control.entity.EMFinancialReimbursementInfo;
 import org.springblade.control.vo.AllProjectStatsVO;
 import org.springblade.control.vo.ControlProjectInfoVO;
 import org.springblade.core.mp.base.BaseService;
@@ -66,5 +67,9 @@ public interface IProjectInfoService extends BaseService<ControlProjectInfo> {
     //根据项目id获取项目截至目前-某个费用分类的的报销支出,按项目环节返回
     Map<Long,BigDecimal> getProjectReimburseByCostType(Long projectId,Integer costType);
 
+    //根据年,获取每月的报销支出
     List<BigDecimal> getAllMonthReimburseByYear(int y);
+
+    //获取当年所有的报销,直接返回
+    List<EMFinancialReimbursementInfo> getThisYearReimburse2(int year);
 }

+ 468 - 376
blade-service/blade-control/src/main/java/org/springblade/control/service/impl/AnnualBudgetServiceImpl.java

@@ -12,6 +12,7 @@ import org.springblade.control.service.*;
 import org.springblade.control.vo.*;
 import org.springblade.core.log.exception.ServiceException;
 import org.springblade.core.mp.base.BaseServiceImpl;
+import org.springblade.system.entity.Dept;
 import org.springframework.beans.BeanUtils;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -549,8 +550,25 @@ public class AnnualBudgetServiceImpl extends BaseServiceImpl<AnnualBudgetMapper,
                 BigDecimal big = new BigDecimal(0);
                 if (budgets != null && budgets.size() > 0) {
                     for (ProjectCostBudget budget : budgets) {
-                        if (budget.getPracticalFinishTime().getMonthValue() == i) {
-                            big = big.add(budget.getActualTotalMoney());
+                        //计算人工支出
+                        if (budget.getRealPlanStartTime().getYear() != y || budget.getPracticalFinishTime().getYear() != y){
+                            if (budget.getIsTwoMonth() != 1){
+                                throw new ServiceException("计划年份异常2");
+                            }
+                            if (budget.getPracticalFinishTime().getYear() != y){
+                                //如果结束时间不是今年,则使用开始金额
+                                if (budget.getRealPlanStartTime().getMonthValue() == i) {
+                                    big = big.add(budget.getPracticalStartMoney());
+                                }
+                            }else {
+                                if (budget.getPracticalFinishTime().getMonthValue() == i) {
+                                    big = big.add(budget.getPracticalEndMoney());
+                                }
+                            }
+                        }else {
+                            if (budget.getPracticalFinishTime().getMonthValue() == i) {
+                                big = big.add(budget.getActualTotalMoney());
+                            }
                         }
                     }
                 }
@@ -713,6 +731,7 @@ public class AnnualBudgetServiceImpl extends BaseServiceImpl<AnnualBudgetMapper,
      */
     @Override
     public List<ProjectIncomeCostRatioVO> portalProjectCostRatio(String date) {
+        int y = Integer.parseInt(date.substring(0,4));
 //        if ("汇总所有".equals(date)){
 //            date = "";
 //        }
@@ -735,7 +754,7 @@ public class AnnualBudgetServiceImpl extends BaseServiceImpl<AnnualBudgetMapper,
         }
         List<ProjectIncomeCostRatioVO> vos = new ArrayList<>();
         //按年获取闭环任务,根据项目分组
-        List<ProjectCostBudget> costByMonth = budgetService.getPlanPracticalCostByMonth(date.substring(0,4));
+        List<ProjectCostBudget> costByMonth = budgetService.getBudgetByYear(y);
         if (costByMonth == null || costByMonth.size() <= 0){
             //没有闭环任务,为每个项目设置为0
             for (ControlProjectInfo info : list) {
@@ -763,7 +782,21 @@ public class AnnualBudgetServiceImpl extends BaseServiceImpl<AnnualBudgetMapper,
             List<ProjectCostBudget> budgets = map.get(info.getId());
             if (budgets != null && budgets.size() > 0){
                 for (ProjectCostBudget budget : budgets) {
-                    big = big.add(budget.getActualTotalMoney());
+//                    big = big.add(budget.getActualTotalMoney());
+                    if (budget.getRealPlanStartTime().getYear() != y || budget.getPracticalFinishTime().getYear() != y){
+                        if (budget.getIsTwoMonth() != 1){
+                            throw new ServiceException("计划年份异常3");
+                        }
+                        if (budget.getPracticalFinishTime().getYear() != y){
+                            //如果结束时间不是今年,则使用开始金额
+                            big = big.add(budget.getPracticalStartMoney());
+                        }else {
+                            big = big.add(budget.getPracticalEndMoney());
+                        }
+                    }else {
+                        big = big.add(budget.getActualTotalMoney());
+                    }
+
                 }
             }
             //维护支出
@@ -845,7 +878,7 @@ public class AnnualBudgetServiceImpl extends BaseServiceImpl<AnnualBudgetMapper,
         }else {
             isPlan2 = false;
         }
-        //获取项目所有已经闭环的计划
+        //获取项目所有已经闭环的固定计划
         List<ProjectCostBudget> finishedTask = budgetService.getProjectAllFinishedTask(projectId, null);
         Map<Long, List<ProjectCostBudget>> collect = new HashMap<>();
         boolean isPlan = true ;
@@ -1102,474 +1135,533 @@ public class AnnualBudgetServiceImpl extends BaseServiceImpl<AnnualBudgetMapper,
         List<String> months = Arrays.asList("一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月");
         //获取当年所有已经选择时间的固定计划
         List<ProjectCostBudget> allPlan = budgetService.getAllPlanByYear(y);
-        //如果当年没有计划,则把所有设置为0
+        Boolean isBudget = true;
+        Map<Integer, List<ProjectCostBudget>> allPlanMap = new HashMap<>();
         if (allPlan != null && allPlan.size() > 0){
-            //根据costType分组
-            Map<Integer, List<ProjectCostBudget>> allPlanMap = allPlan.parallelStream()
+            //如果不为空,根据costType分组
+            allPlanMap = allPlan.parallelStream()
                     .collect(Collectors.groupingBy(ProjectCostBudget::getCostType));
-            //获取当年所有已经完成的固定计划
-            //根据costType分组
-            List<ProjectCostBudget> allFinishedPlan = budgetService.getAllFinishedPlanByYear(y);
-            Boolean isFinished = true;
-            Map<Integer, List<ProjectCostBudget>> finishedMap = new HashMap<>();
-            if (allFinishedPlan != null && allFinishedPlan.size() > 0){
-                finishedMap = allFinishedPlan.parallelStream()
-                        .collect(Collectors.groupingBy(ProjectCostBudget::getCostType));
-            }else {
-                isFinished = false;
-            }
-            //维护支出,返回null证明没有
-            Map<Integer, List<BigDecimal>> maintainMap = budgetService.getAllMaintainCost9(y);
-            Boolean isMaintain = true;
-            if (maintainMap == null || maintainMap.size() <= 0){
-                isMaintain = false;
+        }else {
+            isBudget = false;
+        }
+        //维护支出,返回null证明没有
+        Map<Integer, List<BigDecimal>> maintainMap = budgetService.getAllMaintainCost9(y);
+        Boolean isMaintain = true;
+        if (maintainMap == null || maintainMap.size() <= 0){
+            isMaintain = false;
+        }
+        //获取当年所有已经完成的固定计划
+        //根据costType分组
+        List<ProjectCostBudget> allFinishedPlan = budgetService.getAllFinishedPlanByYear(y);
+        Boolean isFinished = true;
+        Map<Integer, List<ProjectCostBudget>> finishedMap = new HashMap<>();
+        if (allFinishedPlan != null && allFinishedPlan.size() > 0){
+            finishedMap = allFinishedPlan.parallelStream()
+                    .collect(Collectors.groupingBy(ProjectCostBudget::getCostType));
+        }else {
+            isFinished = false;
+        }
+        //获取所有部门
+        List<Dept> allDept = baseMapper.getAllDept();
+        if (allDept == null || allDept.size() <= 0){
+            throw new ServiceException("当前没配置部门,无法统计");
+        }
+        Map<Long, List<Dept>> deptMap = allDept.parallelStream()
+                .collect(Collectors.groupingBy(Dept::getId));
+        //报销支出
+        List<EMFinancialReimbursementInfo> allReimburse = projectInfoService.getThisYearReimburse2(y);
+        Boolean isReimburse = true;
+        Map<Integer, List<EMFinancialReimbursementInfo>> ReimburseMap = new HashMap<>();
+        if (allReimburse != null && allReimburse.size() > 0){
+            //对部门和费用类型做映射
+            for (EMFinancialReimbursementInfo info : allReimburse) {
+                if (info.getCreateDept() != null){
+                    info.setIsTemp(deptMap.get(info.getCreateDept()).get(0).getDeptCategory());
+                }else {
+                    throw new ServiceException("有用户没有部门直接报销,无法统计");
+                }
             }
-            //报销支出
+            ReimburseMap = allReimburse.parallelStream()
+                    .collect(Collectors.groupingBy(EMFinancialReimbursementInfo::getIsTemp));
+        }else {
+            isReimburse = false;
+        }
 
-            BigDecimal c1 = new BigDecimal(0);
-            BigDecimal c2 = new BigDecimal(0);
-            BigDecimal c3 = new BigDecimal(0);
-            BigDecimal c4 = new BigDecimal(0);
-            BigDecimal c5 = new BigDecimal(0);
-            BigDecimal c6 = new BigDecimal(0);
-            BigDecimal c7 = new BigDecimal(0);
-            BigDecimal c8 = new BigDecimal(0);
-            BigDecimal c9 = new BigDecimal(0);
-            BigDecimal c10 = new BigDecimal(0);
-            //循环12个月,为每个月设置值
-            for (int i = 0; i < 12; i++) {
-                BudgetAndPracticalByDeptVO vo = new BudgetAndPracticalByDeptVO();
-                //设置月份
-                vo.setTime(months.get(i));
-                //设置市场部
+        BigDecimal c1 = new BigDecimal(0);
+        BigDecimal c2 = new BigDecimal(0);
+        BigDecimal c3 = new BigDecimal(0);
+        BigDecimal c4 = new BigDecimal(0);
+        BigDecimal c5 = new BigDecimal(0);
+        BigDecimal c6 = new BigDecimal(0);
+        BigDecimal c7 = new BigDecimal(0);
+        BigDecimal c8 = new BigDecimal(0);
+        BigDecimal c9 = new BigDecimal(0);
+        BigDecimal c10 = new BigDecimal(0);
+        //循环12个月,为每个月设置值
+        for (int i = 0; i < 12; i++) {
+            BudgetAndPracticalByDeptVO vo = new BudgetAndPracticalByDeptVO();
+            //设置月份
+            vo.setTime(months.get(i));
+            //设置市场部
+            if (isBudget && allPlanMap.get(1) != null && allPlanMap.get(1).size() > 0) {
                 List<ProjectCostBudget> b1 = allPlanMap.get(1);
-                if (b1 != null && b1.size() > 0){
+                BigDecimal big = new BigDecimal(0);
+                //循环市场部每一个预算
+                for (ProjectCostBudget budget : b1) {
+                    //如果开始时间或结束时间是当月,则添加预算
+                    if ((budget.getPlanStartTime().getMonthValue() == (i + 1) && budget.getPlanStartTime().getYear() == y)
+                            || (budget.getPlanEndTime().getMonthValue() == (i + 1) && budget.getPlanEndTime().getYear() == y)) {
+                        //如果开始时间和结束时间的月相同,则直接用总预算
+                        if (budget.getPlanIsTwoMonth() == 0) {
+                            big = big.add(budget.getPlanStaffCost());
+                        } else {
+                            //如果开始月是当前月,则直接使用开始金额
+                            if (budget.getPlanStartTime().getMonthValue() == (i + 1) && budget.getPlanStartTime().getYear() == y) {
+                                big = big.add(budget.getPlanStartMoney());
+                            } else {
+                                //结束月是当前月,使用结束金额
+                                big = big.add(budget.getPlanEndMoney());
+                            }
+                        }
+                    }
+                }
+                vo.setBudget1(big);
+                c1 = c1.add(big);
+            }else {
+                 vo.setBudget1(new BigDecimal(0));
+            }
+            if (isFinished){
+                List<ProjectCostBudget> d1 = finishedMap.get(1);
+                if (d1 != null && d1.size() > 0){
                     BigDecimal big = new BigDecimal(0);
-                    //循环市场部每一个预算
-                    for (ProjectCostBudget budget : b1) {
-                        //如果开始时间或结束时间是当月,则添加预算
-                        if ((budget.getPlanStartTime().getMonthValue() == (i+1) && budget.getPlanStartTime().getYear() == y)
-                            || (budget.getPlanEndTime().getMonthValue() == (i+1) && budget.getPlanEndTime().getYear() == y)){
+                    //循环市场部每一个支出
+                    for (ProjectCostBudget budget : d1) {
+                        //如果实际开始时间或实际结束时间是当月,则添加支出
+                        if ((budget.getRealPlanStartTime().getMonthValue() == (i+1) && budget.getRealPlanStartTime().getYear() == y)
+                                || (budget.getPracticalFinishTime().getMonthValue() == (i+1) && budget.getPracticalFinishTime().getYear() == y)){
                             //如果开始时间和结束时间的月相同,则直接用总预算
-                            if (budget.getPlanIsTwoMonth() == 0){
-                                big = big.add(budget.getPlanStaffCost());
+                            if (budget.getIsTwoMonth() == 0){
+                                big = big.add(budget.getActualTotalMoney());
                             }else {
                                 //如果开始月是当前月,则直接使用开始金额
-                                if (budget.getPlanStartTime().getMonthValue() == (i+1) && budget.getPlanStartTime().getYear() == y){
-                                    big = big.add(budget.getPlanStartMoney());
+                                if (budget.getRealPlanStartTime().getMonthValue() == (i+1) && budget.getRealPlanStartTime().getYear() == y){
+                                    big = big.add(budget.getPracticalStartMoney());
                                 }else {
                                     //结束月是当前月,使用结束金额
-                                    big = big.add(budget.getPlanEndMoney());
-                                }
-                            }
-                        }
-                    }
-                    vo.setBudget1(big);
-                    c1 = c1.add(big);
-                }else {
-                    vo.setBudget1(new BigDecimal(0));
-                }
-                if (isFinished){
-                    List<ProjectCostBudget> d1 = finishedMap.get(1);
-                    if (d1 != null && d1.size() > 0){
-                        BigDecimal big = new BigDecimal(0);
-                        //循环市场部每一个支出
-                        for (ProjectCostBudget budget : d1) {
-                            //如果实际开始时间或实际结束时间是当月,则添加支出
-                            if ((budget.getRealPlanStartTime().getMonthValue() == (i+1) && budget.getRealPlanStartTime().getYear() == y)
-                                    || (budget.getPracticalFinishTime().getMonthValue() == (i+1) && budget.getPracticalFinishTime().getYear() == y)){
-                                //如果开始时间和结束时间的月相同,则直接用总预算
-                                if (budget.getIsTwoMonth() == 0){
-                                    big = big.add(budget.getActualTotalMoney());
-                                }else {
-                                    //如果开始月是当前月,则直接使用开始金额
-                                    if (budget.getRealPlanStartTime().getMonthValue() == (i+1) && budget.getRealPlanStartTime().getYear() == y){
-                                        big = big.add(budget.getPracticalStartMoney());
-                                    }else {
-                                        //结束月是当前月,使用结束金额
-                                        big = big.add(budget.getPracticalEndMoney());
-                                    }
+                                    big = big.add(budget.getPracticalEndMoney());
                                 }
                             }
                         }
-                        vo.setPractical1(big);
-                        c2 = c2.add(big);
-                    }else {
-                        vo.setPractical1(new BigDecimal(0));
                     }
+                    vo.setPractical1(big);
+                    c2 = c2.add(big);
                 }else {
                     vo.setPractical1(new BigDecimal(0));
                 }
-                //设置维护支出
-                if (isMaintain && maintainMap.get(1) != null && maintainMap.get(1).size() > 0){
-                    vo.setBudget1(vo.getBudget1().add(maintainMap.get(1).get(i)));
-                    vo.setPractical1(vo.getPractical1().add(maintainMap.get(1).get(i)));
-                    c1 = c1.add(maintainMap.get(1).get(i));
-                    c2 = c2.add(maintainMap.get(1).get(i));
+            }else {
+                vo.setPractical1(new BigDecimal(0));
+            }
+            //设置维护支出
+            if (isMaintain && maintainMap.get(1) != null && maintainMap.get(1).size() > 0){
+                vo.setBudget1(vo.getBudget1().add(maintainMap.get(1).get(i)));
+                vo.setPractical1(vo.getPractical1().add(maintainMap.get(1).get(i)));
+                c1 = c1.add(maintainMap.get(1).get(i));
+                c2 = c2.add(maintainMap.get(1).get(i));
+            }
+            //设置报销支出
+            if (isReimburse && ReimburseMap.get(1) != null && ReimburseMap.get(1).size() > 0){
+                List<EMFinancialReimbursementInfo> infos = ReimburseMap.get(1);
+                BigDecimal big = new BigDecimal(0);
+                for (EMFinancialReimbursementInfo info : infos) {
+                    if (info.getFrDate().getMonth() == i){
+                        big = big.add(info.getFrMoney());
+                    }
                 }
+                vo.setPractical1(vo.getPractical1().add(big));
+                c2 = c2.add(big);
+            }
 
-                //设置研发部
+            //设置研发部
+            if (isBudget && allPlanMap.get(2) != null && allPlanMap.get(2).size() > 0) {
                 List<ProjectCostBudget> b2 = allPlanMap.get(2);
-                if (b2 != null && b2.size() > 0){
+                BigDecimal big = new BigDecimal(0);
+                //循环研发部每一个预算
+                for (ProjectCostBudget budget : b2) {
+                    //如果开始时间或结束时间是当月,则添加预算
+                    if ((budget.getPlanStartTime().getMonthValue() == (i+1) && budget.getPlanStartTime().getYear() == y)
+                            || (budget.getPlanEndTime().getMonthValue() == (i+1) && budget.getPlanEndTime().getYear() == y)){
+                        //如果开始时间和结束时间的月相同,则直接用总预算
+                        if (budget.getPlanIsTwoMonth() == 0){
+                            big = big.add(budget.getPlanStaffCost());
+                        }else {
+                            //如果开始月是当前月,则直接使用开始金额
+                            if (budget.getPlanStartTime().getMonthValue() == (i+1) && budget.getPlanStartTime().getYear() == y){
+                                big = big.add(budget.getPlanStartMoney());
+                            }else {
+                                //结束月是当前月,使用结束金额
+                                big = big.add(budget.getPlanEndMoney());
+                            }
+                        }
+                    }
+                }
+                vo.setBudget2(big);
+                c3 = c3.add(big);
+            }else {
+                vo.setBudget2(new BigDecimal(0));
+            }
+            if (isFinished){
+                List<ProjectCostBudget> d2 = finishedMap.get(2);
+                if (d2 != null && d2.size() > 0){
                     BigDecimal big = new BigDecimal(0);
-                    //循环研发部每一个预算
-                    for (ProjectCostBudget budget : b2) {
-                        //如果开始时间或结束时间是当月,则添加预算
-                        if ((budget.getPlanStartTime().getMonthValue() == (i+1) && budget.getPlanStartTime().getYear() == y)
-                                || (budget.getPlanEndTime().getMonthValue() == (i+1) && budget.getPlanEndTime().getYear() == y)){
+                    //循环市场部每一个支出
+                    for (ProjectCostBudget budget : d2) {
+                        //如果实际开始时间或实际结束时间是当月,则添加支出
+                        if ((budget.getRealPlanStartTime().getMonthValue() == (i+1) && budget.getRealPlanStartTime().getYear() == y)
+                                || (budget.getPracticalFinishTime().getMonthValue() == (i+1) && budget.getPracticalFinishTime().getYear() == y)){
                             //如果开始时间和结束时间的月相同,则直接用总预算
-                            if (budget.getPlanIsTwoMonth() == 0){
-                                big = big.add(budget.getPlanStaffCost());
+                            if (budget.getIsTwoMonth() == 0){
+                                big = big.add(budget.getActualTotalMoney());
                             }else {
                                 //如果开始月是当前月,则直接使用开始金额
-                                if (budget.getPlanStartTime().getMonthValue() == (i+1) && budget.getPlanStartTime().getYear() == y){
-                                    big = big.add(budget.getPlanStartMoney());
+                                if (budget.getRealPlanStartTime().getMonthValue() == (i+1) && budget.getRealPlanStartTime().getYear() == y){
+                                    big = big.add(budget.getPracticalStartMoney());
                                 }else {
                                     //结束月是当前月,使用结束金额
-                                    big = big.add(budget.getPlanEndMoney());
-                                }
-                            }
-                        }
-                    }
-                    vo.setBudget2(big);
-                    c3 = c3.add(big);
-                }else {
-                    vo.setBudget2(new BigDecimal(0));
-                }
-                if (isFinished){
-                    List<ProjectCostBudget> d2 = finishedMap.get(2);
-                    if (d2 != null && d2.size() > 0){
-                        BigDecimal big = new BigDecimal(0);
-                        //循环市场部每一个支出
-                        for (ProjectCostBudget budget : d2) {
-                            //如果实际开始时间或实际结束时间是当月,则添加支出
-                            if ((budget.getRealPlanStartTime().getMonthValue() == (i+1) && budget.getRealPlanStartTime().getYear() == y)
-                                    || (budget.getPracticalFinishTime().getMonthValue() == (i+1) && budget.getPracticalFinishTime().getYear() == y)){
-                                //如果开始时间和结束时间的月相同,则直接用总预算
-                                if (budget.getIsTwoMonth() == 0){
-                                    big = big.add(budget.getActualTotalMoney());
-                                }else {
-                                    //如果开始月是当前月,则直接使用开始金额
-                                    if (budget.getRealPlanStartTime().getMonthValue() == (i+1) && budget.getRealPlanStartTime().getYear() == y){
-                                        big = big.add(budget.getPracticalStartMoney());
-                                    }else {
-                                        //结束月是当前月,使用结束金额
-                                        big = big.add(budget.getPracticalEndMoney());
-                                    }
+                                    big = big.add(budget.getPracticalEndMoney());
                                 }
                             }
                         }
-                        vo.setPractical2(big);
-                        c4 = c4.add(big);
-                    }else {
-                        vo.setPractical2(new BigDecimal(0));
                     }
+                    vo.setPractical2(big);
+                    c4 = c4.add(big);
                 }else {
                     vo.setPractical2(new BigDecimal(0));
                 }
-                //设置维护支出
-                if (isMaintain && maintainMap.get(2) != null && maintainMap.get(2).size() > 0){
-                    vo.setBudget2(vo.getBudget2().add(maintainMap.get(2).get(i)));
-                    vo.setPractical2(vo.getPractical2().add(maintainMap.get(2).get(i)));
-                    c3 = c3.add(maintainMap.get(2).get(i));
-                    c4 = c4.add(maintainMap.get(2).get(i));
+            }else {
+                vo.setPractical2(new BigDecimal(0));
+            }
+            //设置维护支出
+            if (isMaintain && maintainMap.get(2) != null && maintainMap.get(2).size() > 0){
+                vo.setBudget2(vo.getBudget2().add(maintainMap.get(2).get(i)));
+                vo.setPractical2(vo.getPractical2().add(maintainMap.get(2).get(i)));
+                c3 = c3.add(maintainMap.get(2).get(i));
+                c4 = c4.add(maintainMap.get(2).get(i));
+            }
+            //设置报销支出
+            if (isReimburse && ReimburseMap.get(2) != null && ReimburseMap.get(2).size() > 0){
+                List<EMFinancialReimbursementInfo> infos = ReimburseMap.get(2);
+                BigDecimal big = new BigDecimal(0);
+                for (EMFinancialReimbursementInfo info : infos) {
+                    if (info.getFrDate().getMonth() == i){
+                        big = big.add(info.getFrMoney());
+                    }
                 }
+                vo.setPractical2(vo.getPractical2().add(big));
+                c4 = c4.add(big);
+            }
+
 
-                //设置实施部
+            //设置实施部
+            if (isBudget && allPlanMap.get(3) != null && allPlanMap.get(3).size() > 0) {
                 List<ProjectCostBudget> b3 = allPlanMap.get(3);
-                if (b3 != null && b3.size() > 0){
+                BigDecimal big = new BigDecimal(0);
+                //循环研发部每一个预算
+                for (ProjectCostBudget budget : b3) {
+                    //如果开始时间或结束时间是当月,则添加预算
+                    if ((budget.getPlanStartTime().getMonthValue() == (i+1) && budget.getPlanStartTime().getYear() == y)
+                            || (budget.getPlanEndTime().getMonthValue() == (i+1) && budget.getPlanEndTime().getYear() == y)){
+                        //如果开始时间和结束时间的月相同,则直接用总预算
+                        if (budget.getPlanIsTwoMonth() == 0){
+                            big = big.add(budget.getPlanStaffCost());
+                        }else {
+                            //如果开始月是当前月,则直接使用开始金额
+                            if (budget.getPlanStartTime().getMonthValue() == (i+1) && budget.getPlanStartTime().getYear() == y){
+                                big = big.add(budget.getPlanStartMoney());
+                            }else {
+                                //结束月是当前月,使用结束金额
+                                big = big.add(budget.getPlanEndMoney());
+                            }
+                        }
+                    }
+                }
+                vo.setBudget3(big);
+                c5 = c5.add(big);
+            }else {
+                vo.setBudget3(new BigDecimal(0));
+            }
+            if (isFinished){
+                List<ProjectCostBudget> d3 = finishedMap.get(3);
+                if (d3 != null && d3.size() > 0){
                     BigDecimal big = new BigDecimal(0);
-                    //循环研发部每一个预算
-                    for (ProjectCostBudget budget : b3) {
-                        //如果开始时间或结束时间是当月,则添加预算
-                        if ((budget.getPlanStartTime().getMonthValue() == (i+1) && budget.getPlanStartTime().getYear() == y)
-                                || (budget.getPlanEndTime().getMonthValue() == (i+1) && budget.getPlanEndTime().getYear() == y)){
+                    //循环每一个支出
+                    for (ProjectCostBudget budget : d3) {
+                        //如果实际开始时间或实际结束时间是当月,则添加支出
+                        if ((budget.getRealPlanStartTime().getMonthValue() == (i+1) && budget.getRealPlanStartTime().getYear() == y)
+                                || (budget.getPracticalFinishTime().getMonthValue() == (i+1) && budget.getPracticalFinishTime().getYear() == y)){
                             //如果开始时间和结束时间的月相同,则直接用总预算
-                            if (budget.getPlanIsTwoMonth() == 0){
-                                big = big.add(budget.getPlanStaffCost());
+                            if (budget.getIsTwoMonth() == 0){
+                                big = big.add(budget.getActualTotalMoney());
                             }else {
                                 //如果开始月是当前月,则直接使用开始金额
-                                if (budget.getPlanStartTime().getMonthValue() == (i+1) && budget.getPlanStartTime().getYear() == y){
-                                    big = big.add(budget.getPlanStartMoney());
+                                if (budget.getRealPlanStartTime().getMonthValue() == (i+1) && budget.getRealPlanStartTime().getYear() == y){
+                                    big = big.add(budget.getPracticalStartMoney());
                                 }else {
                                     //结束月是当前月,使用结束金额
-                                    big = big.add(budget.getPlanEndMoney());
+                                    big = big.add(budget.getPracticalEndMoney());
                                 }
                             }
                         }
                     }
-                    vo.setBudget3(big);
-                    c5 = c5.add(big);
-                }else {
-                    vo.setBudget3(new BigDecimal(0));
-                }
-                if (isFinished){
-                    List<ProjectCostBudget> d3 = finishedMap.get(3);
-                    if (d3 != null && d3.size() > 0){
-                        BigDecimal big = new BigDecimal(0);
-                        //循环每一个支出
-                        for (ProjectCostBudget budget : d3) {
-                            //如果实际开始时间或实际结束时间是当月,则添加支出
-                            if ((budget.getRealPlanStartTime().getMonthValue() == (i+1) && budget.getRealPlanStartTime().getYear() == y)
-                                    || (budget.getPracticalFinishTime().getMonthValue() == (i+1) && budget.getPracticalFinishTime().getYear() == y)){
-                                //如果开始时间和结束时间的月相同,则直接用总预算
-                                if (budget.getIsTwoMonth() == 0){
-                                    big = big.add(budget.getActualTotalMoney());
-                                }else {
-                                    //如果开始月是当前月,则直接使用开始金额
-                                    if (budget.getRealPlanStartTime().getMonthValue() == (i+1) && budget.getRealPlanStartTime().getYear() == y){
-                                        big = big.add(budget.getPracticalStartMoney());
-                                    }else {
-                                        //结束月是当前月,使用结束金额
-                                        big = big.add(budget.getPracticalEndMoney());
-                                    }
-                                }
-                            }
-                        }
-                        vo.setPractical3(big);
-                        c6 = c6.add(big);
-                    }else {
-                        vo.setPractical3(new BigDecimal(0));
-                    }
+                    vo.setPractical3(big);
+                    c6 = c6.add(big);
                 }else {
                     vo.setPractical3(new BigDecimal(0));
                 }
-                //设置维护支出
-                if (isMaintain && maintainMap.get(3) != null && maintainMap.get(3).size() > 0){
-                    vo.setBudget3(vo.getBudget3().add(maintainMap.get(3).get(i)));
-                    vo.setPractical3(vo.getPractical3().add(maintainMap.get(3).get(i)));
-                    c5 = c5.add(maintainMap.get(3).get(i));
-                    c6 = c6.add(maintainMap.get(3).get(i));
+            }else {
+                vo.setPractical3(new BigDecimal(0));
+            }
+            //设置维护支出
+            if (isMaintain && maintainMap.get(3) != null && maintainMap.get(3).size() > 0){
+                vo.setBudget3(vo.getBudget3().add(maintainMap.get(3).get(i)));
+                vo.setPractical3(vo.getPractical3().add(maintainMap.get(3).get(i)));
+                c5 = c5.add(maintainMap.get(3).get(i));
+                c6 = c6.add(maintainMap.get(3).get(i));
+            }
+            //设置报销支出
+            if (isReimburse && ReimburseMap.get(3) != null && ReimburseMap.get(3).size() > 0){
+                List<EMFinancialReimbursementInfo> infos = ReimburseMap.get(3);
+                BigDecimal big = new BigDecimal(0);
+                for (EMFinancialReimbursementInfo info : infos) {
+                    if (info.getFrDate().getMonth() == i){
+                        big = big.add(info.getFrMoney());
+                    }
                 }
+                vo.setPractical3(vo.getPractical3().add(big));
+                c6 = c6.add(big);
+            }
 
-                //设置维护部
+
+            //设置维护部
+            if (isBudget && allPlanMap.get(4) != null && allPlanMap.get(4).size() > 0) {
                 List<ProjectCostBudget> b4 = allPlanMap.get(4);
-                if (b4 != null && b4.size() > 0){
+                BigDecimal big = new BigDecimal(0);
+                //循环每一个预算
+                for (ProjectCostBudget budget : b4) {
+                    //如果开始时间或结束时间是当月,则添加预算
+                    if ((budget.getPlanStartTime().getMonthValue() == (i+1) && budget.getPlanStartTime().getYear() == y)
+                            || (budget.getPlanEndTime().getMonthValue() == (i+1) && budget.getPlanEndTime().getYear() == y)){
+                        //如果开始时间和结束时间的月相同,则直接用总预算
+                        if (budget.getPlanIsTwoMonth() == 0){
+                            big = big.add(budget.getPlanStaffCost());
+                        }else {
+                            //如果开始月是当前月,则直接使用开始金额
+                            if (budget.getPlanStartTime().getMonthValue() == (i+1) && budget.getPlanStartTime().getYear() == y){
+                                big = big.add(budget.getPlanStartMoney());
+                            }else {
+                                //结束月是当前月,使用结束金额
+                                big = big.add(budget.getPlanEndMoney());
+                            }
+                        }
+                    }
+                }
+                vo.setBudget4(big);
+                c7 = c7.add(big);
+            }else {
+                vo.setBudget4(new BigDecimal(0));
+            }
+            if (isFinished){
+                List<ProjectCostBudget> d4 = finishedMap.get(4);
+                if (d4 != null && d4.size() > 0){
                     BigDecimal big = new BigDecimal(0);
-                    //循环每一个预算
-                    for (ProjectCostBudget budget : b4) {
-                        //如果开始时间或结束时间是当月,则添加预算
-                        if ((budget.getPlanStartTime().getMonthValue() == (i+1) && budget.getPlanStartTime().getYear() == y)
-                                || (budget.getPlanEndTime().getMonthValue() == (i+1) && budget.getPlanEndTime().getYear() == y)){
+                    //循环每一个支出
+                    for (ProjectCostBudget budget : d4) {
+                        //如果实际开始时间或实际结束时间是当月,则添加支出
+                        if ((budget.getRealPlanStartTime().getMonthValue() == (i+1) && budget.getRealPlanStartTime().getYear() == y)
+                                || (budget.getPracticalFinishTime().getMonthValue() == (i+1) && budget.getPracticalFinishTime().getYear() == y)){
                             //如果开始时间和结束时间的月相同,则直接用总预算
-                            if (budget.getPlanIsTwoMonth() == 0){
-                                big = big.add(budget.getPlanStaffCost());
+                            if (budget.getIsTwoMonth() == 0){
+                                big = big.add(budget.getActualTotalMoney());
                             }else {
                                 //如果开始月是当前月,则直接使用开始金额
-                                if (budget.getPlanStartTime().getMonthValue() == (i+1) && budget.getPlanStartTime().getYear() == y){
-                                    big = big.add(budget.getPlanStartMoney());
+                                if (budget.getRealPlanStartTime().getMonthValue() == (i+1) && budget.getRealPlanStartTime().getYear() == y){
+                                    big = big.add(budget.getPracticalStartMoney());
                                 }else {
                                     //结束月是当前月,使用结束金额
-                                    big = big.add(budget.getPlanEndMoney());
+                                    big = big.add(budget.getPracticalEndMoney());
                                 }
                             }
                         }
                     }
-                    vo.setBudget4(big);
-                    c7 = c7.add(big);
-                }else {
-                    vo.setBudget4(new BigDecimal(0));
-                }
-                if (isFinished){
-                    List<ProjectCostBudget> d4 = finishedMap.get(4);
-                    if (d4 != null && d4.size() > 0){
-                        BigDecimal big = new BigDecimal(0);
-                        //循环每一个支出
-                        for (ProjectCostBudget budget : d4) {
-                            //如果实际开始时间或实际结束时间是当月,则添加支出
-                            if ((budget.getRealPlanStartTime().getMonthValue() == (i+1) && budget.getRealPlanStartTime().getYear() == y)
-                                    || (budget.getPracticalFinishTime().getMonthValue() == (i+1) && budget.getPracticalFinishTime().getYear() == y)){
-                                //如果开始时间和结束时间的月相同,则直接用总预算
-                                if (budget.getIsTwoMonth() == 0){
-                                    big = big.add(budget.getActualTotalMoney());
-                                }else {
-                                    //如果开始月是当前月,则直接使用开始金额
-                                    if (budget.getRealPlanStartTime().getMonthValue() == (i+1) && budget.getRealPlanStartTime().getYear() == y){
-                                        big = big.add(budget.getPracticalStartMoney());
-                                    }else {
-                                        //结束月是当前月,使用结束金额
-                                        big = big.add(budget.getPracticalEndMoney());
-                                    }
-                                }
-                            }
-                        }
-                        vo.setPractical4(big);
-                        c8 = c8.add(big);
-                    }else {
-                        vo.setPractical4(new BigDecimal(0));
-                    }
+                    vo.setPractical4(big);
+                    c8 = c8.add(big);
                 }else {
                     vo.setPractical4(new BigDecimal(0));
                 }
-                //设置维护支出
-                if (isMaintain && maintainMap.get(4) != null && maintainMap.get(4).size() > 0){
-                    vo.setBudget4(vo.getBudget4().add(maintainMap.get(4).get(i)));
-                    vo.setPractical4(vo.getPractical4().add(maintainMap.get(4).get(i)));
-                    c7 = c7.add(maintainMap.get(4).get(i));
-                    c8 = c8.add(maintainMap.get(4).get(i));
+            }else {
+                vo.setPractical4(new BigDecimal(0));
+            }
+            //设置维护支出
+            if (isMaintain && maintainMap.get(4) != null && maintainMap.get(4).size() > 0){
+                vo.setBudget4(vo.getBudget4().add(maintainMap.get(4).get(i)));
+                vo.setPractical4(vo.getPractical4().add(maintainMap.get(4).get(i)));
+                c7 = c7.add(maintainMap.get(4).get(i));
+                c8 = c8.add(maintainMap.get(4).get(i));
+            }
+            //设置报销支出
+            if (isReimburse && ReimburseMap.get(4) != null && ReimburseMap.get(4).size() > 0){
+                List<EMFinancialReimbursementInfo> infos = ReimburseMap.get(4);
+                BigDecimal big = new BigDecimal(0);
+                for (EMFinancialReimbursementInfo info : infos) {
+                    if (info.getFrDate().getMonth() == i){
+                        big = big.add(info.getFrMoney());
+                    }
                 }
+                vo.setPractical4(vo.getPractical4().add(big));
+                c8 = c8.add(big);
+            }
+
 
-                //设置管理中心 = 管理支出+外包劳务
-                BigDecimal big1 = new BigDecimal(0);
-                BigDecimal big2 = new BigDecimal(0);
+            //设置管理中心 = 管理支出+外包劳务
+            BigDecimal big1 = new BigDecimal(0);
+            BigDecimal big2 = new BigDecimal(0);
+            if (isBudget && allPlanMap.get(5) != null && allPlanMap.get(5).size() > 0) {
                 List<ProjectCostBudget> b5 = allPlanMap.get(5);
-                if (b5 != null && b5.size() > 0){
-                    //循环研发部每一个预算
-                    for (ProjectCostBudget budget : b5) {
-                        //如果开始时间或结束时间是当月,则添加预算
-                        if ((budget.getPlanStartTime().getMonthValue() == (i+1) && budget.getPlanStartTime().getYear() == y)
-                                || (budget.getPlanEndTime().getMonthValue() == (i+1) && budget.getPlanEndTime().getYear() == y)){
+                //循环研发部每一个预算
+                for (ProjectCostBudget budget : b5) {
+                    //如果开始时间或结束时间是当月,则添加预算
+                    if ((budget.getPlanStartTime().getMonthValue() == (i+1) && budget.getPlanStartTime().getYear() == y)
+                            || (budget.getPlanEndTime().getMonthValue() == (i+1) && budget.getPlanEndTime().getYear() == y)){
+                        //如果开始时间和结束时间的月相同,则直接用总预算
+                        if (budget.getPlanIsTwoMonth() == 0){
+                            big1 = big1.add(budget.getPlanStaffCost());
+                        }else {
+                            //如果开始月是当前月,则直接使用开始金额
+                            if (budget.getPlanStartTime().getMonthValue() == (i+1) && budget.getPlanStartTime().getYear() == y){
+                                big1 = big1.add(budget.getPlanStartMoney());
+                            }else {
+                                //结束月是当前月,使用结束金额
+                                big1 = big1.add(budget.getPlanEndMoney());
+                            }
+                        }
+                    }
+                }
+            }
+            if (isFinished){
+                List<ProjectCostBudget> d5 = finishedMap.get(5);
+                if (d5 != null && d5.size() > 0){
+                    //循环市场部每一个支出
+                    for (ProjectCostBudget budget : d5) {
+                        //如果实际开始时间或实际结束时间是当月,则添加支出
+                        if ((budget.getRealPlanStartTime().getMonthValue() == (i+1) && budget.getRealPlanStartTime().getYear() == y)
+                                || (budget.getPracticalFinishTime().getMonthValue() == (i+1) && budget.getPracticalFinishTime().getYear() == y)){
                             //如果开始时间和结束时间的月相同,则直接用总预算
-                            if (budget.getPlanIsTwoMonth() == 0){
-                                big1 = big1.add(budget.getPlanStaffCost());
+                            if (budget.getIsTwoMonth() == 0){
+                                big2 = big2.add(budget.getActualTotalMoney());
                             }else {
                                 //如果开始月是当前月,则直接使用开始金额
-                                if (budget.getPlanStartTime().getMonthValue() == (i+1) && budget.getPlanStartTime().getYear() == y){
-                                    big1 = big1.add(budget.getPlanStartMoney());
+                                if (budget.getRealPlanStartTime().getMonthValue() == (i+1) && budget.getRealPlanStartTime().getYear() == y){
+                                    big2 = big2.add(budget.getPracticalStartMoney());
                                 }else {
                                     //结束月是当前月,使用结束金额
-                                    big1 = big1.add(budget.getPlanEndMoney());
+                                    big2 = big2.add(budget.getPracticalEndMoney());
                                 }
                             }
                         }
                     }
                 }
-                if (isFinished){
-                    List<ProjectCostBudget> d5 = finishedMap.get(5);
-                    if (d5 != null && d5.size() > 0){
-                        //循环市场部每一个支出
-                        for (ProjectCostBudget budget : d5) {
-                            //如果实际开始时间或实际结束时间是当月,则添加支出
-                            if ((budget.getRealPlanStartTime().getMonthValue() == (i+1) && budget.getRealPlanStartTime().getYear() == y)
-                                    || (budget.getPracticalFinishTime().getMonthValue() == (i+1) && budget.getPracticalFinishTime().getYear() == y)){
-                                //如果开始时间和结束时间的月相同,则直接用总预算
-                                if (budget.getIsTwoMonth() == 0){
-                                    big2 = big2.add(budget.getActualTotalMoney());
-                                }else {
-                                    //如果开始月是当前月,则直接使用开始金额
-                                    if (budget.getRealPlanStartTime().getMonthValue() == (i+1) && budget.getRealPlanStartTime().getYear() == y){
-                                        big2 = big2.add(budget.getPracticalStartMoney());
-                                    }else {
-                                        //结束月是当前月,使用结束金额
-                                        big2 = big2.add(budget.getPracticalEndMoney());
-                                    }
-                                }
+            }
+            if (isBudget && allPlanMap.get(6) != null && allPlanMap.get(6).size() > 0) {
+                List<ProjectCostBudget> b6 = allPlanMap.get(6);
+                //循环研发部每一个预算
+                for (ProjectCostBudget budget : b6) {
+                    //如果开始时间或结束时间是当月,则添加预算
+                    if ((budget.getPlanStartTime().getMonthValue() == (i+1) && budget.getPlanStartTime().getYear() == y)
+                            || (budget.getPlanEndTime().getMonthValue() == (i+1) && budget.getPlanEndTime().getYear() == y)){
+                        //如果开始时间和结束时间的月相同,则直接用总预算
+                        if (budget.getPlanIsTwoMonth() == 0){
+                            big1 = big1.add(budget.getPlanStaffCost());
+                        }else {
+                            //如果开始月是当前月,则直接使用开始金额
+                            if (budget.getPlanStartTime().getMonthValue() == (i+1) && budget.getPlanStartTime().getYear() == y){
+                                big1 = big1.add(budget.getPlanStartMoney());
+                            }else {
+                                //结束月是当前月,使用结束金额
+                                big1 = big1.add(budget.getPlanEndMoney());
                             }
                         }
                     }
                 }
-                List<ProjectCostBudget> b6 = allPlanMap.get(6);
-                if (b6 != null && b6.size() > 0){
-                    //循环研发部每一个预算
-                    for (ProjectCostBudget budget : b6) {
-                        //如果开始时间或结束时间是当月,则添加预算
-                        if ((budget.getPlanStartTime().getMonthValue() == (i+1) && budget.getPlanStartTime().getYear() == y)
-                                || (budget.getPlanEndTime().getMonthValue() == (i+1) && budget.getPlanEndTime().getYear() == y)){
+            }
+            if (isFinished){
+                List<ProjectCostBudget> d6 = finishedMap.get(6);
+                if (d6 != null && d6.size() > 0){
+                    //循环市场部每一个支出
+                    for (ProjectCostBudget budget : d6) {
+                        //如果实际开始时间或实际结束时间是当月,则添加支出
+                        if ((budget.getRealPlanStartTime().getMonthValue() == (i+1) && budget.getRealPlanStartTime().getYear() == y)
+                                || (budget.getPracticalFinishTime().getMonthValue() == (i+1) && budget.getPracticalFinishTime().getYear() == y)){
                             //如果开始时间和结束时间的月相同,则直接用总预算
-                            if (budget.getPlanIsTwoMonth() == 0){
-                                big1 = big1.add(budget.getPlanStaffCost());
+                            if (budget.getIsTwoMonth() == 0){
+                                big2 = big2.add(budget.getActualTotalMoney());
                             }else {
                                 //如果开始月是当前月,则直接使用开始金额
-                                if (budget.getPlanStartTime().getMonthValue() == (i+1) && budget.getPlanStartTime().getYear() == y){
-                                    big1 = big1.add(budget.getPlanStartMoney());
+                                if (budget.getRealPlanStartTime().getMonthValue() == (i+1) && budget.getRealPlanStartTime().getYear() == y){
+                                    big2 = big2.add(budget.getPracticalStartMoney());
                                 }else {
                                     //结束月是当前月,使用结束金额
-                                    big1 = big1.add(budget.getPlanEndMoney());
+                                    big2 = big2.add(budget.getPracticalEndMoney());
                                 }
                             }
                         }
                     }
                 }
-                if (isFinished){
-                    List<ProjectCostBudget> d6 = finishedMap.get(6);
-                    if (d6 != null && d6.size() > 0){
-                        //循环市场部每一个支出
-                        for (ProjectCostBudget budget : d6) {
-                            //如果实际开始时间或实际结束时间是当月,则添加支出
-                            if ((budget.getRealPlanStartTime().getMonthValue() == (i+1) && budget.getRealPlanStartTime().getYear() == y)
-                                    || (budget.getPracticalFinishTime().getMonthValue() == (i+1) && budget.getPracticalFinishTime().getYear() == y)){
-                                //如果开始时间和结束时间的月相同,则直接用总预算
-                                if (budget.getIsTwoMonth() == 0){
-                                    big2 = big2.add(budget.getActualTotalMoney());
-                                }else {
-                                    //如果开始月是当前月,则直接使用开始金额
-                                    if (budget.getRealPlanStartTime().getMonthValue() == (i+1) && budget.getRealPlanStartTime().getYear() == y){
-                                        big2 = big2.add(budget.getPracticalStartMoney());
-                                    }else {
-                                        //结束月是当前月,使用结束金额
-                                        big2 = big2.add(budget.getPracticalEndMoney());
-                                    }
-                                }
-                            }
-                        }
+            }
+            //设置维护支出
+            if (isMaintain && maintainMap.get(5) != null && maintainMap.get(5).size() > 0){
+                big1 = big1.add(maintainMap.get(5).get(i));
+                big2 = big2.add(maintainMap.get(5).get(i));
+                c9 = c9.add(maintainMap.get(5).get(i));
+                c10 = c10.add(maintainMap.get(5).get(i));
+            }
+            //设置维护支出
+            if (isMaintain && maintainMap.get(6) != null && maintainMap.get(6).size() > 0){
+                big1 = big1.add(maintainMap.get(6).get(i));
+                big2 = big2.add(maintainMap.get(6).get(i));
+                c9 = c9.add(maintainMap.get(6).get(i));
+                c10 = c10.add(maintainMap.get(6).get(i));
+            }
+            //设置管理中心报销支出
+            if (isReimburse && ReimburseMap.get(5) != null && ReimburseMap.get(5).size() > 0){
+                List<EMFinancialReimbursementInfo> infos = ReimburseMap.get(5);
+                BigDecimal big = new BigDecimal(0);
+                for (EMFinancialReimbursementInfo info : infos) {
+                    if (info.getFrDate().getMonth() == i){
+                        big = big.add(info.getFrMoney());
                     }
                 }
-                //设置维护支出
-                if (isMaintain && maintainMap.get(5) != null && maintainMap.get(5).size() > 0){
-                    big1 = big1.add(maintainMap.get(5).get(i));
-                    big2 = big2.add(maintainMap.get(5).get(i));
-                    c9 = c9.add(maintainMap.get(5).get(i));
-                    c10 = c10.add(maintainMap.get(5).get(i));
-                }
-                //设置维护支出
-                if (isMaintain && maintainMap.get(6) != null && maintainMap.get(6).size() > 0){
-                    big1 = big1.add(maintainMap.get(6).get(i));
-                    big2 = big2.add(maintainMap.get(6).get(i));
-                    c9 = c9.add(maintainMap.get(6).get(i));
-                    c10 = c10.add(maintainMap.get(6).get(i));
-                }
-                vo.setBudget5(big1);
-                c9 = c9.add(big1);
-                vo.setPractical5(big2);
-                c10 = c10.add(big2);
-                list.add(vo);
+                big2 = big2.add(big);
             }
-            //计算总计
-            BudgetAndPracticalByDeptVO vo2 = new BudgetAndPracticalByDeptVO();
-            vo2.setTime("总计");
-            vo2.setBudget1(c1);
-            vo2.setPractical1(c2);
-            vo2.setBudget2(c3);
-            vo2.setPractical2(c4);
-            vo2.setBudget3(c5);
-            vo2.setPractical3(c6);
-            vo2.setBudget4(c7);
-            vo2.setPractical4(c8);
-            vo2.setBudget5(c9);
-            vo2.setPractical5(c10);
-            list.add(vo2);
-            return list;
-        }else {
-            for (int i = 0; i < 12; i++) {
-                BudgetAndPracticalByDeptVO vo = new BudgetAndPracticalByDeptVO();
-                vo.setTime(months.get(i));
-                vo.setBudget1(new BigDecimal(0));
-                vo.setBudget1(new BigDecimal(0));
-                vo.setBudget1(new BigDecimal(0));
-                vo.setBudget1(new BigDecimal(0));
-                vo.setBudget1(new BigDecimal(0));
-                vo.setPractical1(new BigDecimal(0));
-                vo.setPractical1(new BigDecimal(0));
-                vo.setPractical1(new BigDecimal(0));
-                vo.setPractical1(new BigDecimal(0));
-                vo.setPractical1(new BigDecimal(0));
-                list.add(vo);
-            }
-            BudgetAndPracticalByDeptVO vo = new BudgetAndPracticalByDeptVO();
-            vo.setTime("总计");
-            vo.setBudget1(new BigDecimal(0));
-            vo.setBudget1(new BigDecimal(0));
-            vo.setBudget1(new BigDecimal(0));
-            vo.setBudget1(new BigDecimal(0));
-            vo.setBudget1(new BigDecimal(0));
-            vo.setPractical1(new BigDecimal(0));
-            vo.setPractical1(new BigDecimal(0));
-            vo.setPractical1(new BigDecimal(0));
-            vo.setPractical1(new BigDecimal(0));
-            vo.setPractical1(new BigDecimal(0));
+            vo.setBudget5(big1);
+            c9 = c9.add(big1);
+            vo.setPractical5(big2);
+            c10 = c10.add(big2);
             list.add(vo);
-            return list;
         }
+        //计算总计
+        BudgetAndPracticalByDeptVO vo2 = new BudgetAndPracticalByDeptVO();
+        vo2.setTime("总计");
+        vo2.setBudget1(c1);
+        vo2.setPractical1(c2);
+        vo2.setBudget2(c3);
+        vo2.setPractical2(c4);
+        vo2.setBudget3(c5);
+        vo2.setPractical3(c6);
+        vo2.setBudget4(c7);
+        vo2.setPractical4(c8);
+        vo2.setBudget5(c9);
+        vo2.setPractical5(c10);
+        list.add(vo2);
+        return list;
     }
 
     /**
@@ -1597,7 +1689,7 @@ public class AnnualBudgetServiceImpl extends BaseServiceImpl<AnnualBudgetMapper,
         //维护支出
         BigDecimal maintainCost = budgetService.getAllMaintainCost(y);
         //报销支出
-        BigDecimal decimal = projectInfoService.getThisYearReimburse(LocalDate.now().getYear());
+        BigDecimal decimal = projectInfoService.getThisYearReimburse(y);
         vo.setPracticalOutput(disburse.add(maintainCost).add(decimal));
         return vo;
     }

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

@@ -58,7 +58,7 @@ public class DictInfoServiceImpl extends ServiceImpl<DictInfoMapper, DictInfo> i
 
     @Override
     public IPage<DictInfoVO> parentList(Map<String, Object> dict, Query query) {
-        IPage<DictInfo> page = this.page(Condition.getPage(query), Condition.getQueryWrapper(dict, DictInfo.class).lambda().eq(DictInfo::getParentId, CommonConstant.TOP_PARENT_ID).eq(DictInfo::getType, Integer.parseInt(dict.get("type") + "")).orderByAsc(DictInfo::getSort));
+        IPage<DictInfo> page = this.page(Condition.getPage(query), Condition.getQueryWrapper(dict, DictInfo.class).lambda().eq(DictInfo::getParentId, CommonConstant.TOP_PARENT_ID).eq(DictInfo::getType, Integer.parseInt(dict.get("type") + "")).orderByAsc(DictInfo::getSort).orderByDesc(DictInfo::getId));
         return DictInfoWrapper.build().pageVO(page);
     }
 

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

@@ -59,14 +59,14 @@ public class LogHistoryServiceImpl extends BaseServiceImpl<LogHistoryMapper, Log
         if (StringUtils.isNotEmpty(dto.getStartTime()) && StringUtils.isNotEmpty(dto.getEndTime())) {
             queryWrapper.apply("DATE_FORMAT(create_time, '%Y-%m') BETWEEN '" + dto.getStartTime() + "' AND '" + dto.getEndTime() + "'");
         } else {
-            //默认查询当月所有日志
+            //默认查询前30天数据
             LocalDate today = LocalDate.now();
-            LocalDate firstDayOfMonth = today.withDayOfMonth(1);
-            LocalDate lastDayOfMonth = today.withDayOfMonth(today.lengthOfMonth());
+            LocalDate thirtyDaysAgo = today.minusDays(30);
+            LocalDate localDate = today.plusDays(1);
             DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
-            String firstDayOfMonthStr = firstDayOfMonth.format(formatter);
-            String lastDayOfMonthStr = lastDayOfMonth.format(formatter);
-            queryWrapper.between(LogHistoryInfo::getCreateTime, firstDayOfMonthStr, lastDayOfMonthStr);
+            String todayStr = localDate.format(formatter);
+            String thirtyDaysAgoStr = thirtyDaysAgo.format(formatter);
+            queryWrapper.between(LogHistoryInfo::getCreateTime, thirtyDaysAgoStr, todayStr);
         }
         queryWrapper.orderByDesc(true, LogHistoryInfo::getCreateTime);
         List<LogHistoryInfo> logHistoryInfos = baseMapper.selectList(queryWrapper);

+ 23 - 4
blade-service/blade-control/src/main/java/org/springblade/control/service/impl/ProjectCostBudgetServiceImpl.java

@@ -933,11 +933,30 @@ public class ProjectCostBudgetServiceImpl extends BaseServiceImpl<ProjectCostBud
      */
     @Override
     public BigDecimal getYearStaffDisburse(int year) {
-        BigDecimal yearStaffDisburse = baseMapper.getYearStaffDisburse(year);
-        if (yearStaffDisburse == null){
-            return new BigDecimal(0);
+        //不直接获取总金额,因为要跨年
+        //BigDecimal yearStaffDisburse = baseMapper.getYearStaffDisburse(year);
+        //获取实际开始完成时间有今年的临时计划
+        List<ProjectCostBudget> list = baseMapper.getBudgetByYear(year);
+        if (list != null && list.size() > 0){
+            BigDecimal big = new BigDecimal(0);
+            for (ProjectCostBudget budget : list) {
+                if (budget.getRealPlanStartTime().getYear() != year || budget.getPracticalFinishTime().getYear() != year){
+                    if (budget.getIsTwoMonth() != 1){
+                        throw new ServiceException("计划年份异常");
+                    }
+                    if (budget.getPracticalFinishTime().getYear() != year){
+                        //如果结束时间不是今年,则使用开始金额
+                        big = big.add(budget.getPracticalStartMoney());
+                    }else {
+                        big = big.add(budget.getPracticalEndMoney());
+                    }
+                }else {
+                    big = big.add(budget.getActualTotalMoney());
+                }
+            }
+            return big;
         }
-        return yearStaffDisburse;
+        return new BigDecimal(0);
     }
 
     /**

+ 10 - 0
blade-service/blade-control/src/main/java/org/springblade/control/service/impl/ProjectInfoServiceImpl.java

@@ -562,5 +562,15 @@ public class ProjectInfoServiceImpl extends BaseServiceImpl<ProjectInfoMapper, C
         return list;
     }
 
+    /**
+     * 获取当年所有的报销,直接返回
+     * @param year
+     * @return
+     */
+    @Override
+    public List<EMFinancialReimbursementInfo> getThisYearReimburse2(int year) {
+        return baseMapper.getYearReimburseByMonth(year);
+    }
+
 
 }

+ 6 - 3
blade-service/blade-manager/src/main/java/com/mixsmart/utils/CustomFunction.java

@@ -1573,7 +1573,10 @@ public class CustomFunction {
     }
 
 /*    public static void main(String[] args) {
-        Double[] a = scopeParse("≤30",0,1);
+        Double[] a = scopeParse("≤5",0,1);
+        Double[] b = scopeParse("≦5",0,1);
+        Double[] c = scopeParse("≤5",0,1);
+
         System.out.println(a);
     }*/
 
@@ -1588,8 +1591,8 @@ public class CustomFunction {
             double min = 0;
             double max = 0;
             devStr = devStr.replaceAll("\\s+", "");
-            if (devStr.contains("≤") || devStr.contains("<=") || devStr.contains("<")) {
-                devStr = devStr.replace("≤", "").replace("<=", "");
+            if (devStr.contains("≤") || devStr.contains("<=") || devStr.contains("<")||devStr.contains("≦")) {
+                devStr = devStr.replace("≤", "").replace("<=", "").replace("≦","");
                 max = designD + Double.parseDouble(devStr) * xND;
             } else if (devStr.contains("≥") || devStr.contains(">=") || devStr.contains(">")) {
                 devStr = devStr.replace("≥", "").replace(">=", "");

+ 45 - 0
blade-service/blade-manager/src/main/java/com/mixsmart/utils/FormulaUtils.java

@@ -607,6 +607,51 @@ public class FormulaUtils {
            return coords;
      }
 
+    public static FormData createFormDataFast(String name,String code,String values,String coords){
+        if(StringUtils.isNotEmpty(code,name)){
+            //String[] arr=code.split(":");
+           // String coords = tec.getCoordinateMap().get(arr[0]).get(arr[1]);
+            if(StringUtils.isNotEmpty(coords)) {
+                /*定位信息存在才合法*/
+                List<Coords> coordsList = Stream.of(coords).flatMap(s -> Arrays.stream(s.split(";"))).map(s -> {
+                    String[] xy = s.split("_");
+                    return new Coords(xy[1], xy[0]);
+                }).collect(Collectors.toList());
+                List<ElementData> eds = new ArrayList<>();
+                if (StringUtils.isNotEmpty(values)) {
+                    String[] pages = values.split(";;");
+                    for (int index = 0; index < pages.length; index++) {
+                        String pg = pages[index];
+                        if (Func.isNotBlank(pg)) {
+                            String[] val = pg.split("☆");
+                            Map<String, Object> tmpMap = new LinkedHashMap<>();
+                            for (String s : val) {
+                                String[] t = s.split("_\\^_");
+                                String[] c = t[1].split("_");
+                                tmpMap.put(StringUtils.join(code, 0, index, Func.toInt(c[1]), Func.toInt(c[0]), StringPool.AT), t[0]);
+                            }
+                            for (Coords c : coordsList) {
+                                Object data = null;
+                                String key = StringUtils.join(code, 0, index, c.getX(), c.getY(), StringPool.AT);
+                                if (tmpMap.containsKey(key)) {
+                                    data = tmpMap.get(key);
+                                }
+                                eds.add(new ElementData(index, 0, data, c.getX(), c.getY()));
+                            }
+                        }
+                    }
+
+                } else {
+                    eds = coordsList.stream().map(c -> new ElementData(0, 0, null, c.getX(), c.getY())).collect(Collectors.toList());
+                }
+                FormData one = new FormData(code, eds, null, coords);
+                one.setEName(name);
+                return one;
+            }
+        }
+        return null;
+    }
+
     public static void mainT(String[] args) throws IOException {
         XYSeries series = new XYSeries("Data Series");
         series.add(10.2, 1.82);

+ 36 - 24
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ContractInfoController.java

@@ -510,12 +510,11 @@ public class ContractInfoController extends BladeController {
     @PostMapping("/submit-wbsTree-contract")
     @ApiOperationSupport(order = 17)
     @ApiOperation(value = "保存或修改分配合同段wbs树", notes = "传入WbsTreeContractDTO")
-    public R submitWbsTreeInContract(@RequestBody WbsTreeContractDTO wbsTreeContractDTO) {
-        boolean b = wbsTreeContractService.submitWbsTreeInContract(wbsTreeContractDTO);
-        if (b) {
-            return R.success("关联合同段树成功");
+    public R<Object> submitWbsTreeInContract(@RequestBody WbsTreeContractDTO wbsTreeContractDTO) {
+        if (wbsTreeContractService.submitWbsTreeInContract(wbsTreeContractDTO)) {
+            return R.success("操作成功");
         }
-        return R.fail("关联合同段树失败");
+        return R.fail("操作失败");
     }
 
     /**
@@ -718,40 +717,53 @@ public class ContractInfoController extends BladeController {
      * 资料填报(资料查询)节点搜索输入框查询接口
      *
      * @author liuyc
-     * @since 2023年6月15日11:44:36
+     * @date 2023年6月15日11:44:36
      */
     @GetMapping("/getTreeNodeByQueryValueAndContractId")
     @ApiOperationSupport(order = 23)
-    @ApiOperation(value = "资料填报(资料查询)节点搜索输入框查询接口", notes = "传入合同段id、输入框搜索的queryValue")
-    public R getTreeNodeByValueAndContractId(@RequestParam String queryValue, @RequestParam String contractId) {
-        R list = contractInfoService.getTreeNodeByValueAndContractId(queryValue, contractId);
-        if (ObjectUtil.isNotEmpty(list) && ObjectUtil.isNotEmpty(list.getData())) {
-            Object data = list.getData();
+    @ApiOperation(value = "资料填报(资料查询)节点搜索输入框查询接口", notes = "传入合同段id、输入框搜索的queryValue、表单所属方tableOwner")
+    public R<Object> getTreeNodeByValueAndContractId(@RequestParam String queryValue, @RequestParam String contractId, @RequestParam String tableOwner) {
+        R<Object> result = contractInfoService.getTreeNodeByValueAndContractId(queryValue, contractId, tableOwner);
+        if (ObjectUtil.isNotEmpty(result) && ObjectUtil.isNotEmpty(result.getData())) {
+            Object data = result.getData();
             ContractInfo contractInfo = contractInfoService.getBaseMapper().selectById(contractId);
             if (data instanceof List) {
+                List<?> dataList = (List<?>) data;
                 if (contractInfo.getContractType().equals(1)) {
-                    List<WbsTreeContractTreeAllVO> dataList = (List<WbsTreeContractTreeAllVO>) data;
-                    for (WbsTreeContractTreeAllVO wbsTreeContractVO : dataList) {
-                        if (ObjectUtil.isNotEmpty(wbsTreeContractVO.getParentId()) && 0L == wbsTreeContractVO.getParentId()) {
-                            wbsTreeContractVO.setTitle(contractInfo.getContractName());
-                            break;
+                    for (Object item : dataList) {
+                        if (item instanceof WbsTreeContractTreeAllVO) {
+                            WbsTreeContractTreeAllVO wbsTreeContractVO = (WbsTreeContractTreeAllVO) item;
+                            if (ObjectUtil.isNotEmpty(wbsTreeContractVO.getParentId()) && 0L == wbsTreeContractVO.getParentId()) {
+                                wbsTreeContractVO.setTitle(contractInfo.getContractName());
+                                break;
+                            }
                         }
                     }
                     return R.data(data);
                 }
             } else if (data instanceof Map) {
+                Map<?, ?> dataMap = (Map<?, ?>) data;
                 if (contractInfo.getContractType().equals(2) || contractInfo.getContractType().equals(3)) {
                     List<WbsTreeContractTreeAllVO> jlYzList = new LinkedList<>();
-                    Map<Long, List<WbsTreeContractTreeAllVO>> dataMap = (Map<Long, List<WbsTreeContractTreeAllVO>>) data;
-                    for (Map.Entry<Long, List<WbsTreeContractTreeAllVO>> map : dataMap.entrySet()) {
-                        ContractInfo contractInfoJlYz = contractInfoService.getBaseMapper().selectById(map.getKey());
-                        for (WbsTreeContractTreeAllVO wbsTreeContractVO : map.getValue()) {
-                            if (ObjectUtil.isNotEmpty(wbsTreeContractVO.getParentId()) && 0L == wbsTreeContractVO.getParentId()) {
-                                wbsTreeContractVO.setTitle(contractInfoJlYz.getContractName());
-                                break;
+                    for (Map.Entry<?, ?> entry : dataMap.entrySet()) {
+                        Object key = entry.getKey();
+                        Object value = entry.getValue();
+                        if (key instanceof Long && value instanceof List) {
+                            Long mapKey = (Long) key;
+                            List<?> mapValue = (List<?>) value;
+                            ContractInfo contractInfoJlYz = contractInfoService.getBaseMapper().selectById(mapKey);
+                            List<? extends WbsTreeContractTreeAllVO> typedList = mapValue.stream()
+                                    .filter(item -> item instanceof WbsTreeContractTreeAllVO)
+                                    .map(item -> (WbsTreeContractTreeAllVO) item)
+                                    .collect(Collectors.toList());
+                            for (WbsTreeContractTreeAllVO wbsTreeContractVO : typedList) {
+                                if (ObjectUtil.isNotEmpty(wbsTreeContractVO.getParentId()) && 0L == wbsTreeContractVO.getParentId()) {
+                                    wbsTreeContractVO.setTitle(contractInfoJlYz.getContractName());
+                                    break;
+                                }
                             }
+                            jlYzList.addAll(typedList);
                         }
-                        jlYzList.addAll(map.getValue());
                     }
                     return R.data(jlYzList);
                 }

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

@@ -454,8 +454,6 @@ public class ExcelTabController extends BladeController {
     })
     public R<List<ExceTabTreVO>> saveLinkeTab(Long exceTabId, Long tabId) throws IOException {
         String file_path = ParamCache.getValue(CommonConstant.SYS_LOCAL_URL);
-        //String file_path = "C:\\Users\\泓创开发\\Desktop";
-
         // 关联 私有项目 wbs 数据信息
         WbsTreePrivate wbsTree = new WbsTreePrivate();
         wbsTree.setPKeyId(tabId);
@@ -473,8 +471,9 @@ public class ExcelTabController extends BladeController {
         updateWrapper.set("excel_id", exceTabId);
 
         // 复制模版htmlURL
+
         File file_in = ResourceUtil.getFile(excelTab.getHtmlUrl());
-        // File file_in = ResourceUtil.getFile(file_path+"1542338623020961794.html");
+
         String filecode = SnowFlakeUtil.getId() + "";
         String thmlUrl = file_path + "/privateUrl/" + filecode + ".html";
         File file_out = ResourceUtil.getFile(thmlUrl);
@@ -490,11 +489,15 @@ public class ExcelTabController extends BladeController {
         //解析
         Element table = doc.select("table").first();
         Elements trs = table.select("tr");
-        if (aPrivate.getInitTableId() == null) {
-            org.springblade.manager.entity.TableInfo tableInfo = tableInfoService.getOne(new LambdaQueryWrapper<org.springblade.manager.entity.TableInfo>()
-                    .eq(org.springblade.manager.entity.TableInfo::getTabEnName, aPrivate.getInitTableName()));
-            aPrivate.setInitTableId(tableInfo.getId() + "");
-            updateWrapper.set("init_table_id", tableInfo.getId() + "");
+        if(StringUtils.isNotEmpty(excelTab.getTabId())){
+            updateWrapper.set("init_table_id", excelTab.getTabId());
+        }else {
+            if (aPrivate.getInitTableId() == null) {
+                org.springblade.manager.entity.TableInfo tableInfo = tableInfoService.getOne(new LambdaQueryWrapper<org.springblade.manager.entity.TableInfo>()
+                        .eq(org.springblade.manager.entity.TableInfo::getTabEnName, aPrivate.getInitTableName()));
+                aPrivate.setInitTableId(tableInfo.getId() + "");
+                updateWrapper.set("init_table_id", tableInfo.getId() + "");
+            }
         }
 
         List<WbsFormElement> elementList = wbsFormElementService.selectElementListByFid(aPrivate.getInitTableId() + "");

+ 133 - 1
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/FormulaController.java

@@ -373,7 +373,8 @@ public class FormulaController {
         Map<String, Object> result = new LinkedHashMap<>();
         String key = fo.getKey().replaceAll("__[\\d_]+", "");
         ContractInfo contract = this.contractInfoService.getById(fo.getContractId());
-        List<KeyMapper> kms = this.service.getKeyMapperList(Collections.singletonList(fo.getPkeyId()), contract.getPId(), "", ExecuteType.INSPECTION);
+        WbsTreeContract parent = this.wbsTreeContractService.getOne(Wrappers.<WbsTreeContract>lambdaQuery().eq(WbsTreeContract::getId,fo.getParentId()).eq(WbsTreeContract::getContractId,fo.getContractId()).last("limit 1"));
+        List<KeyMapper> kms = this.service.getKeyMapperList(Collections.singletonList(fo.getPkeyId()), contract.getPId(), parent.getPKeyId().toString(), ExecuteType.INSPECTION);
         KeyMapper keyMapper = null;
         if (Func.isNotEmpty(kms)) {
             Optional<KeyMapper> optionalKeyMapper = kms.stream().filter(e -> StringUtils.isEquals(e.getField(), key)).findFirst();
@@ -499,6 +500,10 @@ public class FormulaController {
     @PostMapping("/chart-init")
     @ApiOperationSupport(order = 11)
     public R<Object> chartInit(@RequestBody ChartOption option){
+           /*1.获取公式配置,如果存在子公式,则一直查找到最终公式*/
+           /*2.查找所有依赖元素的所有数据,按表单排序*/
+           /*3.计算结果*/
+           /*4.查找当前表对应返回配置模版结合计算结果生成option*/
             Long pkeyId=option.getPkeyId();
             String id=option.getId();
             WbsTreePrivate wtp = this.wbsTreePrivateService.getOne(Wrappers.<WbsTreePrivate>lambdaQuery().eq(WbsTreePrivate::getPKeyId,pkeyId));
@@ -572,5 +577,132 @@ public class FormulaController {
             return R.data("{}");
     }
 
+    public Formula formulaAct(Long pkeyId){
+        List<Map<String,Object>>  configList= this.jdbcTemplate.queryForList("select d.rely,d.formula ,b.e_key ekey from m_wbs_tree_private a join  m_wbs_form_element b on a.init_table_id=b.f_id join m_element_formula_mapping c on b.id=c.element_id join m_formula d on c.formula_id=d.id  where p_key_id="+pkeyId+" and b.is_deleted=0 and  d.formula like 'FC.chart%' limit 1");
+        if(Func.isNotEmpty(configList)) {
+            Map<String, Object> config = configList.get(0);
+            String relyStr=config.get("rely").toString();
+            String[] rely = relyStr.split(",");
+            String ky=rely[0].split(":")[1];
+            String kx=rely[1].split(":")[1];
+            Formula formulaY =new Formula();
+            formulaY.setFormula(config.get("formula").toString());
+            formulaY.setRely(relyStr);
+            formulaY.setFormula(nest(formulaY.getFormula(),formulaY.getRely()));
+            this.service.relyParse(formulaY);
+        }
+        return null;
+    }
+
+
+    public List<Object> calc(String formula,Map<String,List<ElementData>> dataSource){
+        return null;
+    }
+
+
+    /**
+     * @Description 根据元素码和当前工序pkeyId返回元素数据
+     * @Param [codes, pkeyId]
+     * @return java.util.Map<java.lang.String,java.util.List<org.springblade.manager.dto.ElementData>>
+     * @Author yangyj
+     * @Date 2023.08.01 14:53
+     **/
+    public Map<String,List<ElementData>> getDataFromCodes(List<String> codes,WbsTreePrivate wtp,String id){
+        String s = codes.stream().collect(Collectors.joining("','","'","'"));
+        List<Map<String,Object>> listMap = this.jdbcTemplate.queryForList("select a.id elementId,a.e_key ekey,a.e_name eName,b.init_table_name tableName,b.html_url url,b.p_key_id pkeyId,b.node_name nodeName,CONCAT(b.init_table_name,':',a.e_key) tk from m_wbs_form_element a join m_wbs_tree_private b on a.f_id=b.init_table_id where b.parent_id="+wtp.getParentId()
+                +" and b.project_id="+wtp.getProjectId()+" and b.is_deleted=0 and a.is_deleted=0  and CONCAT(b.init_table_name,':',a.e_key) in("+s+") ORDER BY b.sort,b.create_time");
+        Map<String,List<ElementData>> result = new HashMap<>();
+        if(listMap.size()>codes.size()){
+            Map<String,Map<String,String>> coordsMap = new HashMap<>();
+            for(Map<String,Object> m:listMap){
+                String tableName = m.get("tableName").toString();
+                if(!coordsMap.containsKey(tableName)){
+                    coordsMap.put(tableName,FormulaUtils.getElementCell(m.get("url").toString()));
+                }
+            }
+            Map<String,List<Map<String,Object>>> group=   listMap.stream().collect(Collectors.groupingBy(m->m.get("tableName").toString()));
+            Map<String,String> codeDataMap= new HashMap<>();
+            group.forEach((k,v)->{
+                String sql ="select "+ v.stream().map(m->m.get("ekey").toString()).distinct().collect(Collectors.joining(","))+" from "
+                        +k+" where p_key_id in("+v.stream().map(m->m.get("pkeyId").toString()).distinct().collect(Collectors.joining(","))
+                        +" and group id ="+id;
+                List<Map<String,Object>> dataListMap = this.jdbcTemplate.queryForList(sql);
+                if(dataListMap.size()>0){
+                    for(Map<String,Object> dm:listMap){
+                       dm.forEach((ek,ev)->{
+                           codeDataMap.merge(k+":"+ek,ev.toString(),(v1,v2)->v1+";;"+v2);
+                       });
+                    }
+                }
+            });
+           Map<String,FormData> fdMap= codes.stream().map(c->{
+                String[] tc=c.split(":");
+                return FormulaUtils.createFormDataFast(c,c,codeDataMap.get(c),coordsMap.get(tc[0]).get(tc[1]));
+            }).filter(Objects::nonNull).collect(Collectors.toMap(FormData::getCode, f->f));
+           if(fdMap.size()>0){
+               fdMap.forEach((k,v)->{
+                   result.put(k,v.getValues());
+               });
+           }
+        }
+        return  result;
+    }
+
 
+    public String nest(String formula,String rely){
+        if(Func.isNotBlank(rely)) {
+            String s = Arrays.stream(rely.replaceAll("[\\s]+", "").split(",")).collect(Collectors.joining(",',", "'", "'"));
+            List<Map<String, Object>> listMap = this.jdbcTemplate.queryForList("select CONCAT(a.tab_en_name,':',b.e_key) ek,b.id,b.e_name ename,c.formula_id formulaId,d.formula,d.rely from m_table_info a join m_wbs_form_element b on a.id=b.f_id join m_element_formula_mapping c on b.id=c.element_id left join m_formula d on c.formula_id=d.id where concat(a.tab_en_name,':',b.e_key) in(" + s + ") and b.is_deleted =0 and c.is_deleted=0 ");
+            for (Map<String, Object> m : listMap) {
+                if (StringUtils.isNotEmpty(m.get("formulaId"))) {
+                    String ek = m.get("ek").toString();
+                    String formulaSub = nest(m.get("formula").toString(), m.get("rely").toString());
+                    formula = formula.replace(ek, formulaSub);
+                }
+            }
+        }
+        return formula;
+    }
+
+
+    @GetMapping("/table-name")
+    public R<Object> lack() {
+        List<Map<String,Object>> listMap=this.jdbcTemplate.queryForList("select p_key_id pkeyId,node_name nodeName from m_wbs_tree_contract where  project_id=1630011899725201410 and table_type>0  and is_deleted=0 and init_table_name is null ");
+        Map<Long,String> idMap= listMap.stream().collect(Collectors.toMap(m->Long.parseLong(m.get("pkeyId").toString()),m->m.get("nodeName").toString()));
+        List<Map<String,Object>> tn = this.jdbcTemplate.queryForList("select tab_ch_name ch,tab_en_name en  from m_table_info where tab_ch_name in("+idMap.values().stream().distinct().map(Object::toString).collect(Collectors.joining("','","'","'"))+")");
+        Map<String,String> tbMap= tn.stream().collect(Collectors.toMap(m->m.get("ch").toString(),m->m.get("en").toString()));
+        List<WbsTreeContract> list =   this.wbsTreeContractService.list(Wrappers.<WbsTreeContract>lambdaQuery().in(WbsTreeContract::getPKeyId,idMap.keySet()));
+        list.forEach(e->{
+            if(Func.isBlank(e.getInitTableName())){
+                e.setInitTableName(tbMap.get(e.getFullName()));
+                this.wbsTreeContractService.update(Wrappers.<WbsTreeContract>lambdaUpdate().set(WbsTreeContract::getInitTableName,e.getInitTableName()).eq(WbsTreeContract::getPKeyId,e.getPKeyId()));
+            }
+        });
+        return R.success("成功");
+    }
+
+
+    public R<Object> flushPri(){
+        /*刷inittablename*/
+        List<Map<String,Object>> listMap=this.jdbcTemplate.queryForList("select p_key_id nodeId,init_table_id tableId from m_wbs_tree_private where project_id=1630011899725201410 and init_table_id is not null and init_table_name is null and is_deleted=0");
+        if(listMap.size()>0){
+            Map<Long,Long> idMap= listMap.stream().collect(Collectors.toMap(m->Long.parseLong(m.get("nodeId").toString()),m->Long.parseLong(m.get("tableId").toString())));
+            List<Map<String,Object>> tn = this.jdbcTemplate.queryForList("select id,tab_en_name tbName from m_table_info where id in("+idMap.values().stream().distinct().map(Object::toString).collect(Collectors.joining(","))+")");
+            Map<String,String> tbMap= tn.stream().collect(Collectors.toMap(m->m.get("id").toString(),m->m.get("tbName").toString()));
+            List<WbsTreePrivate> updateList = new ArrayList<>();
+            List<WbsTreePrivate> list =   this.wbsTreePrivateService.list(Wrappers.<WbsTreePrivate>lambdaQuery().in(WbsTreePrivate::getPKeyId,idMap.keySet()));
+            list.forEach(e->{
+                if(e.getInitTableId()!=null&&e.getInitTableName()==null){
+                    e.setInitTableName(tbMap.get(e.getInitTableId()));
+                    this.wbsTreePrivateService.update(Wrappers.<WbsTreePrivate>lambdaUpdate().set(WbsTreePrivate::getInitTableName,e.getInitTableName()).eq(WbsTreePrivate::getPKeyId,e.getPKeyId()));
+                    updateList.add(e);
+                }
+            });
+            if(updateList.size()>0){
+                // this.wbsTreePrivateService.saveOrUpdateBatch(updateList,500);
+            }
+            return R.success("成功");
+        }
+        return R.fail("失败");
+    }
 }

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

@@ -1,5 +1,6 @@
 package org.springblade.manager.controller;
 
+import cn.hutool.core.util.ObjectUtil;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import io.swagger.annotations.*;
 import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
@@ -64,8 +65,11 @@ public class ProjectInfoController extends BladeController {
             @ApiImplicitParam(value = "ReferenceWbsTemplateType", name = "ReferenceWbsTemplateType", required = true)
     })
     public R<ProjectInfoVO2> detail2(ProjectInfo projectInfo) {
-        ProjectInfoVO2 detail = projectInfoService.getOneByCondition(projectInfo.getId(), projectInfo.getReferenceWbsTemplateId(), projectInfo.getReferenceWbsTemplateType());
-        return R.data(detail);
+        if (ObjectUtil.isNotEmpty(projectInfo.getReferenceWbsTemplateId()) && ObjectUtil.isNotEmpty(projectInfo.getId()) && ObjectUtil.isNotEmpty(projectInfo.getReferenceWbsTemplateType())) {
+            ProjectInfoVO2 detail = projectInfoService.getOneByCondition(projectInfo.getId(), projectInfo.getReferenceWbsTemplateId(), projectInfo.getReferenceWbsTemplateType());
+            return R.data(detail);
+        }
+        return R.fail(200, "未查询到信息");
     }
 
 
@@ -232,6 +236,7 @@ public class ProjectInfoController extends BladeController {
 
     /**
      * 保存或修改分配项目级wbs树
+     *
      * @return
      */
     @PostMapping("/submit-wbsTree-project")

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

@@ -318,7 +318,7 @@ public class TextdictInfoController extends BladeController {
                 element.empty().append(checkbox);
             }
         } else if (textdictInfo.getTextId().equals("date")) { // 日期--年月日时分秒
-            element.empty().append("<el-date-picker @keyDowns='dateKeydown()' v-model=" + vmode + " type='datetime' format='YYYY年MM月DD日 HH:mm:ss' value-format='YYYY年MM月DD日 hh:mm:ss' placeholder=" + placeholder + " keyname=" + keyname + " weighing=" + weighing + "  @contextmenu.prevent.native='contextmenuClick(" + parm + ")'  @mouseup.right='RightClick(" + parm + ")' trIndex=" + trindex + " tdIndex=" + tdindex + "  x1=" + x1 + " x2=" + x2 + " y1=" + y1 + " y2=" + y2 + " style='width:100%;height:100%'   placeholder='" + placeholder + "'> </el-date-picker>");
+            element.empty().append("<el-date-picker @keyDowns='dateKeydown()' v-model=" + vmode + " type='datetime' format='YYYY年MM月DD日 HH:mm:ss' value-format='YYYY年MM月DD日 HH:mm:ss' placeholder=" + placeholder + " keyname=" + keyname + " weighing=" + weighing + "  @contextmenu.prevent.native='contextmenuClick(" + parm + ")'  @mouseup.right='RightClick(" + parm + ")' trIndex=" + trindex + " tdIndex=" + tdindex + "  x1=" + x1 + " x2=" + x2 + " y1=" + y1 + " y2=" + y2 + " style='width:100%;height:100%'   placeholder='" + placeholder + "'> </el-date-picker>");
         } else if (textdictInfo.getTextId().equals("dateYMD")) { // 日期--年月日
             element.empty().append("<el-date-picker @keyDowns='dateKeydown()' v-model=" + vmode + " type='date' format='YYYY年MM月DD日' value-format='YYYY年MM月DD日' placeholder=" + placeholder + " keyname=" + keyname + " weighing=" + weighing + "  @contextmenu.prevent.native='contextmenuClick(" + parm + ")'  @mouseup.right='RightClick(" + parm + ")' trIndex=" + trindex + " tdIndex=" + tdindex + "  x1=" + x1 + " x2=" + x2 + " y1=" + y1 + " y2=" + y2 + " style='width:100%;height:100%'   placeholder='" + placeholder + "'> </el-date-picker>");
         } else if (textdictInfo.getTextId().equals("dateHMS")) { // 日期--时分秒

+ 165 - 71
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/WbsParamController.java

@@ -4,6 +4,7 @@ import cn.hutool.core.date.StopWatch;
 import cn.hutool.log.StaticLog;
 import com.alibaba.fastjson.JSON;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
@@ -13,6 +14,7 @@ import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiParam;
 import lombok.AllArgsConstructor;
 import org.springblade.common.utils.BaseUtils;
+import org.springblade.core.log.exception.ServiceException;
 import org.springblade.core.mp.base.BaseService;
 import org.springblade.core.mp.support.Condition;
 import org.springblade.core.mp.support.Query;
@@ -33,9 +35,6 @@ import org.springframework.beans.BeanUtils;
 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;
 
@@ -88,7 +87,7 @@ public class WbsParamController {
             List<WbsParamBean> wps = pb.getWps();
             String names=checkRepeat(wps);
             if(names!=null){
-                return R.success("存在重复参数【"+names+"】,删除多余项再保存");
+                return R.fail("存在重复参数【"+names+"】,删除多余项再保存");
             }
             /*执行顺序,删>增>改*/
             if (Func.isNotEmpty(pb.getDelIds())) {
@@ -99,7 +98,6 @@ public class WbsParamController {
                         this.elementFormulaMappingService.update(Wrappers.<ElementFormulaMapping>lambdaUpdate().set(ElementFormulaMapping::getIsDeleted, 1).in(ElementFormulaMapping::getParamId, pb.getDelIds()));
                     }
                 }
-                /*应该检查接触关联的参数公式还是否存在引用,不存在的情况也要删去*/
             }
             if (CollectionUtil.isNotEmpty(wps)) {
                 Map<Boolean, List<WbsParamBean>> map = wps.stream().peek(w -> w.setType(pb.getType())).collect(Collectors.partitioningBy(e -> e.getId() != null));
@@ -108,6 +106,7 @@ public class WbsParamController {
                 if (CollectionUtil.isNotEmpty(saveList)) {
                     List<WbsParam> entityList = BeanUtil.copy(saveList, WbsParam.class);
                     this.service.saveBatch(entityList);
+                    Map<String, Object> tmpMap = new HashMap<>();
                     if (!pb.isCommon()) {
                         /*新建的时候需要初始化绑定表单元素*/
                         List<Map<String, Object>> elementMap = new ArrayList<>();
@@ -127,38 +126,53 @@ public class WbsParamController {
                                             "where  b.project_id=" + pb.getProjectId() + " and a.p_key_id=" + pb.getNodeId() + "  and b.is_deleted=0 and c.is_deleted=0 ");
                         }
                         if (!elementMap.isEmpty()) {
-                            Map<String, Object> tmpMap = new HashMap<>();
                             List<Map<String, Object>> finalElementMap = elementMap;
+                           // List<Map<String,Object>> formulaIdAndKmaps=this.jdbcTemplate.queryForList("select a.id,b.k from m_formula a join m_wbs_param b on a.param_id=b.id where b.k in ("+entityList.stream().map(WbsParam::getK).collect(Collectors.joining("','","'","'"))+") AND b.type=0");
+                           Map<String,Long> fkMap=this.service.formulaIdKeyMap(entityList.stream().map(WbsParam::getK).collect(Collectors.toList()));
                             entityList.forEach(e -> {
-                                Formula formula = new Formula();
-                                formula.setOutm(Formula.FULL);
-                                formula.setParamId(e.getId());
-                                Map<String, String> keyMap = new HashMap<>();
-                                keyMap.put("name", e.getName());
-                                keyMap.put("id", e.getId().toString());
-                                tmpMap.put(e.getK(), keyMap);
-                                if (RegexUtil.match(ParamElements.LEVEL_REG, e.getV().trim())) {
-                                    /*取层级*/
-                                    formula.setFormula("FC.tree(trees,WP[" + e.getK() + "])");
-                                } else {
-                                    /*直接取数*/
-                                    formula.setFormula("WP[" + e.getK() + "]");
-                                }
-                                formula.setMap(JSON.toJSONString(tmpMap));
-                                this.formulaService.save(formula);
-                                tmpMap.clear();
+//                                Formula formula = new Formula();
+//                                formula.setOutm(Formula.FULL);
+//                                formula.setParamId(e.getId());
+//                                Map<String, String> keyMap = new HashMap<>();
+//                                keyMap.put("name", e.getName());
+//                                keyMap.put("id", e.getId().toString());
+//                                tmpMap.put(e.getK(), keyMap);
+//                                if (RegexUtil.match(ParamElements.LEVEL_REG, e.getV().trim())) {
+//                                    /*取层级*/
+//                                    formula.setFormula("FC.tree(trees,WP[" + e.getK() + "])");
+//                                } else {
+//                                    /*直接取数*/
+//                                    formula.setFormula("WP[" + e.getK() + "]");
+//                                }
+//                                formula.setMap(JSON.toJSONString(tmpMap));
+//                                this.formulaService.save(formula);
+//                                tmpMap.clear();
                                 finalElementMap.forEach(m -> {
                                     if (StringUtils.handleNull(m.get("name")).contains(e.getName())) {
                                         ElementFormulaMapping efm = new ElementFormulaMapping();
                                         efm.setScope(FormulaBean.PARAM);
                                         efm.setParamId(e.getId());
                                         efm.setElementId(Long.parseLong(m.get("id").toString()));
-                                        efm.setFormulaId(formula.getId());
+                                        efm.setFormulaId(fkMap.get(e.getK()));
                                         this.elementFormulaMappingService.save(efm);
                                     }
                                 });
                             });
                         }
+                    }else{
+                        entityList.forEach(e -> {
+                            Formula formula = new Formula();
+                            formula.setOutm(Formula.FULL);
+                            formula.setParamId(e.getId());
+                            Map<String, String> keyMap = new HashMap<>();
+                            keyMap.put("name", e.getName());
+                            keyMap.put("id", e.getId().toString());
+                            tmpMap.put(e.getK(), keyMap);
+                            formula.setFormula("FC.tree(trees,WP[" + e.getK().replaceAll("[\\s]+","") + "])");
+                            formula.setMap(JSON.toJSONString(tmpMap));
+                            this.formulaService.save(formula);
+                            tmpMap.clear();
+                        });
                     }
                 }
                 if (CollectionUtil.isNotEmpty(updateList)) {
@@ -166,8 +180,17 @@ public class WbsParamController {
                     for (WbsParamBean b : updateList) {
                         WbsParam old = this.service.getById(b.getId());
                         if (pb.isCommon()) {
-                            if (old != null && (StringUtils.isNotEquals(old.getK(),b.getK())||StringUtils.isNotEquals(old.getRemark(),b.getRemark()))) {
+                            if (old != null && (StringUtils.isNotEquals(old.getName(),b.getName())||StringUtils.isNotEquals(old.getK(),b.getK())||StringUtils.isNotEquals(old.getRemark(),b.getRemark()))) {
                                 /*只有公式内容变化的时候才需要更新*/
+                                if(StringUtils.isNotEquals(old.getK(),b.getK())||StringUtils.isNotEquals(old.getName(),b.getName())){
+                                    LambdaUpdateWrapper<WbsParam> wrapper=Wrappers.<WbsParam>lambdaUpdate().set(WbsParam::getName,b.getName()).set(WbsParam::getK,b.getK()).eq(WbsParam::getType,1).eq(WbsParam::getK,old.getK());
+                                    this.service.update(wrapper);
+                                    if(StringUtils.isNotEquals(old.getK(),b.getK())) {
+                                        Formula formula = this.formulaService.getOne(Wrappers.<Formula>lambdaQuery().eq(Formula::getParamId, old.getId()));
+                                        formula.setFormula("FC.tree(trees,WP[" + b.getK() + "])");
+                                        this.formulaService.saveOrUpdate(formula);
+                                    }
+                                }
                                 old.setIsDeleted(0);
                                 BeanUtils.copyProperties(b, old);
                                 ul.add(old);
@@ -244,7 +267,7 @@ public class WbsParamController {
     @ApiOperation(value = "获取名称字典", notes = "获取名称字典")
     @GetMapping("/keymap")
     public R<List<WbsParamBean>> list2() {
-        LambdaQueryWrapper<WbsParam> queryWrapper = Wrappers.<WbsParam>query().lambda().eq(WbsParam::getType, 0);
+        LambdaQueryWrapper<WbsParam> queryWrapper = Wrappers.<WbsParam>query().lambda().eq(WbsParam::getType, 0).orderByDesc(WbsParam::getCreateTime);
         List<WbsParamBean> list = new ArrayList<>();
         List<WbsParam> data = this.service.list(queryWrapper);
         if (CollectionUtil.isNotEmpty(data)) {
@@ -263,6 +286,11 @@ public class WbsParamController {
                 .eq(WbsParam::getNodeId, wbsId)
                 .eq(WbsParam::getType, 1));
         if (data.size() > 0) {
+            List<Map<String,Object>> statistics=jdbcTemplate.queryForList("select count(*) sum,param_id id from m_element_formula_mapping a join m_wbs_param b on a.param_id= b.id where b.node_id="+wbsId+" and b.is_deleted=0  GROUP BY a.param_id");
+            Map<Long,Integer> mapSum=statistics.stream().collect(Collectors.toMap(m->Long.parseLong(m.get("id").toString()),m-> Integer.parseInt(m.get("sum").toString()),(v1,v2)->v2));
+            if(statistics.size()>1){
+                data.sort(Comparator.comparingInt((WbsParam d)->mapSum.getOrDefault(d.getId(),0)).reversed());
+            }
             return R.data(BeanUtil.copyProperties(data, WbsParamBean.class));
         }
         return R.data(null);
@@ -315,35 +343,42 @@ public class WbsParamController {
     public R<Boolean> specified(@ApiParam(value = "关联id", required = true) Long paramId, Long elementId) {
         /*先删旧关联,检查是否存在公式,没有就新增 再增新关联*/
         this.jdbcTemplate.execute("update m_element_formula_mapping set is_deleted=1 where element_id=" + elementId + " and param_id=" + paramId);
-        Formula formula = this.formulaService.getOne(Wrappers.<Formula>lambdaQuery().eq(Formula::getParamId, paramId));
-        if (formula == null) {
-            Map<String, Object> tmpMap = new HashMap<>();
-            formula = new Formula();
-            WbsParam param = this.service.getById(paramId);
-            formula.setOutm(Formula.FULL);
-            formula.setParamId(param.getId());
-            Map<String, String> keyMap = new HashMap<>();
-            keyMap.put("name", param.getName());
-            keyMap.put("id", param.getId().toString());
-            tmpMap.put(param.getK(), keyMap);
-            if (RegexUtil.match(ParamElements.LEVEL_REG, param.getV().trim())) {
-                /*取层级*/
-                formula.setFormula("FC.tree(trees,WP[" + param.getK() + "])");
-            } else {
-                /*直接取数*/
-                formula.setFormula("WP[" + param.getK() + "]");
-            }
-            formula.setMap(JSON.toJSONString(tmpMap));
-            this.formulaService.save(formula);
+//        Formula formula = this.formulaService.getOne(Wrappers.<Formula>lambdaQuery().eq(Formula::getParamId, paramId));
+//        if (formula == null) {
+//            Map<String, Object> tmpMap = new HashMap<>();
+//            formula = new Formula();
+//            WbsParam param = this.service.getById(paramId);
+//            formula.setOutm(Formula.FULL);
+//            formula.setParamId(param.getId());
+//            Map<String, String> keyMap = new HashMap<>();
+//            keyMap.put("name", param.getName());
+//            keyMap.put("id", param.getId().toString());
+//            tmpMap.put(param.getK(), keyMap);
+//            if (RegexUtil.match(ParamElements.LEVEL_REG, param.getV().trim())) {
+//                /*取层级*/
+//                formula.setFormula("FC.tree(trees,WP[" + param.getK() + "])");
+//            } else {
+//                /*直接取数*/
+//                formula.setFormula("WP[" + param.getK() + "]");
+//            }
+//            formula.setMap(JSON.toJSONString(tmpMap));
+//            this.formulaService.save(formula);
+//        }
+        WbsParam wbsParam=this.service.getById(paramId);
+        Long formulaId=this.service.formulaId(wbsParam.getK());
+        if(formulaId==null){
+            R.fail("公式不存在");
         }
         ElementFormulaMapping efm = new ElementFormulaMapping();
         efm.setScope(FormulaBean.PARAM);
         efm.setParamId(paramId);
         efm.setElementId(elementId);
-        efm.setFormulaId(formula.getId());
+        efm.setFormulaId(formulaId);
         return R.status(this.elementFormulaMappingService.save(efm));
     }
 
+
+
     @GetMapping("/refresh")
     @ApiOperationSupport(order = 1)
     @ApiOperation(value = "刷新当前节点的节点参数", notes = "刷新当前节点的节点参数")
@@ -374,31 +409,32 @@ public class WbsParamController {
 
                 List<Long> longList = this.jdbcTemplate.queryForList("select element_id from m_element_formula_mapping where is_deleted=0 and scope=35 and param_id in(" + paramList.stream().map(WbsParam::getId).map(String::valueOf).collect(Collectors.joining(",")) + ")", Long.class);
                 if (Func.isNotEmpty(elementMap)) {
-                    Map<String, Object> tmpMap = new HashMap<>();
+//                    Map<String, Object> tmpMap = new HashMap<>();
                     List<Map<String, Object>> finalElementMap = elementMap;
+                    Map<String,Long> fkMap = this.service.formulaIdKeyMap(paramList.stream().map(WbsParam::getK).collect(Collectors.toList()));
                     paramList.forEach(e -> {
                         /*复用节点参数公式,只要公式脚本一样就直接引用*/
-                        Formula formula = this.formulaService.getOne(Wrappers.<Formula>lambdaQuery().eq(Formula::getParamId, e.getId()));
-                        if (formula == null) {
-                            formula = new Formula();
-                            formula.setOutm(Formula.FULL);
-                            formula.setParamId(e.getId());
-                            Map<String, String> keyMap = new HashMap<>();
-                            keyMap.put("name", e.getName());
-                            keyMap.put("id", e.getId().toString());
-                            tmpMap.put(e.getK(), keyMap);
-                            if (RegexUtil.match(ParamElements.LEVEL_REG, e.getV().trim())) {
-                                /*取层级*/
-                                formula.setFormula("FC.tree(trees,WP[" + e.getK() + "])");
-                            } else {
-                                /*直接取数*/
-                                formula.setFormula("WP[" + e.getK() + "]");
-                            }
-                            formula.setMap(JSON.toJSONString(tmpMap));
-                            this.formulaService.save(formula);
-                            tmpMap.clear();
-                        }
-                        Formula finalFormula = formula;
+//                        Formula formula = this.formulaService.getOne(Wrappers.<Formula>lambdaQuery().eq(Formula::getParamId, e.getId()));
+//                        if (formula == null) {
+//                            formula = new Formula();
+//                            formula.setOutm(Formula.FULL);
+//                            formula.setParamId(e.getId());
+//                            Map<String, String> keyMap = new HashMap<>();
+//                            keyMap.put("name", e.getName());
+//                            keyMap.put("id", e.getId().toString());
+//                            tmpMap.put(e.getK(), keyMap);
+//                            if (RegexUtil.match(ParamElements.LEVEL_REG, e.getV().trim())) {
+//                                /*取层级*/
+//                                formula.setFormula("FC.tree(trees,WP[" + e.getK() + "])");
+//                            } else {
+//                                /*直接取数*/
+//                                formula.setFormula("WP[" + e.getK() + "]");
+//                            }
+//                            formula.setMap(JSON.toJSONString(tmpMap));
+//                            this.formulaService.save(formula);
+//                            tmpMap.clear();
+//                        }
+//                        Formula finalFormula = formula;
                         String name = e.getName().replace("【水】", "").trim();
                         finalElementMap.forEach(m -> {
                             if (StringUtils.handleNull(m.get("name")).contains(name)) {
@@ -408,7 +444,7 @@ public class WbsParamController {
                                     efm.setScope(FormulaBean.PARAM);
                                     efm.setParamId(e.getId());
                                     efm.setElementId(Long.parseLong(m.get("id").toString()));
-                                    efm.setFormulaId(finalFormula.getId());
+                                    efm.setFormulaId(fkMap.get(e.getK()));
                                     this.elementFormulaMappingService.save(efm);
                                 }
                             }
@@ -425,6 +461,22 @@ public class WbsParamController {
 
     }
 
+    /**节点公式创建*/
+    private Formula createFormula(WbsParam e){
+        Formula formula = new Formula();
+        Map<String, Object> tmpMap = new HashMap<>();
+        formula.setOutm(Formula.FULL);
+        formula.setParamId(e.getId());
+        Map<String, String> keyMap = new HashMap<>();
+        keyMap.put("name", e.getName());
+        keyMap.put("id", e.getId().toString());
+        tmpMap.put(e.getK(), keyMap);
+        formula.setFormula("FC.tree(trees,WP[" + e.getK() + "])");
+        formula.setMap(JSON.toJSONString(tmpMap));
+        this.formulaService.save(formula);
+        return formula;
+    }
+
     @GetMapping("/del-duplicate")
     public R<Object> duplicate() {
         try {
@@ -485,6 +537,48 @@ public class WbsParamController {
 
     @GetMapping("/test")
     public R<Object> test() {
-          return R.fail("失败");
+          /*刷模版公式*/
+        List<WbsParam> list =service.list(Wrappers.<WbsParam>lambdaQuery().eq(WbsParam::getType,0));
+        Map<String, Object> tmpMap = new HashMap<>();
+        list.forEach(e->{
+             Formula formula = new Formula();
+              formula.setOutm(Formula.FULL);
+              formula.setParamId(e.getId());
+              Map<String, String> keyMap = new HashMap<>();
+              keyMap.put("name", e.getName());
+              keyMap.put("id", e.getId().toString());
+              tmpMap.put(e.getK(), keyMap);
+              formula.setFormula("FC.tree(trees,WP[" + e.getK().replaceAll("[\\s]+","") + "])");
+              formula.setMap(JSON.toJSONString(tmpMap));
+              this.formulaService.save(formula);
+              tmpMap.clear();
+          });
+          return R.success("完成");
+    }
+
+
+    @GetMapping("/lack")
+    public R<Object> lack(String name) {
+        String tamplate="CREATE TABLE `"+name+"` (\n" +
+                "  `id` bigint(20) NOT NULL COMMENT '主键id',\n" +
+                "  `p_key_id` bigint(20) DEFAULT NULL COMMENT '合同段wbs树表单的p_key_id',\n" +
+                "  `group_id` bigint(20) DEFAULT NULL COMMENT '分组id',\n" +
+                "  #REPLACE\n" +
+                "  PRIMARY KEY (`id`) USING BTREE\n" +
+                ") ENGINE=InnoDB DEFAULT CHARSET=utf8";
+        List<Map<String,Object>> listMap= this.jdbcTemplate.queryForList("select a.tab_ch_name tabName,a.tab_en_name initTableName,b.e_name eName,b.id elementId,b.e_key  eKey ,CONCAT(a.tab_en_name,':',b.e_key) code  from m_table_info a join m_wbs_form_element b on b.f_id=a.id where a.tab_en_name in ('"+name+"') and b.is_deleted=0");
+        if(listMap.size()>0){
+            List<String> keys = listMap.stream().map(m-> Func.toStr(m.get("ekey"))).collect(Collectors.toList());
+            String target = keys.stream().distinct().filter(Func::isNotBlank).map(s-> "`"+s+"` varchar(80) DEFAULT NULL,").collect(Collectors.joining("\n"));
+            tamplate=tamplate.replace("#REPLACE",target);
+            System.out.println(tamplate);
+            this.jdbcTemplate.execute(tamplate);
+            return R.success("完成");
+        }
+        return R.fail("创建失败");
     }
+
+
+
+
 }

+ 17 - 28
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/WbsTreeContractController.java

@@ -40,33 +40,6 @@ public class WbsTreeContractController extends BladeController {
     @ApiOperation(value = "查询当前节点下所有元素表信息", notes = "传入节点primaryKeyId、type、合同段id、项目id")
     public R searchNodeAllTable(String primaryKeyId, String type, String contractId, String projectId) {
         List<AppWbsTreeContractVO> list = iWbsTreeContractService.searchNodeAllTable(primaryKeyId, type, contractId, projectId);
-        /*boolean flag = false;
-        Set<Long> l1 = new HashSet<>();
-        for (AppWbsTreeContractVO vo : list) {
-            if (vo.getNodeName().contains("_PL_")){
-                l1.add(vo.getId());
-                flag = true;
-            }
-        }
-        if (flag){
-            for (Long aLong : l1) {
-                List<AppWbsTreeContractVO> vos = new ArrayList<>();
-                for (AppWbsTreeContractVO vo : list) {
-                    if (aLong.equals(vo.getId())){
-                        vos.add(vo);
-                    }
-                }
-                list = list.stream().filter(l -> {
-                    if (l.getId().equals(aLong)){
-                        return false;
-                    }else {
-                        return true;
-                    }
-                }).collect(Collectors.toList());
-                vos = vos.stream().sorted(Comparator.comparing(AppWbsTreeContractVO::getPKeyId)).collect(Collectors.toList());
-                list.addAll(vos);
-            }
-        }*/
         if (list.size() > 0) {
             list.forEach(l -> {
                 if (StringUtils.isNotBlank(l.getHtmlUrl())) {
@@ -176,7 +149,7 @@ public class WbsTreeContractController extends BladeController {
     /**
      * 客户端懒加载获取合同段树(统计颜色、填报数量)
      *
-     * @author liuYC
+     * @author liuyc
      * @date 2023年7月17日10:28:49
      */
     @GetMapping("/lazyQueryContractWbsTree")
@@ -224,4 +197,20 @@ public class WbsTreeContractController extends BladeController {
         return R.status(iWbsTreeContractService.syncContractTabSort(projectId));
     }
 
+
+    /**
+     * 获取合同段详情id
+     */
+    @PostMapping("/getWbsContractById")
+    @ApiOperationSupport(order = 11)
+    @ApiOperation(value = "获取合同段详情", notes = "传入节点pKeyId")
+    @ApiImplicitParams(value = {
+            @ApiImplicitParam(name = "pKeyId", value = "节点pKeyId", required = true)
+    })
+    public R<WbsTreeContract> getWbsContractById(@RequestParam("pKeyId") String pKeyId){
+        WbsTreeContract wbsTreeContract = iWbsTreeContractService.getOne(Wrappers.<WbsTreeContract>query().lambda()
+                .eq(WbsTreeContract::getPKeyId, pKeyId).eq(WbsTreeContract::getIsDeleted, 0));
+        return R.data(wbsTreeContract);
+    }
+
 }

+ 1 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/TableElementConverter.java

@@ -140,6 +140,7 @@ public class TableElementConverter implements ITableElementConverter {
                 fd.setEName(one.getEName());
                 fd.setEAllowDeviation(one.getEAllowDeviation());
                 fd.setEType(one.getEType());
+                fd.setId(one.getFieldId());
                 /*初始化元素数据集*/
                 List<ElementData> eds = fd.getValues();
                 for (int i = 0; i < kms.size(); i++) {

+ 1 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/ExcelTabMapper.xml

@@ -22,6 +22,7 @@
         <result column="attach_size" property="attachSize"/>
         <result column="tab_type" property="tabType"/>
         <result column="sort" property="sort"/>
+        <result column="tab_id" property="tabId"/>
     </resultMap>
 
     <resultMap id="treeNodeResultMap" type="org.springblade.manager.vo.ExceTabTreVO">

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

@@ -437,7 +437,7 @@
                 #{tableOwnerList}
             </foreach>
         </if>
-        ORDER BY sort,full_name
+        ORDER BY sort,full_name,create_time
     </select>
 
     <select id="selectRoleInfo" resultType="org.springblade.manager.entity.SaveUserInfoByProject">

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

@@ -316,7 +316,8 @@
         UPDATE m_wbs_tree_private
         SET html_url        = #{wbsTreePrivate.htmlUrl},
             init_table_name = #{wbsTreePrivate.initTableName},
-            init_table_id   = #{wbsTreePrivate.initTableId}
+            init_table_id   = #{wbsTreePrivate.initTableId},
+            node_name       = #{wbsTreePrivate.nodeName}
         WHERE project_id = #{wbsTreePrivate.projectId}
           and excel_id = #{wbsTreePrivate.excelId}
     </update>

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

@@ -79,7 +79,7 @@ public interface IContractInfoService extends BaseService<ContractInfo> {
 
     List<ContractInfo> getContractListByProjectId(Long projectId);
 
-    R getTreeNodeByValueAndContractId(String queryValue, String contractId);
+    R<Object> getTreeNodeByValueAndContractId(String queryValue, String contractId, String tableOwner);
 
     void updateIsArchivesAutoById(Long id, Integer isArchivesAuto);
 

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

@@ -1,11 +1,13 @@
 package org.springblade.manager.service;
 
 import org.springblade.core.mp.base.BaseService;
+import org.springblade.manager.entity.Formula;
 import org.springblade.manager.entity.WbsParam;
 import org.springblade.manager.entity.WbsTreeContract;
 
 import javax.validation.constraints.NotNull;
 import java.util.List;
+import java.util.Map;
 
 /**
  * @author yangyj
@@ -29,6 +31,13 @@ public interface IWbsParamService extends BaseService<WbsParam> {
     List<WbsParam> findByNodeId(Long nodeId);
 
     List<WbsTreeContract> chain(Long contractId, Long id, Long pkId, WbsTreeContract wbsTreeContract);
-     List<WbsTreeContract> tracing(@NotNull Long pkeyId);
+
+    List<WbsTreeContract> tracing(@NotNull Long pkeyId);
+    /**查重删除*/
     void duplicate(Long nodeId);
+    /**formulaId和参数key的映射*/
+    Map<String,Long> formulaIdKeyMap(List<String> ks);
+    /**指定key的formulaId映射*/
+    Long formulaId(String k);
+    Map<String, Formula> formulaKeyMap(List<String> ks);
 }

+ 226 - 98
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ContractInfoServiceImpl.java

@@ -1,5 +1,7 @@
 package org.springblade.manager.service.impl;
 
+import cn.hutool.core.lang.hash.Hash;
+import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@@ -30,6 +32,8 @@ import org.springblade.system.user.entity.User;
 import org.springblade.system.user.feign.IUserClient;
 import org.springblade.system.user.vo.UserContractInfoVO;
 import org.springblade.system.user.vo.UserVO2;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.StringRedisTemplate;
 import org.springframework.jdbc.core.BeanPropertyRowMapper;
 import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.scheduling.annotation.Async;
@@ -37,6 +41,7 @@ import org.springframework.stereotype.Service;
 
 import java.io.IOException;
 import java.util.*;
+import java.util.function.Function;
 import java.util.stream.Collectors;
 
 @Service
@@ -48,11 +53,14 @@ public class ContractInfoServiceImpl extends BaseServiceImpl<ContractInfoMapper,
     private final SaveUserInfoByProjectMapper saveUserInfoByProjectMapper;
     private final SaveUserInfoByProjectServiceImpl saveUserInfoByProjectService;
     private final WbsTreeContractMapper wbsTreeContractMapper;
+    private final WbsTreeContractServiceImpl wbsTreeContractServiceImpl;
     private final WbsTreePrivateMapper wbsTreePrivateMapper;
     private final JdbcTemplate jdbcTemplate;
     private final IUserClient iUserClient;
     private final InformationQueryClient informationQueryClient;
     private final ArchiveTreeContractMapper archiveTreeContractMapper;
+    @Autowired
+    StringRedisTemplate redisTemplate;
 
     @Override
     public List<String> getProcessContractByJLContractId(String contractId) {
@@ -308,118 +316,218 @@ public class ContractInfoServiceImpl extends BaseServiceImpl<ContractInfoMapper,
     }
 
     @Override
-    public R getTreeNodeByValueAndContractId(String queryValue, String contractId) {
-        Map<Long, List<WbsTreeContractTreeAllVO>> resultMaps = new LinkedHashMap<>();
+    public R<Object> getTreeNodeByValueAndContractId(String queryValue, String contractId, String tableOwner) {
         if (StringUtils.isNotEmpty(queryValue) && StringUtils.isNotEmpty(contractId)) {
             ContractInfo contractInfo = contractInfoMapper.selectById(contractId);
             if (contractInfo != null) {
-                //质检
+                //TODO 质检
                 if (contractInfo.getContractType().equals(1)) {
-                    //获取查询有效节点信息,以及所有上级父级节点
+                    //获取查询有效节点信息
                     LambdaQueryWrapper<WbsTreeContract> queryWrapper = new LambdaQueryWrapper<>();
+                    queryWrapper.select(WbsTreeContract::getParentId, WbsTreeContract::getId, WbsTreeContract::getPKeyId);
                     queryWrapper.like(WbsTreeContract::getFullName, queryValue);
                     queryWrapper.eq(WbsTreeContract::getContractId, contractId);
                     queryWrapper.eq(WbsTreeContract::getType, 1);
+                    //所有匹配节点
                     List<WbsTreeContract> nodes = wbsTreeContractMapper.selectList(queryWrapper);
-                    Set<WbsTreeContract> resultNodes = new LinkedHashSet<>();
-                    this.recursiveGetParentNodes(resultNodes, nodes, contractId);
-                    resultNodes.addAll(nodes);
-                    List<String> nodePkeyIds = resultNodes.stream().map(WbsTreeContract::getPKeyId).map(String::valueOf).collect(Collectors.toList());
-
-                    //获取填报过的资料信息Map
-                    Set<InformationQuery> informationQuerySet = new HashSet<>();
-                    List<List<String>> partition = Lists.partition(nodePkeyIds, 500);
-                    for (List<String> wbsIds : partition) {
-                        List<InformationQuery> informationQueryList = jdbcTemplate.query("select wbs_id,status from u_information_query where wbs_id in(" + org.apache.commons.lang.StringUtils.join(wbsIds, ",") + ")", new BeanPropertyRowMapper<>(InformationQuery.class));
-                        informationQuerySet.addAll(informationQueryList);
-                    }
-                    Map<Long, Integer> informationQueryMaps = informationQuerySet.stream().collect(Collectors.toMap(InformationQuery::getWbsId, InformationQuery::getStatus, (v1, v2) -> v1));
-
-                    //构造vo
-                    List<WbsTreeContractTreeAllVO> wbsTreeContractTreeAllVOS = resultNodes.stream().map(node -> {
-                        WbsTreeContractTreeAllVO vo = BeanUtil.copyProperties(node, WbsTreeContractTreeAllVO.class);
-                        if (vo != null) {
-                            vo.setType(ObjectUtils.isNotEmpty(node.getNodeType()) ? node.getNodeType() : 0);
-                            vo.setTitle(node.getFullName());
-                            vo.setPrimaryKeyId(node.getPKeyId());
-                            if (ObjectUtils.isNotEmpty(informationQueryMaps.get(vo.getPrimaryKeyId()))) {
-                                vo.setSubmitCounts(1L); //如果存在资料填报信息,那么计数
-                                vo.setColorStatus(informationQueryMaps.get(vo.getPrimaryKeyId())); //颜色
-                            } else {
-                                vo.setSubmitCounts(0L);
-                                vo.setColorStatus(null); //没填报就是null
+                    if (nodes.size() > 0) {
+                        //获取当前合同段所有缓存节点信息
+                        List<WbsTreeContractLazyVO> nodesAllTemp;
+                        Object data = redisTemplate.opsForValue().get("blade-manager::contract:wbstree:" + contractId);
+                        if (data != null) {
+                            nodesAllTemp = JSON.parseArray(data.toString(), WbsTreeContractLazyVO.class);
+                        } else {
+                            nodesAllTemp = jdbcTemplate.query("select a.p_key_id,a.id,a.parent_id,(SELECT CASE WHEN count(1) > 0 THEN 1 ELSE 0 END FROM m_wbs_tree_contract b WHERE b.parent_id = a.id AND type = 1 AND b.contract_id = " + contractId + " AND b.is_deleted = 0 ) AS hasChildren from m_wbs_tree_contract a where type = 1 and status = 1 and is_deleted = 0 and contract_id = " + contractId, new BeanPropertyRowMapper<>(WbsTreeContractLazyVO.class));
+                            if (nodesAllTemp.size() > 0) {
+                                JSONArray array = JSONArray.parseArray(JSON.toJSONString(nodesAllTemp));
+                                redisTemplate.opsForValue().set("blade-manager::contract:wbstree:" + contractId, JSON.toJSON(array).toString());
                             }
                         }
-                        return vo;
-                    }).collect(Collectors.toList());
-
-                    //构造树形结构
-                    List<WbsTreeContractTreeAllVO> reNodes = this.buildWbsTreeByStreamByTreeAll(wbsTreeContractTreeAllVOS);
 
-                    //获取构造完的List集合
-                    LinkedList<WbsTreeContractTreeAllVO> resultNodesAll = new LinkedList<>();
-                    this.getNodesAll(reNodes, resultNodesAll);
-                    resultNodesAll.addAll(0, reNodes);
-
-                    //处理父级节点计数、颜色问题
-                    this.reSetSubmitCountsAndColorStatus(resultNodesAll);
-                    return R.data(reNodes);
+                        //去重
+                        List<WbsTreeContractLazyVO> distinctNodesAll = nodesAllTemp.stream()
+                                .collect(Collectors.collectingAndThen(
+                                        Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(WbsTreeContractLazyVO::getPKeyId))),
+                                        ArrayList::new
+                                ));
+                        //所有最底层节点
+                        List<WbsTreeContractLazyVO> distinctLowestNodesAll = distinctNodesAll.stream().filter(f -> f.getHasChildren().equals(0)).collect(Collectors.collectingAndThen(
+                                Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(WbsTreeContractLazyVO::getPKeyId))),
+                                ArrayList::new
+                        ));
+
+                        List<Long> parentIds = nodes.stream().map(WbsTreeContract::getParentId).collect(Collectors.toList());
+                        List<Long> ids = nodes.stream().map(WbsTreeContract::getId).collect(Collectors.toList());
+                        //所有匹配的PKeyIds
+                        Set<Long> resultNodesPKeyIds = new LinkedHashSet<>();
+                        //获取所有匹配节点的父级
+                        this.recursiveGetParentNodes(resultNodesPKeyIds, parentIds, nodesAllTemp);
+                        //获取所有匹配节点的子级
+                        this.recursiveGetChildNodes(resultNodesPKeyIds, ids, nodesAllTemp);
+
+                        //获取结果集节点
+                        resultNodesPKeyIds.addAll(nodes.stream().map(WbsTreeContract::getPKeyId).collect(Collectors.toList()));
+                        List<WbsTreeContract> wbsTreeContractList = wbsTreeContractMapper.selectList(Wrappers.<WbsTreeContract>lambdaQuery().in(WbsTreeContract::getPKeyId, resultNodesPKeyIds));
+
+                        //获取当前合同段填报过的资料信息Map
+                        List<InformationQuery> informationQueryList;
+                        if (ObjectUtil.isEmpty(tableOwner)) {
+                            informationQueryList = jdbcTemplate.query("select wbs_id,status from u_information_query where type = 1 and contract_id = " + contractId, new BeanPropertyRowMapper<>(InformationQuery.class));
+                        } else {
+                            informationQueryList = jdbcTemplate.query("select wbs_id,status from u_information_query where type = 1 and contract_id = " + contractId + " and classify = " + tableOwner, new BeanPropertyRowMapper<>(InformationQuery.class));
+                        }
+                        Map<Long, Integer> informationQueryMaps = informationQueryList.stream().collect(Collectors.toMap(InformationQuery::getWbsId, InformationQuery::getStatus, (v1, v2) -> v1));
+                        List<Long> pKeyIdList = new ArrayList<>(informationQueryMaps.keySet());
+
+                        //填报过的所有最底层节点(并且是查询有效节点的最下级节点)处理数量
+                        List<WbsTreeContractLazyVO> lowestNodesTB = distinctLowestNodesAll.stream().filter(f -> pKeyIdList.contains(f.getPKeyId()) && resultNodesPKeyIds.contains(f.getPKeyId())).collect(Collectors.toList());
+                        List<Long> lowestNodeParentIdsTB = lowestNodesTB.stream().map(WbsTreeContractLazyVO::getParentId).collect(Collectors.toList());
+                        List<WbsTreeContractLazyVO> resultParentNodesTB = new ArrayList<>();
+                        wbsTreeContractServiceImpl.recursiveGetParentNodes(resultParentNodesTB, lowestNodeParentIdsTB, nodesAllTemp);
+
+                        //最底层节点颜色构造后Map
+                        Map<Long, WbsTreeContractLazyVO> lowestNodesMap = lowestNodesTB.stream()
+                                .peek(vo -> {
+                                    Integer colorStatus = informationQueryMaps.get(vo.getPKeyId());
+                                    if (colorStatus != null) {
+                                        //任务状态0=未上报=颜色2蓝色、任务状态1=待审批=颜色3橙色、任务状态2=已审批=颜色4绿色、任务状态3=已废除=颜色1黑色
+                                        vo.setColorStatus(colorStatus == 0 ? 2 : (colorStatus == 1 ? 3 : (colorStatus == 2 ? 4 : 1)));
+                                    } else {
+                                        //未填报的=颜色1黑色
+                                        vo.setColorStatus(1);
+                                    }
+                                }).collect(Collectors.toMap(WbsTreeContractLazyVO::getPKeyId, Function.identity()));
 
+                        //构造vo
+                        if (wbsTreeContractList.size() > 0) {
+                            //处理填报数量
+                            Map<Long, Long> countMap = new HashMap<>();
+                            for (WbsTreeContractLazyVO node : resultParentNodesTB) {
+                                Long key = node.getPKeyId();
+                                if (countMap.containsKey(key)) {
+                                    countMap.put(key, countMap.get(key) + 1L);
+                                } else {
+                                    countMap.put(key, 1L);
+                                }
+                            }
+                            List<WbsTreeContractTreeAllVO> wbsTreeContractTreeAllVOS = wbsTreeContractList.stream().map(node -> {
+                                WbsTreeContractTreeAllVO vo = BeanUtil.copyProperties(node, WbsTreeContractTreeAllVO.class);
+                                if (vo != null) {
+                                    vo.setType(ObjectUtils.isNotEmpty(node.getNodeType()) ? node.getNodeType() : 0);
+                                    vo.setTitle(ObjectUtil.isNotEmpty(node.getFullName()) ? node.getFullName() : node.getNodeName());
+                                    vo.setPrimaryKeyId(node.getPKeyId());
+                                    vo.setSubmitCounts(ObjectUtil.isNotEmpty(countMap.get(vo.getPrimaryKeyId())) ? countMap.get(vo.getPrimaryKeyId()) : (ObjectUtil.isNotEmpty(informationQueryMaps.get(vo.getPrimaryKeyId())) ? 1L : 0L));
+                                    if (vo.getSubmitCounts() >= 1L) {
+                                        vo.setColorStatus(2);
+                                    }
+                                    WbsTreeContractLazyVO lowestNode = lowestNodesMap.get(vo.getPrimaryKeyId());
+                                    if (lowestNode != null) {
+                                        vo.setColorStatus(lowestNode.getColorStatus());
+                                    }
+                                }
+                                return vo;
+                            }).collect(Collectors.toList());
+                            return R.data(this.buildWbsTreeByStreamByTreeAll(wbsTreeContractTreeAllVOS));
+                        }
+                    }
                 } else if (contractInfo.getContractType().equals(2) || contractInfo.getContractType().equals(3)) {
-                    //监理、指挥部
+                    //TODO 监理、指挥部
+                    Map<Long, List<WbsTreeContractTreeAllVO>> resultMaps = new LinkedHashMap<>();
                     List<ContractRelationJlyz> relationJLYZList = jdbcTemplate.query("select * from m_contract_relation_jlyz where contract_id_jlyz = " + contractId, new BeanPropertyRowMapper<>(ContractRelationJlyz.class));
-
+                    if (ObjectUtil.isEmpty(relationJLYZList) || relationJLYZList.size() <= 0) {
+                        return null;
+                    }
                     for (ContractRelationJlyz contractRelationJlyz : relationJLYZList) {
-                        //获取查询的有效节点信息,以及所有上级父级节点
                         LambdaQueryWrapper<WbsTreeContract> queryWrapper = new LambdaQueryWrapper<>();
+                        queryWrapper.select(WbsTreeContract::getParentId, WbsTreeContract::getId, WbsTreeContract::getPKeyId);
                         queryWrapper.like(WbsTreeContract::getFullName, queryValue);
                         queryWrapper.eq(WbsTreeContract::getContractId, contractRelationJlyz.getContractIdSg());
                         queryWrapper.eq(WbsTreeContract::getType, 1);
                         List<WbsTreeContract> nodes = wbsTreeContractMapper.selectList(queryWrapper);
-                        Set<WbsTreeContract> resultNodes = new LinkedHashSet<>();
-                        this.recursiveGetParentNodes(resultNodes, nodes, contractRelationJlyz.getContractIdSg() + "");
-                        resultNodes.addAll(nodes);
-                        List<String> nodePkeyIds = resultNodes.stream().map(WbsTreeContract::getPKeyId).map(String::valueOf).collect(Collectors.toList());
-
-                        //获取填报过的资料信息Map
-                        Set<InformationQuery> informationQuerySet = new HashSet<>();
-                        List<List<String>> partition = Lists.partition(nodePkeyIds, 500);
-                        for (List<String> wbsIds : partition) {
-                            List<InformationQuery> informationQueryList = jdbcTemplate.query("select wbs_id,status from u_information_query where wbs_id in(" + org.apache.commons.lang.StringUtils.join(wbsIds, ",") + ")", new BeanPropertyRowMapper<>(InformationQuery.class));
-                            informationQuerySet.addAll(informationQueryList);
-                        }
-                        Map<Long, Integer> informationQueryMaps = informationQuerySet.stream().collect(Collectors.toMap(InformationQuery::getWbsId, InformationQuery::getStatus, (v1, v2) -> v1));
-
-                        //构造vo
-                        List<WbsTreeContractTreeAllVO> wbsTreeContractTreeAllVOS = resultNodes.stream().map(node -> {
-                            WbsTreeContractTreeAllVO vo = BeanUtil.copyProperties(node, WbsTreeContractTreeAllVO.class);
-                            if (vo != null) {
-                                vo.setType(ObjectUtils.isNotEmpty(node.getNodeType()) ? node.getNodeType() : 0);
-                                vo.setTitle(node.getFullName());
-                                vo.setPrimaryKeyId(node.getPKeyId());
-                                if (ObjectUtils.isNotEmpty(informationQueryMaps.get(vo.getPrimaryKeyId()))) {
-                                    vo.setSubmitCounts(1L); //如果存在资料填报信息,那么计数
-                                    vo.setColorStatus(informationQueryMaps.get(vo.getPrimaryKeyId())); //颜色
-                                } else {
-                                    vo.setSubmitCounts(0L);
-                                    vo.setColorStatus(null); //没填报就是null
+                        if (nodes.size() > 0) {
+                            List<WbsTreeContractLazyVO> nodesAllTemp;
+                            Object data = redisTemplate.opsForValue().get("blade-manager::contract:wbstree:" + contractRelationJlyz.getContractIdSg());
+                            if (data != null) {
+                                nodesAllTemp = JSON.parseArray(data.toString(), WbsTreeContractLazyVO.class);
+                            } else {
+                                nodesAllTemp = jdbcTemplate.query("select a.p_key_id,a.id,a.parent_id,(SELECT CASE WHEN count(1) > 0 THEN 1 ELSE 0 END FROM m_wbs_tree_contract b WHERE b.parent_id = a.id AND type = 1 AND b.contract_id = " + contractRelationJlyz.getContractIdSg() + " AND b.is_deleted = 0 ) AS hasChildren from m_wbs_tree_contract a where type = 1 and status = 1 and is_deleted = 0 and contract_id = " + contractRelationJlyz.getContractIdSg(), new BeanPropertyRowMapper<>(WbsTreeContractLazyVO.class));
+                                if (nodesAllTemp.size() > 0) {
+                                    JSONArray array = JSONArray.parseArray(JSON.toJSONString(nodesAllTemp));
+                                    redisTemplate.opsForValue().set("blade-manager::contract:wbstree:" + contractId, JSON.toJSON(array).toString());
                                 }
                             }
-                            return vo;
-                        }).collect(Collectors.toList());
-
-                        //构造树形结构
-                        List<WbsTreeContractTreeAllVO> reNodes = this.buildWbsTreeByStreamByTreeAll(wbsTreeContractTreeAllVOS);
 
-                        //获取构造完的List集合
-                        LinkedList<WbsTreeContractTreeAllVO> resultNodesAll = new LinkedList<>();
-                        this.getNodesAll(reNodes, resultNodesAll);
-                        resultNodesAll.addAll(0, reNodes);
-
-                        //处理父级节点计数、颜色问题
-                        this.reSetSubmitCountsAndColorStatus(resultNodesAll);
-                        //返回结果集
-                        resultMaps.put(contractRelationJlyz.getContractIdSg(), reNodes);
+                            List<WbsTreeContractLazyVO> distinctNodesAll = nodesAllTemp.stream()
+                                    .collect(Collectors.collectingAndThen(
+                                            Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(WbsTreeContractLazyVO::getPKeyId))),
+                                            ArrayList::new
+                                    ));
+                            List<WbsTreeContractLazyVO> distinctLowestNodesAll = distinctNodesAll.stream().filter(f -> f.getHasChildren().equals(0)).collect(Collectors.collectingAndThen(
+                                    Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(WbsTreeContractLazyVO::getPKeyId))),
+                                    ArrayList::new
+                            ));
+
+                            List<Long> parentIds = nodes.stream().map(WbsTreeContract::getParentId).collect(Collectors.toList());
+                            List<Long> ids = nodes.stream().map(WbsTreeContract::getId).collect(Collectors.toList());
+                            Set<Long> resultNodesPKeyIds = new LinkedHashSet<>();
+                            this.recursiveGetParentNodes(resultNodesPKeyIds, parentIds, nodesAllTemp);
+                            this.recursiveGetChildNodes(resultNodesPKeyIds, ids, nodesAllTemp);
+                            resultNodesPKeyIds.addAll(nodes.stream().map(WbsTreeContract::getPKeyId).collect(Collectors.toList()));
+                            List<WbsTreeContract> wbsTreeContractList = wbsTreeContractMapper.selectList(Wrappers.<WbsTreeContract>lambdaQuery().in(WbsTreeContract::getPKeyId, resultNodesPKeyIds));
+
+                            List<InformationQuery> informationQueryList;
+                            if (ObjectUtil.isEmpty(tableOwner)) {
+                                informationQueryList = jdbcTemplate.query("select wbs_id,status from u_information_query where type = 1 and contract_id = " + contractRelationJlyz.getContractIdSg(), new BeanPropertyRowMapper<>(InformationQuery.class));
+                            } else {
+                                informationQueryList = jdbcTemplate.query("select wbs_id,status from u_information_query where type = 1 and contract_id = " + contractRelationJlyz.getContractIdSg() + " and classify = " + tableOwner, new BeanPropertyRowMapper<>(InformationQuery.class));
+                            }
+                            Map<Long, Integer> informationQueryMaps = informationQueryList.stream().collect(Collectors.toMap(InformationQuery::getWbsId, InformationQuery::getStatus, (v1, v2) -> v1));
+                            List<Long> pKeyIdList = new ArrayList<>(informationQueryMaps.keySet());
+
+                            List<WbsTreeContractLazyVO> lowestNodesTB = distinctLowestNodesAll.stream().filter(f -> pKeyIdList.contains(f.getPKeyId()) && resultNodesPKeyIds.contains(f.getPKeyId())).collect(Collectors.toList());
+                            List<Long> lowestNodeParentIdsTB = lowestNodesTB.stream().map(WbsTreeContractLazyVO::getParentId).collect(Collectors.toList());
+                            List<WbsTreeContractLazyVO> resultParentNodesTB = new ArrayList<>();
+                            wbsTreeContractServiceImpl.recursiveGetParentNodes(resultParentNodesTB, lowestNodeParentIdsTB, nodesAllTemp);
+                            Map<Long, WbsTreeContractLazyVO> lowestNodesMap = lowestNodesTB.stream()
+                                    .peek(vo -> {
+                                        Integer colorStatus = informationQueryMaps.get(vo.getPKeyId());
+                                        if (colorStatus != null) {
+                                            vo.setColorStatus(colorStatus == 0 ? 2 : (colorStatus == 1 ? 3 : (colorStatus == 2 ? 4 : 1)));
+                                        } else {
+                                            vo.setColorStatus(1);
+                                        }
+                                    }).collect(Collectors.toMap(WbsTreeContractLazyVO::getPKeyId, Function.identity()));
+
+                            if (wbsTreeContractList.size() > 0) {
+                                Map<Long, Long> countMap = new HashMap<>();
+                                for (WbsTreeContractLazyVO node : resultParentNodesTB) {
+                                    Long key = node.getPKeyId();
+                                    if (countMap.containsKey(key)) {
+                                        countMap.put(key, countMap.get(key) + 1L);
+                                    } else {
+                                        countMap.put(key, 1L);
+                                    }
+                                }
+                                List<WbsTreeContractTreeAllVO> wbsTreeContractTreeAllVOS = wbsTreeContractList.stream().map(node -> {
+                                    WbsTreeContractTreeAllVO vo = BeanUtil.copyProperties(node, WbsTreeContractTreeAllVO.class);
+                                    if (vo != null) {
+                                        vo.setType(ObjectUtils.isNotEmpty(node.getNodeType()) ? node.getNodeType() : 0);
+                                        vo.setTitle(ObjectUtil.isNotEmpty(node.getFullName()) ? node.getFullName() : node.getNodeName());
+                                        vo.setPrimaryKeyId(node.getPKeyId());
+                                        vo.setSubmitCounts(ObjectUtil.isNotEmpty(countMap.get(vo.getPrimaryKeyId())) ? countMap.get(vo.getPrimaryKeyId()) : (ObjectUtil.isNotEmpty(informationQueryMaps.get(vo.getPrimaryKeyId())) ? 1L : 0L));
+                                        if (vo.getSubmitCounts() >= 1L) {
+                                            vo.setColorStatus(2);
+                                        }
+                                        WbsTreeContractLazyVO lowestNode = lowestNodesMap.get(vo.getPrimaryKeyId());
+                                        if (lowestNode != null) {
+                                            vo.setColorStatus(lowestNode.getColorStatus());
+                                        }
+                                    }
+                                    return vo;
+                                }).collect(Collectors.toList());
+                                resultMaps.put(contractRelationJlyz.getContractIdSg(), this.buildWbsTreeByStreamByTreeAll(wbsTreeContractTreeAllVOS));
+                            }
+                        }
                     }
                     return R.data(resultMaps);
                 }
@@ -511,7 +619,7 @@ public class ContractInfoServiceImpl extends BaseServiceImpl<ContractInfoMapper,
         for (WbsTreeContractTreeAllVO node : reNodes) {
             if (node.getChildren() != null && !node.getChildren().isEmpty()) {
                 result.addAll(node.getChildren());
-                getNodesAll(node.getChildren(), result);
+                this.getNodesAll(node.getChildren(), result);
             }
         }
     }
@@ -519,17 +627,37 @@ public class ContractInfoServiceImpl extends BaseServiceImpl<ContractInfoMapper,
     /**
      * 反向递归获取父级
      *
-     * @param resultNodes
-     * @param nodes
-     * @param contractId
+     * @param resultPKeyIds  结果集PKeyIds
+     * @param nodesParentIds 父级节点ids
+     * @param nodesAllTemp   当合同段所有节点缓存
      */
-    private void recursiveGetParentNodes(Set<WbsTreeContract> resultNodes, List<WbsTreeContract> nodes, String contractId) {
-        Set<String> parentIds = nodes.stream().map(WbsTreeContract::getParentId).map(String::valueOf).filter(ObjectUtils::isNotEmpty).collect(Collectors.toSet());
-        if (parentIds.size() > 0) {
-            List<WbsTreeContract> parentNodes = jdbcTemplate.query("select * from m_wbs_tree_contract where is_deleted = 0 and status = 1 and type = 1 and id in(" + org.apache.commons.lang.StringUtils.join(parentIds, ",") + ") and contract_id = " + contractId, new BeanPropertyRowMapper<>(WbsTreeContract.class));
+    private void recursiveGetParentNodes(Set<Long> resultPKeyIds, List<Long> nodesParentIds, List<WbsTreeContractLazyVO> nodesAllTemp) {
+        if (nodesParentIds.size() > 0) {
+            List<WbsTreeContractLazyVO> parentNodes = nodesAllTemp.stream().filter(f -> nodesParentIds.contains(f.getId())).collect(Collectors.toList());
             if (parentNodes.size() > 0) {
-                resultNodes.addAll(parentNodes);
-                this.recursiveGetParentNodes(resultNodes, parentNodes, contractId);
+                List<Long> pKeyIds = parentNodes.stream().map(WbsTreeContractLazyVO::getPKeyId).collect(Collectors.toList());
+                List<Long> parentIds = parentNodes.stream().map(WbsTreeContractLazyVO::getParentId).filter(ObjectUtils::isNotEmpty).collect(Collectors.toList());
+                resultPKeyIds.addAll(pKeyIds);
+                this.recursiveGetParentNodes(resultPKeyIds, parentIds, nodesAllTemp);
+            }
+        }
+    }
+
+    /**
+     * 递归获取子级
+     *
+     * @param resultPKeyIds 结果集PKeyIds
+     * @param nodesIds      子级节点ids
+     * @param nodesAllTemp  当合同段所有节点缓存
+     */
+    private void recursiveGetChildNodes(Set<Long> resultPKeyIds, List<Long> nodesIds, List<WbsTreeContractLazyVO> nodesAllTemp) {
+        if (nodesIds.size() > 0) {
+            List<WbsTreeContractLazyVO> childNodes = nodesAllTemp.stream().filter(f -> nodesIds.contains(f.getParentId())).collect(Collectors.toList());
+            if (childNodes.size() > 0) {
+                List<Long> pKeyIds = childNodes.stream().map(WbsTreeContractLazyVO::getPKeyId).collect(Collectors.toList());
+                List<Long> ids = childNodes.stream().map(WbsTreeContractLazyVO::getId).filter(ObjectUtils::isNotEmpty).collect(Collectors.toList());
+                resultPKeyIds.addAll(pKeyIds);
+                this.recursiveGetChildNodes(resultPKeyIds, ids, nodesAllTemp);
             }
         }
     }

+ 225 - 199
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ExcelTabServiceImpl.java

@@ -298,7 +298,7 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
                         String lastStr = dataInfo2.getString(ziduan[0]) + "_^_" + ziduan[0].split("__")[1];
                         for (int i = 1; i < ziduan.length; i++) {
                             String keyData = dataInfo2.getString(ziduan[i]);
-                            if (!keyData.equals("")) {
+                            if (StringUtils.isNotEmpty(keyData) && !keyData.equals("")) {
                                 lastStr += "☆" + dataInfo2.getString(ziduan[i]) + "_^_" + ziduan[i].split("__")[1];
                             }
 
@@ -959,6 +959,7 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
                         transactionManager1.rollback(transactionStatus);
                         log.append(e.getMessage()).append("@@");
                         e.printStackTrace();
+                        return R.fail(wbsTreeContract.getNodeName());
                     }
                 }
 
@@ -1085,105 +1086,117 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
 
         // 匹配关联
         try {
-            File file1 = ResourceUtil.getFile(wbsTreeContract.getHtmlUrl());
-            if (file1.exists()) {
-
-                String htmlString = IoUtil.readToString(new FileInputStream(file1));
-                Document doc = Jsoup.parse(htmlString);
-
-                // 解析
-                // 模糊匹配
-                Elements dwtitle = doc.select("el-input[placeholder~=.*承包单位]");
-                Elements sgtitle = doc.select("el-input[placeholder~=^施工单位]");
-                Elements sgtitle1 = doc.select("el-input[placeholder=安装单位]");
-                sgtitle.addAll(sgtitle1);
-
-                Elements htdtitle = doc.select("el-input[placeholder~=.*合同段.*]");
-                Elements htdtitle1 = doc.select("el-input[placeholder~=合同名称.*]");
-                htdtitle.addAll(htdtitle1);
-
-                Elements jltitle = doc.select("el-input[placeholder~=监理单位.*]");
-
-                Elements bhtitle = doc.select("el-input[placeholder~=^编号]");
-                Elements bhtitle1 = doc.select("el-input[placeholder~=合同编号.*]");
-                bhtitle.addAll(bhtitle1);
-
-
-                Elements xmtitle = doc.select("el-input[placeholder~=^项目名称]");
-
+            InputStream inputStreamByUrl = FileUtils.getInputStreamByUrl(wbsTreeContract.getHtmlUrl());
 
-                // Elements title = doc.select("el-input[placeholder~=^编号]");
+            String htmlString = IoUtil.readToString(inputStreamByUrl);
+            Document doc = Jsoup.parse(htmlString);
 
-                /**
-                 * 承包单位 承包单位、施工单位:引用施工单位名称 ,
-                 * 监理单位:引用监理单位名称
-                 * 合同段、所属建设项目(合同段):引用合同段编号
-                 *
-                 * 施工单位:施工单位 和 安装单位
-                 *
-                 */
-                ContractInfo contractInfo = contractInfoService.getById(wbsTreeContract.getContractId());
-                // 施工单位名称
-                if (dwtitle.size() >= 1) {
-                    int y = Integer.parseInt(dwtitle.attr("trindex"));
-                    if (y <= 10) {
-                        reData.put(dwtitle.attr("keyName"), contractInfo.getConstructionUnitName());
-                    }
+            // 解析
+            // 模糊匹配
+            Elements dwtitle = doc.select("el-input[placeholder~=.*承包单位]");
+            Elements sgtitle = doc.select("el-input[placeholder~=^施工单位]");
+            Elements sgtitle1 = doc.select("el-input[placeholder=安装单位]");
+            sgtitle.addAll(sgtitle1);
+
+            //合同段显示合同编号
+            Elements htdtitle = doc.select("el-input[placeholder~=.*合同段.*]");
+            //合同名称显示合同名称
+            Elements htdtitle1 = doc.select("el-input[placeholder~=合同名称.*]");
+//            htdtitle.addAll(htdtitle1);
+
+            Elements jltitle = doc.select("el-input[placeholder~=监理单位.*]");
+
+            //编号为父节点划分编号
+            Elements bhtitle = doc.select("el-input[placeholder~=^编号]");
+            //合同编号为合同编号
+            Elements bhtitle1 = doc.select("el-input[placeholder~=合同编号.*]");
+            bhtitle1.addAll(htdtitle);
+
+            Elements xmtitle = doc.select("el-input[placeholder~=^项目名称]");
+
+
+            // Elements title = doc.select("el-input[placeholder~=^编号]");
+
+            /**
+             * 承包单位 承包单位、施工单位:引用施工单位名称 ,
+             * 监理单位:引用监理单位名称
+             * 合同段、所属建设项目(合同段):引用合同段编号
+             *
+             * 施工单位:施工单位 和 安装单位
+             *
+             */
+            ContractInfo contractInfo = contractInfoService.getById(wbsTreeContract.getContractId());
+            // 施工单位名称
+            if (dwtitle.size() >= 1) {
+                int y = Integer.parseInt(dwtitle.attr("trindex"));
+                if (y <= 10) {
+                    reData.put(dwtitle.attr("keyName"), contractInfo.getConstructionUnitName());
+                }
 
+            }
+            if (sgtitle.size() >= 1) {
+                int y = Integer.parseInt(sgtitle.attr("trindex"));
+                if (y <= 10) {
+                    reData.put(sgtitle.attr("keyName"), contractInfo.getConstructionUnitName());
                 }
-                if (sgtitle.size() >= 1) {
-                    int y = Integer.parseInt(sgtitle.attr("trindex"));
-                    if (y <= 10) {
-                        reData.put(sgtitle.attr("keyName"), contractInfo.getConstructionUnitName());
+            }
+
+            // 合同段名称
+            if (htdtitle1.size() >= 1) {
+                for (Element element : htdtitle1) {
+                    int trindex = Integer.parseInt(element.attr("trindex"));
+                    if (trindex <= 8) {
+                        reData.put(element.attr("keyName"), contractInfo.getContractName());
                     }
                 }
+            }
+            // 监理单位名称
+            if (jltitle.size() >= 1) {
 
-                // 合同段名称
-                if (htdtitle.size() >= 1) {
-                    for (Element element : htdtitle) {
-                        int trindex = Integer.parseInt(element.attr("trindex"));
-                        if (trindex <= 8) {
-                            reData.put(element.attr("keyName"), contractInfo.getContractNumber());
-                        }
+                for (Element element : jltitle) {
+                    int trindex = Integer.parseInt(element.attr("trindex"));
+                    if (trindex <= 10) {
+                        reData.put(element.attr("keyName"), contractInfo.getSupervisionUnitName());
                     }
                 }
-                // 监理单位名称
-                if (jltitle.size() >= 1) {
-
-                    for (Element element : jltitle) {
-                        int trindex = Integer.parseInt(element.attr("trindex"));
-                        if (trindex <= 10) {
-                            reData.put(element.attr("keyName"), contractInfo.getSupervisionUnitName());
-                        }
+            }
+            //获取父节点划分编号
+            WbsTreeContract node = wbsTreeContractService.getBaseMapper().selectOne(Wrappers.<WbsTreeContract>query().lambda()
+                    .eq(WbsTreeContract::getId, wbsTreeContract.getParentId())
+                    .eq(WbsTreeContract::getContractId, wbsTreeContract.getContractId()));
+            // 编号
+            if (bhtitle.size() >= 1 && contractInfo.getIsReferenceNumber() == 1) {
+                for (Element element : bhtitle) {
+                    int trindex = Integer.parseInt(element.attr("trindex"));
+                    if (trindex <= 10) {
+                        reData.put(element.attr("keyName"), node.getPartitionCode() == null ? "" : node.getPartitionCode());
                     }
                 }
-                //获取父节点划分编号
-                WbsTreeContract node = wbsTreeContractService.getBaseMapper().selectOne(Wrappers.<WbsTreeContract>query().lambda()
-                        .eq(WbsTreeContract::getId, wbsTreeContract.getParentId())
-                        .eq(WbsTreeContract::getContractId, wbsTreeContract.getContractId()));
-                // 编号
-                if (bhtitle.size() >= 1 && contractInfo.getIsReferenceNumber() == 1) {
-                    for (Element element : bhtitle) {
-                        int trindex = Integer.parseInt(element.attr("trindex"));
-                        if (trindex <= 10) {
-                            reData.put(element.attr("keyName"), node.getPartitionCode() == null ? "" : node.getPartitionCode());
-                        }
+            }
+            //获取合同编号
+            if (bhtitle1.size() >= 1) {
+                for (Element element : bhtitle1) {
+                    int trindex = Integer.parseInt(element.attr("trindex"));
+                    if (trindex <= 10) {
+                        reData.put(element.attr("keyName"), contractInfo.getContractNumber());
                     }
                 }
+            }
 
-                // 项目名称
-                if (xmtitle.size() >= 1) {
-                    for (Element element : xmtitle) {
-                        int trindex = Integer.parseInt(element.attr("trindex"));
-                        if (trindex <= 6) {
-                            ProjectInfo projectInfo = projectInfoService.getById(wbsTreeContract.getProjectId());
-                            reData.put(element.attr("keyName"), projectInfo.getProjectName());
-                        }
+            // 项目名称
+            if (xmtitle.size() >= 1) {
+                for (Element element : xmtitle) {
+                    int trindex = Integer.parseInt(element.attr("trindex"));
+                    if (trindex <= 6) {
+                        ProjectInfo projectInfo = projectInfoService.getById(wbsTreeContract.getProjectId());
+                        reData.put(element.attr("keyName"), projectInfo.getProjectName());
                     }
                 }
             }
         } catch (FileNotFoundException e) {
             e.printStackTrace();
+        } catch (Exception e) {
+            e.printStackTrace();
         }
 
         if (dataIn != null && dataIn.size() >= 1) {
@@ -1308,7 +1321,6 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
 
         //获取清表信息
         ExcelTab excelTab = this.getById(wbsTreeContract.getExcelId());
-
         if (excelTab == null) {
             return R.fail("失败");
         }
@@ -1365,6 +1377,9 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
             }
         }
 
+        if(pkeyId == 1644218999589830668L){
+          //  System.out.println("12321");
+        }
         //数据不为空
         if (StringUtils.isNotEmpty(wbsTreeContract.getHtmlUrl())) {
             InputStream inputStreamByUrl = FileUtils.getInputStreamByUrl(wbsTreeContract.getHtmlUrl());
@@ -1377,114 +1392,122 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
 
             if (ObjectUtil.isNotEmpty(DataInfo)) {
                 for (String val : DataInfo.keySet()) {
-                    if (val.indexOf("__") >= 0) {
-                        String[] DataVal = val.split("__");
-                        String[] xy = DataVal[1].split("_");
-                        if (Integer.parseInt(xy[0]) < trs.size()) {
-                            Element ytzData = trs.get(Integer.parseInt(xy[0]));
-                            if (ytzData != null) {
-                                Elements tdsx = ytzData.select("td");
-                                if (Integer.parseInt(xy[1]) < tdsx.size()) {
-                                    Element data = ytzData.select("td").get(Integer.parseInt(xy[1]));
-                                    if (data != null) {
-                                        if (data.html().indexOf("x1") >= 0 && data.html().indexOf("y1") >= 0) {
-                                            int x1 = 0;
-                                            int x2 = 0;
-                                            int y1 = 0;
-                                            int y2 = 0;
-
-                                            if (data.html().indexOf("el-tooltip") >= 0) {
-                                                x1 = Integer.parseInt(data.children().get(0).children().get(0).attr("x1"));
-                                                x2 = Integer.parseInt(data.children().get(0).children().get(0).attr("x2"));
-                                                y1 = Integer.parseInt(data.children().get(0).children().get(0).attr("y1"));
-                                            } else {
-                                                x1 = Integer.parseInt(data.children().get(0).attr("x1"));
-                                                y1 = Integer.parseInt(data.children().get(0).attr("y1"));
-                                            }
-                                            if (x1 == 0) {
-                                                x1 = 1;
-                                            }
-                                            String myData = DataInfo.get(val) + "";
-                                            if ((myData.indexOf("T") >= 0 && myData.indexOf("-") >= 0) || (myData.indexOf(",") >= 0 && myData.indexOf("]") >= 0)) {
-                                                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
-                                                sdf.setTimeZone(TimeZone.getTimeZone("GTM+8"));
-                                                SimpleDateFormat formatStr = new SimpleDateFormat("yyyy年MM月dd日");
-                                                if (myData.indexOf(",") >= 0 && myData.indexOf("]") >= 0) {
-
-                                                    myData = myData.replace("[", "").replace("]", "").replaceAll("'", "");
-                                                    String[] dataVal = myData.split(",");
-
-                                                    Date Start_dataStr = sdf.parse(dataVal[0]);
-                                                    Date end_dataStr = sdf.parse(dataVal[1]);
-                                                    String StartDate = formatStr.format(Start_dataStr);
-                                                    String endDate = formatStr.format(end_dataStr);
-                                                    if (StartDate.equals(endDate)) {
-                                                        myData = StartDate;
-                                                    } else {
-                                                        myData = StartDate + "-" + endDate;
-                                                    }
-                                                } else {
-                                                    String[] dataStr = myData.split("T")[0].split("-");
-                                                    if (dataStr.length == 3) {
-                                                        myData = StringUtil.format("{}年{}月{}日", dataStr[0], dataStr[1], Integer.parseInt(dataStr[2]));
-                                                    }
-                                                }
-                                            }
+                    Elements datas = doc.getElementsByAttributeValue("keyname", val);
+                    Element data = null;
+                    if(val.equals("key_12__25_0")){
+                        //System.out.println("1231");
+                    }
+                    if (datas.size() >= 1) {
+                        data = datas.get(0);
+                    }
 
-                                            if (myData.indexOf("lang.String") >= 0) {
-                                                Object obj = DataInfo.get(val);
-                                                if (obj instanceof String[]) {
-                                                    String[] dataDate = (String[]) obj;
-                                                    myData = dataDate[0] + "-" + dataDate[1].trim();
-                                                }
-                                            }
+                    if (data != null) {
+                        if (data.hasAttr("x1") && data.hasAttr("y1")) {
+                            int x1 = 0;
+                            int x2 = 0;
+                            int y1 = 0;
+                            int y2 = 0;
 
-                                            //https:bladex-test-info.oss-cn-chengdu.aliyuncs.com//upload/20220819/b53cb6700db369381e3b03d7737bcdec.jpg__16_1
-                                            if ((myData.indexOf("https") >= 0 || myData.indexOf("http") >= 0) && myData.indexOf("aliyuncs") >= 0) {
-
-                                                InputStream imageIn = CommonUtil.getOSSInputStream(myData);
-                                                byte[] byteNew = IOUtils.toByteArray(imageIn);
-                                                byte[] bytes = CommonUtil.compressImage(byteNew);
-                                                // 这里根据实际需求选择图片类型
-                                                int pictureIdx = workbook.addPicture(bytes, 6);
-                                                CreationHelper helper = workbook.getCreationHelper();
-                                                ClientAnchor anchor = helper.createClientAnchor();
-                                                anchor.setCol1(x1); // param1是列号
-                                                anchor.setCol2(x2);
-                                                anchor.setRow1(y1); // param2是行号
-                                                anchor.setRow2(y2); // param2是行号
-                                                //
-                                                Drawing drawing = sheet.createDrawingPatriarch();
-                                                anchor.setAnchorType(ClientAnchor.AnchorType.MOVE_AND_RESIZE);
-                                                // 插入图片
-                                                Picture pict = drawing.createPicture(anchor, pictureIdx); // 调整图片占单元格百分比的大小,1.0就是100%
-                                                pict.resize(1, 1);
-                                                FileUtils.imageOrientation(sheet, anchor, new DataVO(x1 - 1, y1 - 1));
-
-                                            } else if (myData.equals("1") && data.html().indexOf("hc-form-checkbox-group") >= 0) {
-                                                Row row = sheet.getRow(y1 - 1);
-                                                if (row != null) {
-                                                    Cell cell = row.getCell(x1 - 1);
-                                                    if (cell != null || ObjectUtils.isNotEmpty(cell)) {
-                                                        String exceVal = cell.getStringCellValue().replaceAll(" ", "");
-                                                        short fontIndex = cell.getCellStyle().getFontIndex();
-                                                        Font fontAt = workbook.getFontAt(fontIndex);
-                                                        fontAt.setFontName("EUDC");
-                                                        cell.setCellValue(exceVal.replace("□", "\u2611"));
-                                                    }
-                                                }
-                                            } else {
-                                                Row row = sheet.getRow(y1 - 1);
-                                                if (row != null) {
-                                                    Cell cell = row.getCell(x1 - 1);
-                                                    if (cell != null || ObjectUtils.isNotEmpty(cell)) {
-                                                        cell.setCellValue(myData);
-                                                    }
+                            x1 = Integer.parseInt(data.attr("x1"));
+                            y1 = Integer.parseInt(data.attr("y1"));
+
+                            if (x1 == 0) {
+                                x1 = 1;
+                            }
+
+                            String myData = DataInfo.get(val) + "";
+                            if ((myData.indexOf("T") >= 0 && myData.indexOf("-") >= 0) || (myData.indexOf(",") >= 0 && myData.indexOf("]") >= 0)) {
+                                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
+                                sdf.setTimeZone(TimeZone.getTimeZone("GTM+8"));
+                                SimpleDateFormat formatStr = new SimpleDateFormat("yyyy年MM月dd日");
+                                if (myData.indexOf(",") >= 0 && myData.indexOf("]") >= 0) {
+
+                                    myData = myData.replace("[", "").replace("]", "").replaceAll("'", "");
+                                    String[] dataVal = myData.split(",");
+
+                                    Date Start_dataStr = sdf.parse(dataVal[0]);
+                                    Date end_dataStr = sdf.parse(dataVal[1]);
+                                    String StartDate = formatStr.format(Start_dataStr);
+                                    String endDate = formatStr.format(end_dataStr);
+                                    if (StartDate.equals(endDate)) {
+                                        myData = StartDate;
+                                    } else {
+                                        myData = StartDate + "-" + endDate;
+                                    }
+                                } else {
+                                    String[] dataStr = myData.split("T")[0].split("-");
+                                    if (dataStr.length == 3) {
+                                        myData = StringUtil.format("{}年{}月{}日", dataStr[0], dataStr[1], Integer.parseInt(dataStr[2]));
+                                    }
+                                }
+                            }
+
+                            if (myData.indexOf("lang.String") >= 0) {
+                                Object obj = DataInfo.get(val);
+                                if (obj instanceof String[]) {
+                                    String[] dataDate = (String[]) obj;
+                                    myData = dataDate[0] + "-" + dataDate[1].trim();
+                                }
+                            }
+
+                            //https:bladex-test-info.oss-cn-chengdu.aliyuncs.com//upload/20220819/b53cb6700db369381e3b03d7737bcdec.jpg__16_1
+                            if ((myData.indexOf("https") >= 0 || myData.indexOf("http") >= 0) && myData.indexOf("aliyuncs") >= 0) {
+
+                                InputStream imageIn = CommonUtil.getOSSInputStream(myData);
+                                byte[] byteNew = IOUtils.toByteArray(imageIn);
+                                byte[] bytes = CommonUtil.compressImage(byteNew);
+                                // 这里根据实际需求选择图片类型
+                                int pictureIdx = workbook.addPicture(bytes, 6);
+                                CreationHelper helper = workbook.getCreationHelper();
+                                ClientAnchor anchor = helper.createClientAnchor();
+                                anchor.setCol1(x1); // param1是列号
+                                anchor.setCol2(x2);
+                                anchor.setRow1(y1); // param2是行号
+                                anchor.setRow2(y2); // param2是行号
+                                //
+                                Drawing drawing = sheet.createDrawingPatriarch();
+                                anchor.setAnchorType(ClientAnchor.AnchorType.MOVE_AND_RESIZE);
+                                // 插入图片
+                                Picture pict = drawing.createPicture(anchor, pictureIdx); // 调整图片占单元格百分比的大小,1.0就是100%
+                                pict.resize(1, 1);
+                                FileUtils.imageOrientation(sheet, anchor, new DataVO(x1 - 1, y1 - 1));
+
+                            } else if (data.tagName().equals("hc-form-checkbox-group")) {
+                                Row row = sheet.getRow(y1 - 1);
+                                if (row != null) {
+                                    Cell cell = row.getCell(x1 - 1);
+                                    if (cell != null || ObjectUtils.isNotEmpty(cell)) {
+                                        String exceVal = cell.getStringCellValue().replaceAll(" ", "");
+                                        //如果有□ 代表 自动生成  如果没有 代表后期添加 需要显示html 中的值
+                                        if(exceVal.indexOf("□")>=0 ){
+                                            if(myData.equals("1")){
+                                                short fontIndex = cell.getCellStyle().getFontIndex();
+                                                Font fontAt = workbook.getFontAt(fontIndex);
+                                                fontAt.setFontName("EUDC");
+                                                cell.setCellValue(exceVal.replace("□", "\u2611"));
+                                            }
+                                        }else{
+                                            String dataJson = data.attr(":objs");
+                                            if(StringUtils.isNotEmpty(dataJson)){
+                                                JSONArray jsonArray = JSONArray.parseArray(dataJson);
+                                                List<Integer> idList = Func.toIntList(myData);
+                                                String dataInfo = jsonArray.getJSONObject(0).getString("name");
+                                                for(int inx=1 ; inx<idList.size() ; inx++){
+                                                    dataInfo = dataInfo+","+jsonArray.getJSONObject(inx).getString("name");
                                                 }
+                                                cell.setCellValue(dataInfo);
                                             }
                                         }
                                     }
                                 }
+                            } else {
+                                Row row = sheet.getRow(y1 - 1);
+                                if (row != null) {
+                                    Cell cell = row.getCell(x1 - 1);
+                                    if (cell != null || ObjectUtils.isNotEmpty(cell)) {
+                                        cell.setCellValue(myData);
+                                    }
+                                }
                             }
                         }
                     }
@@ -1508,6 +1531,7 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
                             Elements tdsx = ytzData.select("td");
                             if (Integer.parseInt(trtd[1]) < tdsx.size()) {
                                 Element data = ytzData.select("td").get(Integer.parseInt(trtd[1]));
+
                                 if (data.html().indexOf("el-tooltip") >= 0) {
                                     data = data.children().get(0);
                                 }
@@ -1548,6 +1572,7 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
         FileOutputStream outputStream = new FileOutputStream(excelPath);
         workbook.write(outputStream);
         FileUtils.setExcelScaleToPdf(excelPath, pdfPath);
+
         BladeFile bladeFile = newIOSSClient.uploadFile(pkeyId + ".pdf", pdfPath);
 
         //附件
@@ -1594,8 +1619,8 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
         if (exceInp != null) {
             IoUtil.closeQuietly(exceInp);
         }
+         return R.data(bladeFile2.getLink());
 
-        return R.data(bladeFile2.getLink());
     }
 
     @Override
@@ -1966,38 +1991,39 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
         reData.remove("contractId");
         reData.remove("pkeyId");
         reData.remove("projectId");
-        chart(reData,wbsTreePrivate);
+        chart(reData, wbsTreePrivate);
         list.add(reData);
         return list;
     }
-    private void  chart(Map<String,Object> reData,WbsTreePrivate wtp){
+
+    private void chart(Map<String, Object> reData, WbsTreePrivate wtp) {
         try {
-            if(reData.size()>0&&wtp!=null) {
+            if (reData.size() > 0 && wtp != null) {
                 List<Map<String, Object>> configList = this.jdbcTemplate.queryForList("select d.rely ,b.e_key ekey from m_wbs_tree_private a join  m_wbs_form_element b on a.init_table_id=b.f_id join m_element_formula_mapping c on b.id=c.element_id join m_formula d on c.formula_id=d.id  where p_key_id=" + wtp.getPKeyId() + " and b.is_deleted=0 and d.formula like 'FC.chart%' limit 1");
                 if (Func.isNotEmpty(configList)) {
                     Map<String, Object> config = configList.get(0);
                     String[] rely = Func.toStr(config.get("rely")).split(",");
                     String ky = rely[0].split(":")[1];
                     String kx = rely[1].split(":")[1];
-                    Map<String,String> coordsMap = FormulaUtils.getElementCell(wtp.getHtmlUrl());
-                    List<String> ly= Arrays.stream((coordsMap.get(ky)).split(";")).filter(Func::isNotBlank).map(k->ky+"__"+k).collect(Collectors.toList());
-                    List<String> lx= Arrays.stream((coordsMap.get(kx)).split(";")).filter(Func::isNotBlank).map(k->kx+"__"+k).collect(Collectors.toList());
-                    List<String> fct= new ArrayList<>();
-                    if(ly.size()>0){
+                    Map<String, String> coordsMap = FormulaUtils.getElementCell(wtp.getHtmlUrl());
+                    List<String> ly = Arrays.stream((coordsMap.get(ky)).split(";")).filter(Func::isNotBlank).map(k -> ky + "__" + k).collect(Collectors.toList());
+                    List<String> lx = Arrays.stream((coordsMap.get(kx)).split(";")).filter(Func::isNotBlank).map(k -> kx + "__" + k).collect(Collectors.toList());
+                    List<String> fct = new ArrayList<>();
+                    if (ly.size() > 0) {
                         fct.addAll(ly);
                     }
-                    if(lx.size()>0){
+                    if (lx.size() > 0) {
                         fct.addAll(lx);
                     }
-                    String formChartKey= String.join(",", fct);
-                    if(Func.isNotEmpty(formChartKey)){
-                        reData.put("formChartKey",formChartKey);
-                        String key=Func.toStr(config.get("ekey"));
-                        reData.put("formchartKeyShow",key+"__"+coordsMap.get(key).split(";")[0]);
+                    String formChartKey = String.join(",", fct);
+                    if (Func.isNotEmpty(formChartKey)) {
+                        reData.put("formChartKey", formChartKey);
+                        String key = Func.toStr(config.get("ekey"));
+                        reData.put("formchartKeyShow", key + "__" + coordsMap.get(key).split(";")[0]);
                     }
                 }
             }
-        }catch (Exception e){
+        } catch (Exception e) {
             e.printStackTrace();
         }
     }

+ 40 - 11
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/FormulaServiceImpl.java

@@ -351,7 +351,7 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
             Map<String, Object> elementInfoMap=this.getElementInfoByCodes(String.join(",",missingList));
             /*1从当前节点其它表格中查找匹配的元素*/
             List<String> removeList=new ArrayList<>();
-            if(false) {/*全加载后,关闭当前节的搜索,假如后期改成依赖加载可以再次利用*/
+            /*if(false) {*//*全加载后,关闭当前节的搜索,假如后期改成依赖加载可以再次利用*//*
                 for (String r : missingList) {
                     String tn = r.substring(0, r.indexOf(StringPool.COLON));
                     String key = r.substring(r.indexOf(StringPool.COLON) + 1);
@@ -369,10 +369,10 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
                     }
                 }
                 if (Func.isNotEmpty(removeList)) {
-                    /*移除已经找到的元素数据*/
+                    *//*移除已经找到的元素数据*//*
                     missingList.removeIf(removeList::contains);
                 }
-            }
+            }*/
             if(Func.isNotEmpty(missingList)){
                 /*2从当前节点的兄弟节点中查找匹配的元素*/
                 CurrentNode currentNode = this.tec.getCurrentNode();
@@ -504,23 +504,45 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
         }
         this.tec.getLog().append("【本节点参数情况:").append(result.entrySet().stream().map(p->logMap.get(p.getKey())+":"+p.getValue()).collect(Collectors.joining(";"))).append("】");
         /*元素动态绑定*/
-        tec.formDataMap.values().stream().filter(e->e.getIsCurrentNodeElement()&&e.getFormula()==null).forEach(e->{
-            /*执行列表里不存在,且元素的名称和节点参数名称匹配成功*/
+        Map<String,Formula> formulaIdMap = this.wpService.formulaKeyMap(total.stream().map(WbsParam::getK).collect(Collectors.toList()));
+        /**查找无绑定公式且单元格只有一个的当前表单元素*/
+        List<FormData> notFormulaFds=tec.formDataMap.values().stream().filter(e->e.getIsCurrentNodeElement()&&e.getFormula()==null&&e.getCoordsList().size()==1).collect(Collectors.toList());
+        if(notFormulaFds.size()>0){
+            notFormulaFds.forEach(e->{
+                /*执行列表里不存在,且元素的名称和节点参数名称匹配成功,暂时用参数名称是否包含元素名称作为匹配规则*/
+                total.stream().filter(p->e.getEName().contains(p.getName().replaceAll("【[\\u4E00-\\u9FFF]+】|\\s+",""))&&!tec.formDataList.contains(e)).findAny().ifPresent(d->{
+                    Formula tf= formulaIdMap.get(d.getK());
+                    if(tf!=null&&e.getId()!=null) {
+                        e.setFormula(tf);
+                        tec.formDataList.add(e);
+                        ElementFormulaMapping efm = new ElementFormulaMapping();
+                        efm.setScope(FormulaBean.PARAM);
+                        efm.setParamId(d.getId());
+                        efm.setElementId(e.getId());
+                        efm.setFormulaId(tf.getId());
+                        this.elementFormulaMappingService.save(efm);
+                    }
+                });
+            });
+        }
+    /*    tec.formDataMap.values().stream().filter(e->e.getIsCurrentNodeElement()&&e.getFormula()==null).forEach(e->{
+            *//*执行列表里不存在,且元素的名称和节点参数名称匹配成功*//*
             total.stream().filter(p->e.getEName().contains(p.getName().replace("【水】","").trim())&&!tec.formDataList.contains(e)).findAny().ifPresent(d->{
                 Formula  formula=new Formula();
                 formula.setOutm(Formula.FULL);
-                if(RegexUtil.match(ParamElements.LEVEL_REG,d.getV().trim())){
-                    /*取层级*/
+             *//*   if(RegexUtil.match(ParamElements.LEVEL_REG,d.getV().trim())){
+                    *//**//*取层级*//**//*
                     formula.setFormula("FC.tree(trees,WP["+d.getK()+"])");
                 }else{
-                    /*直接取数*/
+                    *//**//*直接取数*//**//*
                     formula.setFormula("WP["+d.getK()+"]");
-                }
+                }*//*
+                formula.setFormula("FC.tree(trees,WP["+d.getK()+"])");
                 e.setFormula(formula);
                 tec.getLog().append("动态绑定参数:").append(e.getEName()).append(";");
                 tec.formDataList.add(e);
             });
-        });
+        });*/
         return result;
     }
 
@@ -884,6 +906,10 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
                             String values=subTableInfo.stream().map(TableInfo::getDataMap).map(m->m.get(StringUtils.handleNull(e.get("ekey")))).filter(StringUtils::isNotEmpty).collect(Collectors.joining(";;"));
                             FormData tmp=  createFormDataFast(StringUtils.handleNull(e.get("ename")),StringUtils.handleNull(e.get("code")),values);
                             if(tmp!=null){
+                                String idStr =StringUtils.handleNull(e.get("fieldId"));
+                                if(Func.isNotEmpty(idStr)) {
+                                    tmp.setId(Func.toLong(idStr));
+                                }
                                 tmp.setIsCurrentNodeElement(true);
                                 tec.formDataMap.put(tmp.getCode(),tmp);
                                 tec.formDataList.add(tmp);
@@ -1345,7 +1371,10 @@ public  List<ElementData> setScale(Integer scale,List<ElementData> data){
         List<Object> result = new ArrayList<>();
         try {
             pretreatment(local,formula);
-            List<Object>  r= local.stream().map(e-> Expression.parse(e.getFormula()).calculate(e.getCurrentMap())).collect(Collectors.toList());
+            List<Object>  r= local.stream().map(e-> {
+                /*所有依赖元素的内容必须非空才进行计算,否则返回空值*/
+                return e.hasEmptyElementValue()?"": Expression.parse(e.getFormula()).calculate(e.getCurrentMap());
+            }).collect(Collectors.toList());
             if(CollectionUtil.isNotEmpty(r)&&r.stream().anyMatch(StringUtils::isNotEmpty)){
                 result.addAll(r);
             }

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

@@ -21,6 +21,7 @@ import org.springblade.manager.mapper.TableInfoMapper;
 import org.springblade.manager.mapper.WbsFormElementMapper;
 import org.springblade.manager.mapper.WbsTreeMapper;
 import org.springblade.manager.mapper.WbsTreePrivateMapper;
+import org.springblade.manager.service.IExcelTabService;
 import org.springblade.manager.service.ITableInfoService;
 import org.springblade.manager.service.IWbsFormElementService;
 import org.springblade.manager.utils.WbsElementUtil;
@@ -51,6 +52,8 @@ public class WbsFormElementServiceImpl extends BaseServiceImpl<WbsFormElementMap
 
     private final ITableInfoService tableInfoService;
 
+    private final IExcelTabService excelTabService;
+
     //元素字符串、数值、时间类型默认长度
     public static final Integer DEFAULT_ELEMENT_LENGTH_VARCHAR = 250;
     public static final Integer DEFAULT_ELEMENT_LENGTH_NUMBER = 50;
@@ -754,6 +757,12 @@ public class WbsFormElementServiceImpl extends BaseServiceImpl<WbsFormElementMap
                         if (formElementDTO.getSubmitStatus() == 2) {
                             baseMapper.insertWbsTabRelationExcelTab(SnowFlakeUtil.getId(), formElementDTO.getExcelTabId(), formElementDTO.getId());
                         }
+
+                        // 绑定excel 与实体表的关系
+                        excelTabService.update(Wrappers.<ExcelTab>lambdaUpdate()
+                                .set(ExcelTab::getTabId, formElementDTO.getInitTableId())
+                                .eq(ExcelTab::getId, formElementDTO.getExcelTabId())
+                        );
                     }
                 } catch (Exception e) {
                     //删除元素表

+ 42 - 4
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsParamServiceImpl.java

@@ -7,14 +7,12 @@ 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.BaseEntity;
 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;
-import org.springblade.manager.entity.ContractInfo;
-import org.springblade.manager.entity.WbsParam;
-import org.springblade.manager.entity.WbsTreeContract;
-import org.springblade.manager.entity.WbsTreePrivate;
+import org.springblade.manager.entity.*;
 import org.springblade.manager.mapper.WbsParamMapper;
 import org.springblade.manager.service.IElementFormulaMappingService;
 import org.springblade.manager.service.IFormulaService;
@@ -218,6 +216,46 @@ public class WbsParamServiceImpl extends BaseServiceImpl<WbsParamMapper, WbsPara
     }
 
 
+    /**
+     * @Description 获取公式和key 的字典,复用共key公式
+     * @Param [ks]
+     * @return java.util.Map<java.lang.String,java.lang.String>
+     * @Author yangyj
+     * @Date 2023.07.27 10:30
+     **/
+    @Override
+    public Map<String,Long> formulaIdKeyMap(List<String> ks){
+        Map<String,Long> fkMap=new HashMap<>();
+        if(Func.isNotEmpty(ks)) {
+            List<Map<String, Object>> formulaIdAndKmaps = this.jdbcTemplate.queryForList("select a.id,b.k from m_formula a join m_wbs_param b on a.param_id=b.id where b.k in (" + ks.stream().filter(Func::isNotBlank).distinct().collect(Collectors.joining("','", "'", "'")) + ") AND b.type=0");
+            if(Func.isNotEmpty(formulaIdAndKmaps)) {
+                fkMap = formulaIdAndKmaps.stream().collect(Collectors.toMap(m -> m.get("k").toString(), m -> Long.parseLong(m.get("id").toString()), (p, n) -> n));
+            }
+        }
+        return fkMap;
+    }
+    @Override
+    public Long formulaId(String k){
+        if(Func.isNotBlank(k)) {
+            Map<String, Long> fkMap = formulaIdKeyMap(Collections.singletonList(k));
+            return fkMap.get(k);
+        }
+        return null;
+    }
+
+    @Override
+    public Map<String, Formula> formulaKeyMap(List<String> ks) {
+        Map<String,Formula> result = new HashMap<>();
+        Map<String,Long> fkMap= formulaIdKeyMap(ks);
+        if(fkMap.size()>0) {
+           List<Formula> list =  this.formulaService.listByIds(fkMap.values());
+           Map<Long,Formula> idMap=list.stream().collect(Collectors.toMap(BaseEntity::getId, f->f));
+           fkMap.forEach((k,v)->{
+               result.put(k,idMap.get(v));
+           });
+        }
+        return result;
+    }
 }
 
 

+ 159 - 122
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreeContractServiceImpl.java

@@ -10,7 +10,6 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.google.common.collect.Lists;
 import lombok.AllArgsConstructor;
 import org.apache.commons.lang.StringUtils;
-import org.jetbrains.annotations.NotNull;
 import org.jsoup.Jsoup;
 import org.jsoup.nodes.Document;
 import org.jsoup.nodes.Element;
@@ -42,9 +41,7 @@ import org.springblade.manager.service.IWbsTreeContractService;
 import org.springblade.manager.vo.*;
 import org.springblade.system.cache.ParamCache;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.dao.DataAccessException;
 import org.springframework.data.redis.core.StringRedisTemplate;
-import org.springframework.jdbc.core.BatchPreparedStatementSetter;
 import org.springframework.jdbc.core.BeanPropertyRowMapper;
 import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.stereotype.Service;
@@ -57,9 +54,6 @@ import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.math.BigInteger;
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.SQLException;
 import java.util.*;
 import java.util.function.Function;
 import java.util.regex.Matcher;
@@ -109,108 +103,154 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
     public boolean submitWbsTreeInContract(WbsTreeContractDTO pawDTO) {
         String wbsTreeIds = pawDTO.getWbsTreeIds();
         String[] ids = wbsTreeIds.split(",");
+        //项目对应到合同段的入参节点ids
         List<String> idList = Arrays.asList(ids);
         List<String> idList1 = idList.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
 
-        //获取当前合同段所有节点、表单(不包括客户端新增或者复制节点)
-        List<WbsTreeContract> list = baseMapper.selectList(Wrappers.<WbsTreeContract>lambdaQuery()
-                .select(WbsTreeContract::getId, WbsTreeContract::getType, WbsTreeContract::getParentId)
+        //获取当前合同段所有节点、表单(不包括客户端新增或者复制节点)
+        List<WbsTreeContract> nowContractNodeAndTabAll = baseMapper.selectList(Wrappers.<WbsTreeContract>lambdaQuery()
+                .select(WbsTreeContract::getId, WbsTreeContract::getType)
                 .eq(WbsTreeContract::getContractId, pawDTO.getContractId())
                 .eq(WbsTreeContract::getWbsId, pawDTO.getWbsId())
                 .eq(WbsTreeContract::getStatus, 1)
                 .isNull(WbsTreeContract::getOldId));
 
         //当前合同段所有表单ids
-        List<String> collect1 = new ArrayList<>();
+        List<String> nowContractTabIds = new ArrayList<>();
         //当前合同段所有节点ids
-        List<String> collect2 = new ArrayList<>();
-        if (list.size() > 0) {
-            collect1 = list.stream().filter(f -> f.getType() == 2).collect(Collectors.toList()).stream().map(WbsTreeContract::getId).map(String::valueOf).collect(Collectors.toList());
-            collect2 = list.stream().filter(f -> f.getType() == 1).collect(Collectors.toList()).stream().map(WbsTreeContract::getId).map(String::valueOf).collect(Collectors.toList());
+        List<String> nowContractNodeIds = new ArrayList<>();
+        if (nowContractNodeAndTabAll.size() > 0) {
+            nowContractTabIds = nowContractNodeAndTabAll.stream().filter(f -> f.getType() == 2).collect(Collectors.toList()).stream().map(WbsTreeContract::getId).map(String::valueOf).collect(Collectors.toList());
+            nowContractNodeIds = nowContractNodeAndTabAll.stream().filter(f -> f.getType() == 1).collect(Collectors.toList()).stream().map(WbsTreeContract::getId).map(String::valueOf).collect(Collectors.toList());
         }
 
-        List<String> collect3 = collect2;
-        List<String> saveIds = idList1.stream().filter(f -> !collect3.contains(f)).collect(Collectors.toList());
-        List<String> delIds = collect3.stream().filter(f -> !idList1.contains(f)).collect(Collectors.toList());
+        List<String> finalNowContractNodeIds = nowContractNodeIds;
+        List<String> saveIds = idList1.stream().filter(f -> !finalNowContractNodeIds.contains(f)).collect(Collectors.toList());
+        List<String> delIds = finalNowContractNodeIds.stream().filter(f -> !idList1.contains(f)).collect(Collectors.toList());
 
         //TODO ---------节点未变只同步元素表---------
         if (saveIds.size() == 0 && delIds.size() == 0) {
-            List<WbsTreePrivate> wbsTreePrivateListResult = new ArrayList<>();
-            //当前项目所有表
-            List<WbsTreePrivate> wbsTreePrivateList = wbsTreePrivateMapper.selectList(Wrappers.<WbsTreePrivate>query().lambda()
-                    .eq(WbsTreePrivate::getProjectId, Long.parseLong(pawDTO.getProjectId()))
-                    .eq(WbsTreePrivate::getWbsId, Long.parseLong(pawDTO.getWbsId()))
+            //当前项目所有原始表(从公有树到项目私有树同步后的,或是私有到私有的)
+            List<WbsTreePrivate> nowProjectTabs = wbsTreePrivateMapper.selectList(Wrappers.<WbsTreePrivate>query().lambda()
+                    .select(WbsTreePrivate::getId, WbsTreePrivate::getParentId, WbsTreePrivate::getType)
+                    .eq(WbsTreePrivate::getProjectId, pawDTO.getProjectId())
+                    .eq(WbsTreePrivate::getWbsId, pawDTO.getWbsId())
                     .eq(WbsTreePrivate::getStatus, 1)
                     .eq(WbsTreePrivate::getType, 2)
             );
+            //判断当前的表是否有在合同段中有上级节点(不存在上级节点的表说明没有分配,不参与同步,根据入参的节点id与当前项目表的parentId判断)
+            List<String> saveSyncTabIds = nowProjectTabs.stream()
+                    .flatMap(wbsTreePrivate -> idList1.stream()
+                            .filter(id -> Long.parseLong(id) == (wbsTreePrivate.getParentId()) && wbsTreePrivate.getType() == 2)
+                            .map(id -> String.valueOf(wbsTreePrivate.getId())))
+                    .collect(Collectors.toList());
 
-            wbsTreePrivateList.forEach(wbsTreePrivate -> {
-                idList1.forEach(id -> {
-                    if (Long.parseLong(id) == (wbsTreePrivate.getParentId()) && wbsTreePrivate.getType() == 2) {
-                        wbsTreePrivateListResult.add(wbsTreePrivate);
-                    }
-                });
-            });
-
-            //当前项目节点下的所有表单Ids
-            List<String> collect = wbsTreePrivateListResult.stream().map(WbsTreePrivate::getId).distinct().map(String::valueOf).collect(Collectors.toList());
-
-            if (collect.size() == collect1.size()) {
+            //如果当前项目表与入参合同段的表一样数量,那么不需要同步
+            if (saveSyncTabIds.size() == nowContractTabIds.size()) {
                 return true;
             }
 
-            List<String> finalCollect = collect1;
-            Map<String, String> resultMapData = collect.stream().filter(f -> !finalCollect.contains(f)).collect(Collectors.toMap(Object::toString, Function.identity()));
+            //不同表(需要保存的表),根据当前合同段判断
+            List<String> finalCollect = nowContractTabIds;
+            List<String> saveTabIds = saveSyncTabIds.stream().filter(f -> !finalCollect.contains(f)).collect(Collectors.toList());
 
+            //构造结果集
             List<WbsTreeContract> wbsTreeContractResultData = new ArrayList<>();
-            wbsTreePrivateList.forEach(wbsTreePrivate -> {
-                String resultObj = resultMapData.get(wbsTreePrivate.getId() + "");
-                if (resultObj != null) {
-                    WbsTreeContract wbsTreeContract = BeanUtil.copyProperties(wbsTreePrivate, WbsTreeContract.class);
+            if (!saveTabIds.isEmpty()) {
+                //获取对应需要同步的表信息(项目级)
+                List<WbsTreePrivate> needSaveSyncProjectTabs = wbsTreePrivateMapper.selectList(Wrappers.<WbsTreePrivate>lambdaQuery()
+                        .in(WbsTreePrivate::getId, saveTabIds)
+                        .eq(WbsTreePrivate::getProjectId, pawDTO.getProjectId())
+                        .eq(WbsTreePrivate::getWbsId, pawDTO.getWbsId())
+                        .eq(WbsTreePrivate::getType, 2)
+                        .eq(WbsTreePrivate::getStatus, 1));
+                needSaveSyncProjectTabs.forEach(obj -> {
+                    WbsTreeContract wbsTreeContract = BeanUtil.copyProperties(obj, WbsTreeContract.class);
                     if (wbsTreeContract != null) {
                         wbsTreeContract.setPKeyId(SnowFlakeUtil.getId());
                         wbsTreeContract.setWbsId(pawDTO.getWbsId());
                         wbsTreeContract.setProjectId(pawDTO.getProjectId());
                         wbsTreeContract.setContractId(pawDTO.getContractId());
-                        wbsTreeContract.setIsTypePrivatePid(wbsTreePrivate.getPKeyId());
-                        if (wbsTreePrivate.getType() == 2) {
-                            wbsTreeContract.setIsTypePrivatePid(wbsTreePrivate.getPKeyId());
+                        wbsTreeContract.setIsTypePrivatePid(obj.getPKeyId());
+                        wbsTreeContract.setCreateTime(new Date());
+                        if (obj.getType() == 2) {
+                            wbsTreeContract.setIsTypePrivatePid(obj.getPKeyId());
                         }
                         wbsTreeContractResultData.add(wbsTreeContract);
                     }
-                }
-            });
+                });
+            }
 
-            //获取当前合同段的复制节点或者新增节点
-            List<WbsTreeContract> copyAndAddNodeList = baseMapper.selectList(Wrappers.<WbsTreeContract>lambdaQuery()
-                    .select(WbsTreeContract::getId, WbsTreeContract::getOldId)
-                    .eq(WbsTreeContract::getContractId, pawDTO.getContractId())
-                    .eq(WbsTreeContract::getWbsId, pawDTO.getWbsId())
-                    .eq(WbsTreeContract::getStatus, 1)
-                    .isNotNull(WbsTreeContract::getOldId));
-
-            List<WbsTreeContract> copyAddNodeTabs = new ArrayList<>();
-            if (copyAndAddNodeList.size() > 0) {
-                for (WbsTreeContract synTab : wbsTreeContractResultData) {
-                    for (WbsTreeContract copyAddNode : copyAndAddNodeList) {
-                        if (synTab.getParentId().toString().equals(copyAddNode.getOldId())) {
-                            WbsTreeContract copyAddNodeTab = BeanUtil.copyProperties(synTab, WbsTreeContract.class);
-                            if (copyAddNodeTab != null) {
-                                copyAddNodeTab.setParentId(copyAddNode.getId());
-                                copyAddNodeTab.setAncestors(synTab.getAncestors().replace(synTab.getParentId() + "", copyAddNodeTab.getParentId() + ""));
-                                copyAddNodeTab.setPKeyId(SnowFlakeUtil.getId());
-                                copyAddNodeTab.setCreateTime(new Date());
-                                copyAddNodeTabs.add(copyAddNodeTab);
+            if (wbsTreeContractResultData.size() > 0) {
+                //获取当前合同段的复制节点或者新增节点最底层节点(只有最底层节点存在元素表)
+                String sql = "SELECT a.id, a.old_id," +
+                        " (SELECT CASE WHEN COUNT(1) > 0 THEN 1 ELSE 0 END" +
+                        " FROM m_wbs_tree_contract b" +
+                        " WHERE b.parent_id = a.id" +
+                        " AND b.wbs_id = " + pawDTO.getWbsId() +
+                        " AND b.contract_id = " + pawDTO.getContractId() +
+                        " AND b.status = 1" +
+                        " AND b.type = 1" +
+                        " AND b.is_deleted = 0" +
+                        " ) AS hasChildren" +
+                        " FROM m_wbs_tree_contract a" +
+                        " WHERE " +
+                        " a.status = 1" +
+                        " AND a.is_deleted = 0" +
+                        " AND a.type = 1" +
+                        " AND a.wbs_id = " + pawDTO.getWbsId() +
+                        " AND a.contract_id = " + pawDTO.getContractId() +
+                        " AND a.old_id is not null" +
+                        " HAVING hasChildren = 0";
+                List<WbsTreeContract> copyAndAddNodeList = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(WbsTreeContract.class));
+
+                //新增复制节点对应的表结果集
+                List<WbsTreeContract> copyAddNodeTabsResult = new ArrayList<>();
+                if (copyAndAddNodeList.size() > 0) {
+                    //转换为Map,oldId作为Key,id作为Value
+                    Map<String, List<WbsTreeContract>> oldIdToIdMap = copyAndAddNodeList.stream().collect(Collectors.groupingBy(WbsTreeContract::getOldId));
+                    for (WbsTreeContract synTab : wbsTreeContractResultData) {
+                        //获取每张需要同步的表与之对应的新增或复制的节点
+                        List<WbsTreeContract> copyOrAddNodes = oldIdToIdMap.get(synTab.getParentId().toString());
+                        if (copyOrAddNodes != null && copyOrAddNodes.size() > 0) {
+                            for (WbsTreeContract node : copyOrAddNodes) {
+                                WbsTreeContract copyAddNodeTab = BeanUtil.copyProperties(synTab, WbsTreeContract.class);
+                                if (copyAddNodeTab != null) {
+                                    //把表同步到对应的节点下,重新构造ParentId、Ancestors、PKeyId
+                                    copyAddNodeTab.setParentId(node.getId());
+                                    copyAddNodeTab.setAncestors(synTab.getAncestors().replace(synTab.getParentId() + "", copyAddNodeTab.getParentId() + ""));
+                                    copyAddNodeTab.setPKeyId(SnowFlakeUtil.getId());
+                                    copyAddNodeTab.setOldId(synTab.getId() + "");
+                                    copyAddNodeTab.setCreateTime(new Date());
+                                    copyAddNodeTabsResult.add(copyAddNodeTab);
+                                }
                             }
                         }
                     }
                 }
-            }
+                if (copyAddNodeTabsResult.size() > 0) {
+                    wbsTreeContractResultData.addAll(copyAddNodeTabsResult);
+                }
 
-            if (wbsTreeContractResultData.size() > 0) {
-                if (copyAddNodeTabs.size() > 0) {
-                    //新增复制节点的表
-                    wbsTreeContractResultData.addAll(copyAddNodeTabs);
+                //去重,构造wbsTreeContractResultData列表中的唯一组合(id, parent_id, wbs_id, contract_id)
+                Set<String> uniqueCombinations = new HashSet<>();
+                for (WbsTreeContract contract : wbsTreeContractResultData) {
+                    String combination = contract.getId() + "_" + contract.getParentId() + "_" + contract.getWbsId() + "_" + contract.getContractId();
+                    uniqueCombinations.add(combination);
+                }
+                List<String> existingCombinations = new ArrayList<>();
+                if (!uniqueCombinations.isEmpty()) {
+                    String inClause = "'" + String.join("','", uniqueCombinations) + "'";
+                    String sqlStr = "SELECT CONCAT(id, '_', parent_id, '_', wbs_id, '_', contract_id) AS combination FROM m_wbs_tree_contract WHERE type = 2 AND is_deleted = 0 AND status = 1 AND CONCAT(id, '_', parent_id, '_', wbs_id, '_', contract_id) IN (" + inClause + ")";
+                    existingCombinations = jdbcTemplate.queryForList(sqlStr, String.class);
+                }
+                Iterator<WbsTreeContract> iterator = wbsTreeContractResultData.iterator();
+                while (iterator.hasNext()) {
+                    WbsTreeContract next = iterator.next();
+                    String combination = next.getId() + "_" + next.getParentId() + "_" + next.getWbsId() + "_" + next.getContractId();
+                    if (existingCombinations.contains(combination)) {
+                        iterator.remove();
+                    }
                 }
                 this.insertBatch(wbsTreeContractResultData, 1000);
             }
@@ -223,7 +263,6 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                     throw new ServiceException("当前施工合同段wbs树被监理或业主合同段引用中,删除失败!");
                 }
                 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<>();
@@ -234,9 +273,7 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                         }
                     });
                 }
-
                 List<String> nodeNames = tableNames.stream().map(WbsTreeContract::getNodeName).collect(Collectors.toList());
-
                 if (nodeNames.size() > 0) {
                     String names = StringUtils.join(nodeNames, " , ");
                     throw new ServiceException(StringUtil.format("节点下的 {} 中存在填报数据,删除失败!", names));
@@ -246,56 +283,53 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
 
             //TODO ---------新增---------
             if (saveIds.size() > 0) {
-                List<WbsTreePrivate> wbsTreePrivatesList = new ArrayList<>();
-                List<WbsTreeContract> wbsTreeContractList = new ArrayList<>();
                 ArrayList<ConstructionLedger> constructionLedgerList = new ArrayList<>();
+                List<WbsTreePrivate> wbsTreePrivatesList = wbsTreePrivateMapper.selectNodeAndTable2(pawDTO.getWbsId(), pawDTO.getProjectId());
+                Set<Long> saveIdsSet = saveIds.stream().map(Long::parseLong).collect(Collectors.toSet());
+                List<WbsTreeContract> wbsTreeContractList = wbsTreePrivatesList.stream()
+                        .filter(wbsTreePrivate -> {
+                            if (wbsTreePrivate.getType() == 1 || wbsTreePrivate.getType() == 2) {
+                                return saveIdsSet.contains(wbsTreePrivate.getId()) ||
+                                        (saveIdsSet.contains(wbsTreePrivate.getParentId()) && wbsTreePrivate.getType() == 2);
+                            }
+                            return false;
+                        })
+                        .map(wbsTreePrivate -> {
+                            WbsTreeContract wbsTreeContract = BeanUtil.copyProperties(wbsTreePrivate, WbsTreeContract.class);
+                            if (wbsTreeContract != null) {
+                                wbsTreeContract.setPKeyId(SnowFlakeUtil.getId());
+                                wbsTreeContract.setWbsId(pawDTO.getWbsId());
+                                wbsTreeContract.setWbsType(Integer.valueOf(wbsTreePrivate.getWbsType()));
+                                wbsTreeContract.setIsBussShow(1);
+                                wbsTreeContract.setProjectId(pawDTO.getProjectId());
+                                wbsTreeContract.setContractId(pawDTO.getContractId());
+                                wbsTreeContract.setIsConcealedWorksNode(0);
+                                wbsTreeContract.setIsTypePrivatePid(wbsTreePrivate.getPKeyId());
+                                wbsTreeContract.setCreateTime(new Date());
+                                if (wbsTreePrivate.getType() == 2) {
+                                    wbsTreeContract.setIsTypePrivatePid(wbsTreePrivate.getPKeyId());
+                                }
+                                if (wbsTreePrivate.getType() == 1) {
+                                    wbsTreeContract.setImportMatchingInfo(wbsTreePrivate.getFullName());
+                                }
+                                //台账
+                                if (wbsTreeContract.getNodeType() == 6) {
+                                    ConstructionLedger constructionLedger = new ConstructionLedger();
+                                    constructionLedger.setIsBeton(0);
+                                    constructionLedger.setWbsId(wbsTreeContract.getPKeyId());
+                                    constructionLedger.setSite(wbsTreeContract.getNodeName());
+                                    constructionLedger.setStation(wbsTreeContract.getNodeName());
+                                    constructionLedger.setContractId(Long.parseLong(pawDTO.getContractId()));
+                                    constructionLedgerList.add(constructionLedger);
+                                }
+                                return wbsTreeContract;
+                            }
+                            return null;
+                        })
+                        .filter(Objects::nonNull)
+                        .collect(Collectors.toList());
 
-                //获取wbs私有树下节点、表
-                List<WbsTreePrivate> wbsTreePrivates = wbsTreePrivateMapper.selectNodeAndTable2(pawDTO.getWbsId(), pawDTO.getProjectId());
-                for (WbsTreePrivate wbsTreePrivate : wbsTreePrivates) {
-                    for (String id : saveIds) {
-                        if (Long.parseLong(id) == (wbsTreePrivate.getId())) {
-                            wbsTreePrivatesList.add(wbsTreePrivate);
-                        } else if (Long.parseLong(id) == (wbsTreePrivate.getParentId()) && wbsTreePrivate.getType() == 2) {
-                            wbsTreePrivatesList.add(wbsTreePrivate);
-                        }
-                    }
-                }
-
-                //初始化
-                wbsTreePrivatesList.forEach(wbsTreePrivate -> {
-                    WbsTreeContract wbsTreeContract = BeanUtil.copyProperties(wbsTreePrivate, WbsTreeContract.class);
-                    if (wbsTreeContract != null) {
-                        wbsTreeContract.setPKeyId(SnowFlakeUtil.getId());
-                        wbsTreeContract.setWbsId(pawDTO.getWbsId());
-                        wbsTreeContract.setWbsType(Integer.valueOf(wbsTreePrivate.getWbsType()));
-                        wbsTreeContract.setIsBussShow(1);
-                        wbsTreeContract.setProjectId(pawDTO.getProjectId());
-                        wbsTreeContract.setContractId(pawDTO.getContractId());
-                        wbsTreeContract.setIsConcealedWorksNode(0);
-                        wbsTreeContract.setIsTypePrivatePid(wbsTreePrivate.getPKeyId());
-                        wbsTreeContract.setCreateTime(new Date());
-                        if (wbsTreePrivate.getType() == 2) {
-                            wbsTreeContract.setIsTypePrivatePid(wbsTreePrivate.getPKeyId());
-                        }
-                        if (wbsTreePrivate.getType() == 1) {
-                            wbsTreeContract.setImportMatchingInfo(wbsTreePrivate.getFullName());
-                        }
-                        wbsTreeContractList.add(wbsTreeContract);
-
-                        //台账
-                        if (wbsTreeContract.getNodeType() == 6) {
-                            ConstructionLedger constructionLedger = new ConstructionLedger();
-                            constructionLedger.setIsBeton(0);
-                            constructionLedger.setWbsId(wbsTreeContract.getPKeyId());
-                            constructionLedger.setSite(wbsTreeContract.getNodeName());
-                            constructionLedger.setStation(wbsTreeContract.getNodeName());
-                            constructionLedger.setContractId(Long.parseLong(pawDTO.getContractId()));
-                            constructionLedgerList.add(constructionLedger);
-                        }
-                    }
-                });
-
+                //入库
                 this.insertBatch(wbsTreeContractList, 1000);
                 constructionLedgerFeign.initConstructionLedger(constructionLedgerList);
             }
@@ -693,6 +727,9 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                         //根节点时默认加载所有施工合同段的树
                         contractIds = this.contractClient.getProcessContractByJLContractId(contractId);
                     }
+                    if (ObjectUtil.isEmpty(contractIds) || contractIds.size() <= 0) {
+                        return null;
+                    }
                     for (String sgContractId : contractIds) {
                         ContractInfo sgContractInfo = jdbcTemplate.query("select contract_name from m_contract_info where id = " + sgContractId, new BeanPropertyRowMapper<>(ContractInfo.class)).stream().findAny().orElse(null);
                         if (sgContractInfo != null) {
@@ -865,7 +902,7 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
      * @param lowestNodeParentIds 最底层节点ParentIds
      * @param nodesAll            所有节点
      */
-    private void recursiveGetParentNodes(List<WbsTreeContractLazyVO> result, List<Long> lowestNodeParentIds, List<WbsTreeContractLazyVO> nodesAll) {
+    public void recursiveGetParentNodes(List<WbsTreeContractLazyVO> result, List<Long> lowestNodeParentIds, List<WbsTreeContractLazyVO> nodesAll) {
         if (lowestNodeParentIds.isEmpty()) {
             return;
         }

+ 19 - 10
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreePrivateServiceImpl.java

@@ -312,7 +312,15 @@ public class WbsTreePrivateServiceImpl extends BaseServiceImpl<WbsTreePrivateMap
 
     @Override
     public Long findWbsTreePrivate(String ids) {
-        return baseMapper.selectCount(Wrappers.<WbsTreePrivate>query().lambda().eq(WbsTreePrivate::getProjectId, ids));
+        List<WbsTreePrivate> wbsTreePrivates = baseMapper.selectList(Wrappers.<WbsTreePrivate>query().lambda().select(WbsTreePrivate::getParentId).eq(WbsTreePrivate::getProjectId, ids));
+        boolean allParentIdAreMinus10 = wbsTreePrivates.stream().allMatch(f -> f.getParentId() == -10L);
+        if (allParentIdAreMinus10) {
+            //如果都是元素库引用的表,那么直接全部删除
+            jdbcTemplate.execute("delete from m_wbs_tree_private where project_id = " + ids);
+            return 0L;
+        } else {
+            return 1L;
+        }
     }
 
     @Override
@@ -968,8 +976,9 @@ public class WbsTreePrivateServiceImpl extends BaseServiceImpl<WbsTreePrivateMap
                     if (!insertList.isEmpty()) {
                         insertList.forEach(i -> i.setId(SnowFlakeUtil.getId()));
                         this.wbsParamServiceImpl.saveOrUpdateBatch(insertList, 1000);
-                        /*生成公式,并自动绑定元素*/
-                        Map<Long, Formula> insertFormulaMap = insertList.stream().map(e -> {
+                        /*生成公式,并自动绑定元素,同key复用一个公式*/
+                        Map<String, Long> formulaIdeyMap = this.wbsParamServiceImpl.formulaIdKeyMap(insertList.stream().map(WbsParam::getK).collect(Collectors.toList()));
+                      /*  Map<Long, Formula> insertFormulaMap = insertList.stream().map(e -> {
                             Map<String, Object> tmpMap = new HashMap<>();
                             Formula formula = new Formula();
                             formula.setOutm(Formula.FULL);
@@ -979,16 +988,16 @@ public class WbsTreePrivateServiceImpl extends BaseServiceImpl<WbsTreePrivateMap
                             keyMap.put("id", e.getId().toString());
                             tmpMap.put(e.getK(), keyMap);
                             if (RegexUtil.match(ParamElements.LEVEL_REG, e.getV().trim())) {
-                                /*取层级*/
+                                *//*取层级*//*
                                 formula.setFormula("FC.tree(trees,WP[" + e.getK() + "])");
                             } else {
-                                /*直接取数*/
+                                *//*直接取数*//*
                                 formula.setFormula("WP[" + e.getK() + "]");
                             }
                             formula.setMap(JSON.toJSONString(tmpMap));
                             formula.setId(SnowFlakeUtil.getId());
                             return formula;
-                        }).collect(Collectors.toMap(Formula::getParamId, f -> f));
+                        }).collect(Collectors.toMap(Formula::getParamId, f -> f));*/
                         List<String> nodeIds = insertList.stream().map(WbsParam::getNodeId).distinct().map(Objects::toString).collect(Collectors.toList());
                         /*每道工序下包含的元素集合*/
                         List<Map<String, Object>> listMaps = this.jdbcTemplate.queryForList(
@@ -1001,7 +1010,7 @@ public class WbsTreePrivateServiceImpl extends BaseServiceImpl<WbsTreePrivateMap
                         List<ElementFormulaMapping> insertEfm = new ArrayList<>();
                         insertList.forEach(p -> {
                             List<Map<String, Object>> elementMap = groupElementNode.get(p.getNodeId().toString());
-                            Formula formula = insertFormulaMap.get(p.getId());
+                            // Formula formula = insertFormulaMap.get(p.getId());
                             if (Func.isNotEmpty(elementMap)) {
                                 elementMap.forEach(m -> {
                                     if (com.mixsmart.utils.StringUtils.handleNull(m.get("name")).contains(p.getName())) {
@@ -1010,15 +1019,15 @@ public class WbsTreePrivateServiceImpl extends BaseServiceImpl<WbsTreePrivateMap
                                         efm.setScope(FormulaBean.PARAM);
                                         efm.setParamId(p.getId());
                                         efm.setElementId(Long.parseLong(m.get("id").toString()));
-                                        efm.setFormulaId(formula.getId());
+                                        efm.setFormulaId(formulaIdeyMap.get(p.getK()));
                                         insertEfm.add(efm);
                                     }
                                 });
                             }
                         });
-                        if (insertFormulaMap.size() > 0) {
+/*                        if (insertFormulaMap.size() > 0) {
                             this.formulaService.saveBatch(insertFormulaMap.values(), 1000);
-                        }
+                        }*/
                         if (insertEfm.size() > 0) {
                             this.elementFormulaMappingService.saveBatch(insertEfm, 1000);
                         }

+ 38 - 56
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreeServiceImpl.java

@@ -796,39 +796,30 @@ public class WbsTreeServiceImpl extends BaseServiceImpl<WbsTreeMapper, WbsTree>
                     List<WbsTreePrivate> insertData2 = new ArrayList<>();
 
                     if (pawDTO.getReferenceType().equals("public")) {
-                        List<WbsTree> addListData = new ArrayList<>();
                         //获取当前树下所有节点、表信息
-                        List<WbsTree> treesAll = baseMapper.selectList(Wrappers.<WbsTree>lambdaQuery().eq(WbsTree::getWbsId, pawDTO.getWbsId()).eq(WbsTree::getStatus, 1));
-                        for (WbsTree wbsTree : treesAll) {
-                            for (String id : saveIds) {
-                                if (Long.parseLong(id) == (wbsTree.getId())) {
-                                    addListData.add(wbsTree);
-                                } else if (Long.parseLong(id) == (wbsTree.getParentId()) && wbsTree.getType() == 2) {
-                                    addListData.add(wbsTree);
-                                }
-                            }
-                        }
-
-                        addListData.forEach(tree -> {
-                            WbsTreePrivate wbsTreePrivate = BeanUtil.copyProperties(tree, WbsTreePrivate.class);
-                            if (wbsTreePrivate != null) {
-                                wbsTreePrivate.setPKeyId(SnowFlakeUtil.getId());
-                                wbsTreePrivate.setWbsType(String.valueOf(pawDTO.getWbsType()));
-                                wbsTreePrivate.setProjectId(pawDTO.getProjectId());
-                                wbsTreePrivate.setFullName(wbsTreePrivate.getNodeName());
-                                wbsTreePrivate.setInitTableId(ObjectUtil.isNotEmpty(tree.getInitTableId()) ? String.valueOf(tree.getInitTableId()) : null);
-                            }
-                            insertData1.add(wbsTreePrivate);
-                        });
+                        List<WbsTree> treesAll = baseMapper.selectList(Wrappers.<WbsTree>lambdaQuery()
+                                .eq(WbsTree::getWbsId, pawDTO.getWbsId())
+                                .eq(WbsTree::getStatus, 1));
+                        Set<Long> saveIdsSet = saveIds.stream().map(Long::parseLong).collect(Collectors.toSet());
+                        insertData1 = treesAll.stream()
+                                .filter(wbsTree -> saveIdsSet.contains(wbsTree.getId()) || (saveIdsSet.contains(wbsTree.getParentId()) && wbsTree.getType() == 2))
+                                .map(tree -> {
+                                    WbsTreePrivate wbsTreePrivate = BeanUtil.copyProperties(tree, WbsTreePrivate.class);
+                                    if (wbsTreePrivate != null) {
+                                        wbsTreePrivate.setPKeyId(SnowFlakeUtil.getId());
+                                        wbsTreePrivate.setWbsType(String.valueOf(pawDTO.getWbsType()));
+                                        wbsTreePrivate.setProjectId(pawDTO.getProjectId());
+                                        wbsTreePrivate.setFullName(wbsTreePrivate.getNodeName());
+                                        wbsTreePrivate.setInitTableId(ObjectUtil.isNotEmpty(tree.getInitTableId()) ? String.valueOf(tree.getInitTableId()) : null);
+                                    }
+                                    return wbsTreePrivate;
+                                })
+                                .collect(Collectors.toList());
 
                     } else if (pawDTO.getReferenceType().equals("private")) {
                         List<WbsTreePrivate> addListData = new ArrayList<>();
 
-                        /*//获取当前树下所有节点、表信息(type=10独立表)
-                        List<WbsTreePrivate> wbsTreePrivatesNodeAndTab = wbsTreePrivateMapper.selectList(Wrappers.<WbsTreePrivate>lambdaQuery().eq(WbsTreePrivate::getStatus, 1).eq(WbsTreePrivate::getProjectId, pawDTO.getReferencePrivateWbsProjectId()).eq(WbsTreePrivate::getWbsId, pawDTO.getWbsId()).and(obj -> obj.eq(WbsTreePrivate::getType, 1).or().eq(WbsTreePrivate::getType, 2)));
-                        List<WbsTreePrivate> wbsTreePrivatesTableDLOld = wbsTreePrivateMapper.selectList(Wrappers.<WbsTreePrivate>lambdaQuery().eq(WbsTreePrivate::getProjectId, pawDTO.getReferencePrivateWbsProjectId()).eq(WbsTreePrivate::getType, 10).eq(WbsTreePrivate::getStatus, 1).eq(WbsTreePrivate::getParentId, -10).isNull(WbsTreePrivate::getWbsId));
-                        wbsTreePrivatesNodeAndTab.addAll(wbsTreePrivatesTableDLOld);*/
-
+                        //获取私有引用模板树信息
                         List<WbsTreePrivate> wbsTreePrivatesNodeAndTab = wbsTreePrivateMapper.selectList(Wrappers.<WbsTreePrivate>lambdaQuery()
                                 .eq(WbsTreePrivate::getStatus, 1)
                                 .eq(WbsTreePrivate::getProjectId, pawDTO.getReferencePrivateWbsProjectId())
@@ -836,31 +827,30 @@ public class WbsTreeServiceImpl extends BaseServiceImpl<WbsTreeMapper, WbsTree>
 
                         //获取当前项目下的所有独立表
                         List<WbsTreePrivate> wbsTreePrivatesTableDL = wbsTreePrivateMapper.selectList(Wrappers.<WbsTreePrivate>lambdaQuery().select(WbsTreePrivate::getId).eq(WbsTreePrivate::getProjectId, pawDTO.getProjectId()).eq(WbsTreePrivate::getType, 10).eq(WbsTreePrivate::getParentId, -10).eq(WbsTreePrivate::getStatus, 1));
-
-                        for (WbsTreePrivate wbsTreePrivate : wbsTreePrivatesNodeAndTab) {
-                            if (wbsTreePrivate.getType() == 1 || wbsTreePrivate.getType() == 2) {
-                                for (String id : saveIds) {
-                                    if (Long.parseLong(id) == (wbsTreePrivate.getId())) {
-                                        addListData.add(wbsTreePrivate);
-
-                                    } else if (Long.parseLong(id) == (wbsTreePrivate.getParentId()) && wbsTreePrivate.getType() == 2) {
-                                        addListData.add(wbsTreePrivate);
-                                    }
+                        Set<Long> saveIdsSet = saveIds.stream().map(Long::parseLong).collect(Collectors.toSet());
+                        wbsTreePrivatesNodeAndTab.forEach(wbsTreePrivate -> {
+                            boolean isType1Or2 = wbsTreePrivate.getType() == 1 || wbsTreePrivate.getType() == 2;
+                            boolean isType10WithParentIdMinus10 = wbsTreePrivate.getType() == 10 && wbsTreePrivate.getParentId() == -10;
+                            if (isType1Or2) {
+                                boolean isIdInSaveIds = saveIdsSet.contains(wbsTreePrivate.getId());
+                                boolean isParentIdInSaveIds = saveIdsSet.contains(wbsTreePrivate.getParentId()) && wbsTreePrivate.getType() == 2;
+                                if (isIdInSaveIds || isParentIdInSaveIds) {
+                                    addListData.add(wbsTreePrivate);
                                 }
                             }
 
-                            if (wbsTreePrivate.getType() == 10 && wbsTreePrivate.getParentId() == -10) { //type=10,parentId=-10 独立库
-                                //判断是否存在独立表单,存在则不新增
-                                List<WbsTreePrivate> collect = wbsTreePrivatesTableDL.stream().filter(f -> f.getId().equals(wbsTreePrivate.getId())).collect(Collectors.toList());
-                                if (collect.size() == 0) {
+                            if (isType10WithParentIdMinus10) {
+                                //判断是否存在独立表单,不存在则添加
+                                boolean existsInWbsTreePrivatesTableDL = wbsTreePrivatesTableDL.stream().anyMatch(t -> t.getId().equals(wbsTreePrivate.getId()));
+                                if (!existsInWbsTreePrivatesTableDL) {
                                     addListData.add(wbsTreePrivate);
                                 }
                             }
-                        }
-
-                        //只同步独立库中有关联过清表的元素表type=10,以及原始方式的元素表type=2,节点信息type=1
-                        List<WbsTreePrivate> collect = addListData.stream().filter(f -> f.getType().equals(1) || f.getType().equals(2) || (f.getHtmlUrl() != null && f.getType().equals(10))).collect(Collectors.toList());
+                        });
 
+                        List<WbsTreePrivate> collect = addListData.stream()
+                                .filter(f -> f.getType().equals(1) || f.getType().equals(2) || (f.getHtmlUrl() != null && f.getType().equals(10)))
+                                .collect(Collectors.toList());
                         collect.forEach(tree -> {
                             WbsTreePrivate wbsTreePrivate = BeanUtil.copyProperties(tree, WbsTreePrivate.class);
                             if (wbsTreePrivate != null) {
@@ -868,13 +858,11 @@ public class WbsTreeServiceImpl extends BaseServiceImpl<WbsTreeMapper, WbsTree>
                                 wbsTreePrivate.setProjectId(pawDTO.getProjectId());
                                 wbsTreePrivate.setFullName(wbsTreePrivate.getNodeName());
                                 wbsTreePrivate.setInitTableId(ObjectUtil.isNotEmpty(tree.getInitTableId()) ? String.valueOf(tree.getInitTableId()) : null);
-
                                 wbsTreePrivate.setHtmlUrl(ObjectUtil.isNotEmpty(tree.getHtmlUrl()) ? tree.getHtmlUrl() : null);
-
-                                if (tree.getType() == 10) {  //独立表单数据
+                                if (tree.getType() == 10) {
                                     wbsTreePrivate.setWbsId(null);
                                     wbsTreePrivate.setWbsType(null);
-                                } else { //非独立库形式
+                                } else {
                                     wbsTreePrivate.setWbsId(pawDTO.getPrimaryKeyId());
                                     wbsTreePrivate.setWbsType(String.valueOf(pawDTO.getWbsType()));
                                 }
@@ -888,19 +876,15 @@ public class WbsTreeServiceImpl extends BaseServiceImpl<WbsTreeMapper, WbsTree>
                         for (List<WbsTreePrivate> addList : partition1) {
                             wbsTreePrivateService.insertBatch(addList, 1000);
                         }
-
-                        //修改状态
                         if (pawDTO.getWbsType() == 1) {
                             projectInfoMapper.updateTemplateInfoQuality(pawDTO.getProjectId(), pawDTO.getWbsId(), "public");
                         }
                         if (pawDTO.getWbsType() == 2) {
                             projectInfoMapper.updateTemplateInfoTrial(pawDTO.getProjectId(), pawDTO.getWbsId(), "public");
                         }
-
                         if (pawDTO.getWbsType() == 5) {
                             projectInfoMapper.updateTemplateInfoLar(pawDTO.getProjectId(), pawDTO.getWbsId(), "public");
                         }
-
                     } else if (pawDTO.getReferenceType().equals("private")) {
                         List<List<WbsTreePrivate>> partition1 = Lists.partition(insertData2, 1000);
                         for (List<WbsTreePrivate> addList : partition1) {
@@ -910,14 +894,12 @@ public class WbsTreeServiceImpl extends BaseServiceImpl<WbsTreeMapper, WbsTree>
                         //异步修改htmlUrl
                         wbsTreePrivateService.batchResetHtmlUrl(insertData2);
 
-                        //修改状态
                         if (pawDTO.getWbsType() == 1) {
                             projectInfoMapper.updateTemplateInfoQuality(pawDTO.getProjectId(), pawDTO.getPrimaryKeyId(), "private");
                         }
                         if (pawDTO.getWbsType() == 2) {
                             projectInfoMapper.updateTemplateInfoTrial(pawDTO.getProjectId(), pawDTO.getPrimaryKeyId(), "private");
                         }
-
                         if (pawDTO.getWbsType() == 5) {
                             projectInfoMapper.updateTemplateInfoLar(pawDTO.getProjectId(), pawDTO.getWbsId(), "private");
                         }