Эх сурвалжийг харах

Merge remote-tracking branch 'origin/test-merge' into test-merge

LHB 19 цаг өмнө
parent
commit
c788a7ac73
21 өөрчлөгдсөн 622 нэмэгдсэн , 60 устгасан
  1. 54 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/vo/FixedFlowInfoVO.java
  2. 2 1
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/WbsTreeContract.java
  3. 4 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/WbsNodeTableVO.java
  4. 125 3
      blade-service/blade-business/src/main/java/org/springblade/business/controller/EVisaTaskCheckController.java
  5. 3 0
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/FixedFlowMapper.java
  6. 9 0
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/FixedFlowMapper.xml
  7. 4 0
      blade-service/blade-business/src/main/java/org/springblade/business/service/IFixedFlowService.java
  8. 7 0
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/FixedFlowServiceImpl.java
  9. 2 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ExcelTabController.java
  10. 1 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/InformationImportRecordController.java
  11. 2 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsTreeContractMapper.java
  12. 3 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsTreeContractMapper.xml
  13. 1 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsTreePrivateMapper.xml
  14. 1 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/IExcelTabService.java
  15. 1 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/IWbsTreeContractService.java
  16. 202 48
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ExcelTabServiceImpl.java
  17. 1 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/FormulaServiceImpl.java
  18. 85 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreeContractServiceImpl.java
  19. 110 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/utils/FileUtils.java
  20. 4 4
      blade-service/blade-meter/src/main/java/org/springblade/meter/mapper/FormPeriodMapper.xml
  21. 1 0
      blade-service/blade-meter/src/main/java/org/springblade/meter/service/impl/FormPeriodServiceImpl.java

+ 54 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/vo/FixedFlowInfoVO.java

@@ -0,0 +1,54 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.business.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.springblade.business.entity.FixedFlow;
+import org.springblade.business.entity.FixedFlowLink;
+import org.springblade.core.mp.support.Query;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 视图实体类
+ *
+ * @author BladeX
+ * @since 2022-07-01
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class FixedFlowInfoVO extends FixedFlow {
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty("环节处理人姓名及ID,拼接格式为:环节处理人姓名-环节处理人ID(英文逗号)环节处理人姓名-环节处理人ID")
+    private String linkUserJoinString;
+
+    private String linkUserIds;
+
+    @ApiModelProperty("是否可选")
+    private boolean disabled;
+
+    @ApiModelProperty("提示信息")
+    private String tips;
+
+    @ApiModelProperty("是否删除")
+    private boolean deletedIs;
+
+}

+ 2 - 1
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/WbsTreeContract.java

@@ -331,6 +331,7 @@ public class WbsTreeContract extends BaseEntity {
     @ApiModelProperty(value = "是否完成日期填写 1是 2否")
     private Integer dateIsComplete;
 
-
+    @ApiModelProperty(value = "导入Id")
+    private Long importId;
 
 }

+ 4 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/WbsNodeTableVO.java

@@ -105,4 +105,8 @@ public class WbsNodeTableVO implements Serializable {
 
     @ApiModelProperty(value = "是否默认隐藏,0:否,1:是")
     private Integer defaultConceal;
+
+    @ApiModelProperty("是否隐藏:1显示 其他 代表隐藏")
+    private Integer isBussShow;
+
 }

+ 125 - 3
blade-service/blade-business/src/main/java/org/springblade/business/controller/EVisaTaskCheckController.java

@@ -21,14 +21,17 @@ import org.springblade.business.service.IFixedFlowLinkService;
 import org.springblade.business.service.IFixedFlowService;
 import org.springblade.business.service.IInformationQueryService;
 import org.springblade.business.utils.PDFUtil;
+import org.springblade.business.vo.FixedFlowInfoVO;
 import org.springblade.business.vo.FixedFlowVO;
 import org.springblade.common.constant.CommonConstant;
 import org.springblade.core.secure.utils.AuthUtil;
 import org.springblade.core.tool.api.R;
 import org.springblade.core.tool.utils.Func;
 import org.springblade.core.tool.utils.ObjectUtil;
+import org.springblade.manager.dto.SaveUserInfoByProjectDTO;
 import org.springblade.manager.entity.*;
 import org.springblade.manager.feign.*;
+import org.springblade.manager.vo.ExecutionTime;
 import org.springblade.system.cache.ParamCache;
 import org.springblade.system.user.entity.User;
 import org.springblade.system.user.feign.IUserClient;
@@ -37,7 +40,9 @@ import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.web.bind.annotation.*;
 
 import java.util.*;
+import java.util.function.Function;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 @RestController
 @AllArgsConstructor
@@ -339,8 +344,125 @@ public class EVisaTaskCheckController {
             @ApiImplicitParam(name = "theLogPrimaryKeyId", value = "日志左侧所选的填报类型ID"),
             @ApiImplicitParam(name = "firstId", value = "首件记录ID,列表批量上报时传任意一个即可")
     })
-    public R<IPage<FixedFlowVO>> queryFixedFlow(@RequestBody JSONObject json) {
+    public R<List<FixedFlowInfoVO>> queryFixedFlow(@RequestBody JSONObject json) {
+        ExecutionTime executionTime = new ExecutionTime();
+        List<FixedFlowInfoVO> flowList = this.fixedFlowService.getFixedFlowList(json.getLong("contractId"), json.getLong("projectId"));
+        //获取对应表格的所有电签配置
+        String tableOwner = json.getString("tableOwner");
+        if (StringUtils.isBlank(tableOwner)) {
+            tableOwner = json.getString("classifyType"); //1 施工方  2监理  3 业主
+        }
+        Long contractId=0L;
+        if(json.getLong("contractIdRelation")!=null){
+            contractId=json.getLong("contractIdRelation");
+        }else {
+            contractId=json.getLong("contractId");
+        }
+        //查询当前节点的PDF
+        InformationQuery node = informationQueryService.getOne(new LambdaQueryWrapper<InformationQuery>()
+                .eq(InformationQuery::getWbsId, json.getString("nodeId"))
+                .eq(InformationQuery::getContractId, contractId)
+                .eq(InformationQuery::getClassify, tableOwner).last("ORDER BY id DESC limit 1"));
+
+        if (node == null || StringUtils.isBlank(node.getPdfUrl())) {
+            return R.fail(300, "当前节点还未生成PDF,不能上报");
+        }
+        List<JSONObject> jsonList = this.queryTableEVisaConfig(json, node.getPdfUrl());
+
+        if (jsonList == null || jsonList.size() == 0) {
+            return R.fail(300, "未找到符合电签配置的相关流程,请重新保存再上报");
+        }
+        //汇总电签配置的审批角色
+        List<String> eVisaRoleList = jsonList.stream().map(jsonObject -> jsonObject.getString("sigRoleId")).distinct().collect(Collectors.toList());
+        List<User> users = userClient.selectUserAll();
+        if (ObjectUtil.isEmpty(users)){
+            return R.fail(300, "未获取到当前项目用户信息");
+        }
+
+        Map<Long, User> userNamesMap = users.stream().collect(Collectors.toMap(User::getId,Function.identity(),
+                        (v1, v2) -> v1 // 冲突时保留第一个值
+                ));
+
+        List<Long> userIds = users.stream().map(l -> l.getId()).collect(Collectors.toList());
+        executionTime.info("122222");
+        List<SaveUserInfoByProjectDTO> userRoleInfo = jdbcTemplate.query("SELECT project_id as projectId,contract_id as contractId,user_id as userId,role_id as roleId from m_project_assignment_user  where is_deleted=0 ", new BeanPropertyRowMapper<>(SaveUserInfoByProjectDTO.class));
+        executionTime.info("3333333");
+        for (FixedFlowInfoVO flow : flowList){
+            //先将流程设置为可选
+            executionTime.info("1");
+            flow.setDisabled(false);
+            List<Long> ids = Func.toLongList(flow.getLinkUserIds());
+            Set<Long> flowUser = new HashSet<>(ids);
+            flowUser.removeAll(userIds);
+            if (flowUser.size() > 0){
+                flow.setDisabled(true);
+                List<String> names = new ArrayList<>();
+                for (Long id : flowUser) {
+                    names.add(userNamesMap.get(id).getName());
+                }
+                flow.setTips("以下用户账号已经删除:"+String.join(",",names));
+                continue;
+            }
+
+            // 为流程设置用户名称
+            List<String> taskUserNames = new ArrayList<>();
+            for(  Long id: ids) {
+                taskUserNames.add(userNamesMap.get(id).getName())  ;
+            }
+            flow.setLinkUserJoinString(String.join(",",taskUserNames));
+            //获取这些人资料合同段下的权限
+            executionTime.info("2");
+
+            //&& user.getContractId().equals(finalContractId) ids.contains(user.getUserId())
+            String finalContractId = contractId+"";
+            List<SaveUserInfoByProjectDTO> userRoleList =userRoleInfo.stream().filter(user -> flow.getLinkUserIds().indexOf((user.getUserId()+""))>=0 && (user.getContractId()+"").equals(finalContractId) ).collect(Collectors.toList());
+
+            executionTime.info("3");
+            if (userRoleList == null || userRoleList.size() <= 0) {
+                executionTime.info("4");
+                //查看当前项目下是否有监理合同段关联此合同段
+                String sql = "SELECT id from m_contract_info mci WHERE contract_type = 2 and id in (SELECT contract_id_jlyz  FROM m_contract_relation_jlyz WHERE contract_id_sg = " + node.getContractId() + ")";
+                ContractInfo contractInfo = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(ContractInfo.class)).stream().findAny().orElse(null);
+                if (contractInfo != null) {
+                  //  userRoleList = userRoleInfo.stream().filter(user -> ids.contains(user.getUserId()) && user.getContractId().equals(contractInfo.getId()+"")).collect(Collectors.toList());
+                    userRoleList =userRoleInfo.stream().filter(user -> flow.getLinkUserIds().indexOf((user.getUserId()+""))>=0 && (user.getContractId()+"").equals(contractInfo.getId()+"") ).collect(Collectors.toList());
+                }
+                executionTime.info("5");
+            }
+            if (userRoleList == null) {
+                flow.setDisabled(true);
+            } else {
+                //校验流程
+                //循环审批人的角色集合,并判断电签配置中是否含有这个角色
+                executionTime.info("6");
+                for (SaveUserInfoByProjectDTO userRole : userRoleList) {
+                    if (!eVisaRoleList.contains(userRole.getRoleId())) {
+                        //但凡有个不符合条件,禁选
+                        flow.setDisabled(true);
+                        //设置提示信息
+                        String name="";
+                        executionTime.info("11");
+                        User userInfo = userNamesMap.get(userRole.getUserId());
+                        executionTime.info("12");
+                        if(userInfo!=null ){
+                            name = userInfo.getName();
+                            flow.setTips(name + "没有电签权限,请检查电签配置或查看表单是否隐藏");
+                        }else{
+                            name = userRole.getUserId();
+                            flow.setTips(name + "该用户不存在");
+                        }
+                        break;
+                    }
+                }
+                executionTime.info("7");
+            }
+        }
+        return R.data(flowList);
+    }
+
+    public R<IPage<FixedFlowVO>> queryFixedFlowOld(@RequestBody JSONObject json) {
         //获取所有流程
+        ExecutionTime executionTime = new ExecutionTime();
         FixedFlowVO vo = new FixedFlowVO();
         vo.setCurrent(1);
         vo.setSize(100);
@@ -376,7 +498,7 @@ public class EVisaTaskCheckController {
             return R.fail(300, "未找到符合电签配置的相关流程,请重新保存再上报");
         }
 
-
+        executionTime.info("d第一阶段结束");
         //汇总电签配置的审批角色
         List<String> eVisaRoleList = jsonList.stream().map(jsonObject -> jsonObject.getString("sigRoleId")).distinct().collect(Collectors.toList());
         List<User> users = userClient.selectUserAll();
@@ -441,7 +563,7 @@ public class EVisaTaskCheckController {
                 }
             }
         }
-
+        executionTime.info("第二阶段结束");
         //设置流程
         flowPage.setRecords(flowList);
 

+ 3 - 0
blade-service/blade-business/src/main/java/org/springblade/business/mapper/FixedFlowMapper.java

@@ -2,6 +2,7 @@ package org.springblade.business.mapper;
 
 import org.apache.ibatis.annotations.Param;
 import org.springblade.business.entity.FixedFlow;
+import org.springblade.business.vo.FixedFlowInfoVO;
 import org.springblade.business.vo.FixedFlowVO;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 
@@ -22,4 +23,6 @@ public interface FixedFlowMapper extends BaseMapper<FixedFlow> {
      */
     List<FixedFlow> selectFixedFlowPage(@Param("current") Long current, @Param("size") Integer size, @Param("vo") FixedFlowVO vo);
 
+    List<FixedFlowInfoVO> getFixedFlowList(@Param("contractId") Long contractId, @Param("projectId") Long projectId);
+
 }

+ 9 - 0
blade-service/blade-business/src/main/java/org/springblade/business/mapper/FixedFlowMapper.xml

@@ -39,4 +39,13 @@
         order by sort ASC limit ${current}, ${size}
     </select>
 
+    <select id="getFixedFlowList" resultType="org.springblade.business.vo.FixedFlowInfoVO">
+        select a.*,
+               (select  group_concat(fixed_flow_link_user) from u_fixed_flow_link where is_deleted = 0 and fixed_flow_id =a.id GROUP BY fixed_flow_id order by fixed_flow_link_sort ASC) as linkUserIds,
+               (SELECT COUNT(*)>1 FROM u_task WHERE fixed_flow_id = a.id AND is_deleted = 0 And status !=3) as deletedIs
+        from u_fixed_flow a where a.is_deleted = 0 AND ( a.is_meter != 1 OR a.is_meter IS NULL )
+          and project_id = #{projectId}
+          and contract_id = #{contractId}
+        order by sort ASC
+    </select>
 </mapper>

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

@@ -1,10 +1,13 @@
 package org.springblade.business.service;
 
 import org.springblade.business.entity.FixedFlow;
+import org.springblade.business.vo.FixedFlowInfoVO;
 import org.springblade.business.vo.FixedFlowVO;
 import org.springblade.core.mp.base.BaseService;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 
+import java.util.List;
+
 /**
  * 服务类
  *
@@ -18,4 +21,5 @@ public interface IFixedFlowService extends BaseService<FixedFlow> {
      */
     IPage<FixedFlowVO> selectFixedFlowPage(FixedFlowVO vo);
 
+    List<FixedFlowInfoVO> getFixedFlowList(Long contractId, Long projectId);
 }

+ 7 - 0
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/FixedFlowServiceImpl.java

@@ -22,6 +22,7 @@ import lombok.AllArgsConstructor;
 import org.springblade.business.entity.FixedFlow;
 import org.springblade.business.entity.FixedFlowLink;
 import org.springblade.business.service.IFixedFlowLinkService;
+import org.springblade.business.vo.FixedFlowInfoVO;
 import org.springblade.business.vo.FixedFlowVO;
 import org.springblade.business.mapper.FixedFlowMapper;
 import org.springblade.business.service.IFixedFlowService;
@@ -30,6 +31,7 @@ import org.springblade.core.mp.support.Condition;
 import org.springframework.stereotype.Service;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 
+import java.util.Collections;
 import java.util.List;
 
 /**
@@ -77,4 +79,9 @@ public class FixedFlowServiceImpl extends BaseServiceImpl<FixedFlowMapper, Fixed
         return iPage.setRecords(resultVO);
     }
 
+    @Override
+    public List<FixedFlowInfoVO> getFixedFlowList(Long contractId, Long projectId) {
+        return  this.baseMapper.getFixedFlowList(contractId, projectId);
+    }
+
 }

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

@@ -2436,7 +2436,8 @@ public class ExcelTabController extends BladeController {
         }
 
         //保存数据到数据库
-        R<Object> result = this.excelTabService.saveOrUpdateInfo(tableInfoList,singnType,flag);
+//        R<Object> result = this.excelTabService.saveOrUpdateInfo(tableInfoList,singnType,flag);
+        R<Object> result = this.excelTabService.saveOrUpdateInfo1(tableInfoList,flag);
         RandomNumberHolder.RandomTemplateTypeclear();
         RandomNumberHolder.RandomWbsTreeContractclear();
         executionTime.info("----数据保存结束----");

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

@@ -241,7 +241,7 @@ public class InformationImportRecordController extends BladeController {
                 List<WbsTreeContract> query = jdbcTemplate.query("select * from m_wbs_tree_contract where is_deleted = 0 and p_id = " + pId + " and full_name = '" + split[i] + "'",
                         new BeanPropertyRowMapper<>(WbsTreeContract.class));
                 if (query.isEmpty() || query.get(0) == null) {
-                    break;
+                    continue;
                 }
                 target = query.get(0);
                 pId = target.getPKeyId();

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

@@ -193,4 +193,6 @@ public interface WbsTreeContractMapper extends EasyBaseMapper<WbsTreeContract> {
     List<WbsTreeContract> getChildWbsTreeContractsBatch(@Param("parentKeyId") Long parentKeyId);
 
     void updateAncestors(@Param("contract") WbsTreeContract contract);
+
+    Integer selectImportSize(@Param("importId") Long importId);
 }

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

@@ -1102,4 +1102,7 @@
     <select id="getChildWbsTreeContractsBatch" resultType="org.springblade.manager.entity.WbsTreeContract">
         CALL GetChildNodes(#{parentKeyId});
     </select>
+    <select id="selectImportSize" resultType="java.lang.Integer">
+        SELECT count(0) FROM m_wbs_tree_contract where import_id=#{importId} and is_deleted=0;
+    </select>
 </mapper>

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

@@ -515,6 +515,7 @@
                wt.id                                                                                AS id,
                wt.wbs_type                                                                          AS wbsType,
                wt.node_name                                                                         AS tableName,
+               wt.is_buss_show                                                                      AS isBussShow,
                IFNULL(if(length(trim(wt.full_name)) > 0, wt.full_name, wt.node_name), wt.node_name) AS fullName,
                case
                    when wt.table_type in (1, 9) then 1

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

@@ -109,6 +109,7 @@ public interface IExcelTabService extends BaseService<ExcelTab> {
      * 结果信息持久化
      */
     R<Object> saveOrUpdateInfo(List<TableInfo> tableInfoList,String singType,Boolean flag) throws SQLException;
+    R<Object> saveOrUpdateInfo1(List<TableInfo> tableInfoList,Boolean flag) throws SQLException;
 
     Map<String, String> getTablbCols(String pkeyid, String colkey) throws FileNotFoundException;
 

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

@@ -43,6 +43,7 @@ public interface IWbsTreeContractService extends BaseService<WbsTreeContract> {
     List<WbsTreeContractTreeVO3> lazyTreeThree(String contractIdRelation, Long parentId, String contractId);
 
     List<AppWbsTreeContractVO> searchNodeAllTable(String primaryKeyId, String tableOwner, String contractId, String projectId, HttpServletRequest request);
+    List<AppWbsTreeContractVO> searchNodeAllTable(String primaryKeyId, String tableOwner);
 
     List<WbsTreeContract> searchParentAllNode(long primaryKeyId, Long contractId);
 

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

@@ -675,7 +675,7 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
     private List<NodeTable> createNodeTables(Long nodeId, String contractId, String projectId, ExecuteType type ,String tableOwner, String recordId) {
         List<NodeTable> tableAll = new ArrayList<>();
         if (type.equals(ExecuteType.INSPECTION)) {
-            List<AppWbsTreeContractVO> treeNode = wbsTreeContractService.searchNodeAllTable(nodeId.toString(), tableOwner, contractId, projectId, null);
+            List<AppWbsTreeContractVO> treeNode = wbsTreeContractService.searchNodeAllTable(nodeId.toString(), tableOwner);
             tableAll = BeanUtil.copyProperties(treeNode, NodeTable.class);
         } else if (type.equals(ExecuteType.TESTING)) {
             List<WbsTreePrivateVO4> wbsTreePrivateVO4s = wbsTreePrivateService.searchNodeAllTable(nodeId.toString(), "1", "9", contractId, projectId, null, null);
@@ -711,8 +711,14 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
             } else {
                 List<WbsTreeContract> list = wbsTreeContractService.getBaseMapper().selectList(Wrappers.<WbsTreeContract>query().lambda().in(WbsTreeContract::getPKeyId, pkeyIds));
                 if (list.size() > 0) {
+                    Map<String, Map<String, String>> htmlElementCellMap = new HashMap<>();
                     list.forEach(e -> {
-                        Map<String, String> elementCell = FormulaUtils.getElementCell(e.getHtmlUrl());
+                        Map<String, String> map = htmlElementCellMap.get(e.getHtmlUrl());
+                        if (map == null) {
+                            map = FormulaUtils.getElementCell(e.getHtmlUrl());
+                            htmlElementCellMap.put(e.getHtmlUrl(), map);
+                        }
+                        Map<String, String> elementCell = map;
                         //扩展中间元素开发 获取字段是辅助字段  并且在html上没有这个字段
                         List<String> collect = keyMappers.stream().filter(f -> f.getAssist() == 1
                                 && elementCell.get(f.getField()) == null).map(KeyMapper::getField).collect(Collectors.toList());
@@ -1371,20 +1377,7 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
         Long projectId = Long.parseLong(wtc.getProjectId());
 
         StringBuilder data = new StringBuilder();
-        for (TableInfo tableInfo : tableInfoList) {
-            if (pKeyIds.toString().contains(tableInfo.getPkeyId())) {
-                LinkedHashMap<String, String> dataMap = tableInfo.getDataMap();
-                List<String> keys = pKeyIdKeyMap.get(tableInfo.getPkeyId());
-                if (dataMap != null && keys != null) {
-                    for (String key : keys) {
-                        String value = dataMap.get(key);
-                        if (StringUtil.hasText(value)) {
-                            data.append(value).append(",");
-                        }
-                    }
-                }
-            }
-        }
+        String resultData = "";
 
         if (currentNode != null) {
             TableElementConverter tec = new TableElementConverter(tableInfoList, keyMapperList, formulaList, coordinateMap, currentNode, tableAll);
@@ -1397,7 +1390,6 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
                 tec.before();
                 // 暂不执行特殊公式
                 this.formulaService.init(tec).sort(tec).pre(tec).calculate(tec).format(tec);
-                tec.after();
             } else {
                 tec.getLog().put(FormulaLog.OTHER, "没有执行任何公式");
             }
@@ -1405,12 +1397,48 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
             if (data.length() == 0) {
                 Map<String, FormData> map = tec.getFormDataMap();
                 List<String> relyList = formula.getRelyList();
-                if (relyList != null) {
+                FormData resultFormData = map.get(wbsTreeTable.getInitTableName() + ":" + split1[0]);
+                int index = 0;
+                if (resultFormData != null && resultFormData.getValues() != null) {
+                    List<ElementData> values = resultFormData.getValues();
+                    int x = 0, y = 0;
+                    if (split1.length > 1 && split1[1].contains("_")) {
+                        String[] point = split1[1].split("_");
+                        try {
+                            y = Integer.parseInt(point[0]);
+                            x = Integer.parseInt(point[1]);
+                        } catch (NumberFormatException e) {
+                            log.error("坐标转换错误,keyname = " + keyname);
+                        }
+                    }
+                    for (int i = 0; i < values.size(); i++) {
+                        if (values.get(i).getY() == y && values.get(i).getX() == x) {
+                            String value = values.get(i).stringValue();
+                            if (StringUtil.isBlank( value)) {
+                                value = "";
+                                if (resultFormData.getInitial().size() > i && resultFormData.getInitial().get(i) != null) {
+                                    value = resultFormData.getInitial().get(i).stringValue();
+                                }
+                            }
+                            resultData = value;
+                            index = i;
+                            break;
+                        }
+                    }
+                }
+                if (StringUtil.hasText(resultData) && relyList != null) {
+                    int tempIndex = index;
                     relyList.forEach(rely -> {
                         FormData formData = map.get(rely);
                         if (formData != null && formData.getValues() != null) {
-                            String value = formData.getValues().stream().map(ElementData::getValue).filter(Objects::nonNull).map(Objects::toString).collect(Collectors.joining(","));
-                            data.append(value).append( "☆");
+                            if (formData.getValues().size() > tempIndex) {
+                                ElementData elementData = formData.getValues().get(tempIndex);
+                                if ((elementData ==  null || StringUtil.isBlank(elementData.stringValue())) && formData.getInitial() != null && formData.getInitial().size() > tempIndex ) {
+                                    elementData = formData.getInitial().get(tempIndex);
+                                }
+                                data.append(elementData == null || elementData.getValue() == null ? "" : elementData.getValue().toString());
+                            }
+                            data.append(" ,");
                         }
                     });
                 }
@@ -1424,31 +1452,30 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
         result.put("elementName", elementName.length() == 0 ? "" : elementName.deleteCharAt(elementName.length() - 1).toString());
         result.put("type", type == 0 ? "计算" : "数据获取");
         String sourceData = data.length() == 0 ? "" : data.deleteCharAt(data.length() - 1).toString();
-        String resultData = "";
-        try {
-            resultData = tableInfoList.get(0).getDataMap().get(split1[0]);
-            if (split1.length > 1) {
-                String index = split1[1];
-                String[] split = resultData.split("☆");
-                if (split.length > 1) {
-                    resultData = "";
-                }
-                for (int i = 0; i < split.length; i++) {
-                    String string = split[i];
-                    if (string.contains(index)) {
-                        resultData = string.split("_\\^_")[0];
-                        String[] split2 = data.toString().split("☆");
-                        if (i < split2.length) {
-                            sourceData = split2[i].split("_\\^_")[0];
-                        }
-                        break;
-                    }
-                }
-            }
-            resultData = resultData.replaceAll("(\" *)","");
-        } catch (Exception e) {
-            log.error("公式计算异常:" + e.getMessage());
-        }
+//        try {
+//            resultData = tableInfoList.get(0).getDataMap().get(split1[0]);
+//            if (split1.length > 1) {
+//                String index = split1[1];
+//                String[] split = resultData.split("☆");
+//                if (split.length > 1) {
+//                    resultData = "";
+//                }
+//                for (int i = 0; i < split.length; i++) {
+//                    String string = split[i];
+//                    if (string.contains(index)) {
+//                        resultData = string.split("_\\^_")[0];
+//                        String[] split2 = data.toString().split("☆");
+//                        if (i < split2.length) {
+//                            sourceData = split2[i].split("_\\^_")[0];
+//                        }
+//                        break;
+//                    }
+//                }
+//            }
+//            resultData = resultData.replaceAll("(\" *)","");
+//        } catch (Exception e) {
+//            log.error("公式计算异常:" + e.getMessage());
+//        }
         if (resultData != null) {
             resultData = resultData.replaceAll("(_\\^_\\d+_\\d+☆?)",",");
             if (!resultData.isEmpty() && resultData.charAt(resultData.length() - 1) == ',') {
@@ -1456,6 +1483,9 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
             }
         }
         if (sourceData != null) {
+            if (resultData == null || resultData.isEmpty()) {
+                sourceData = "";
+            }
             sourceData = sourceData.replaceAll("(\" *)","").replaceAll("(_\\^_\\d+_\\d+☆?)",",");
             if (!sourceData.isEmpty() && sourceData.charAt(sourceData.length() - 1) == ',') {
                 sourceData = sourceData.substring(0, sourceData.length() - 1);
@@ -1848,6 +1878,123 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
        return R.data(tableInfoList2);
        // return R.success(fileName1);
     }
+
+    /**
+     * 保存数据, 仅针对同一节点下的表
+     * @param tableInfoList 表数据
+     * @param flag 是否回滚
+     * @return
+     */
+    @Override
+    public R<Object> saveOrUpdateInfo1(List<TableInfo> tableInfoList,Boolean flag) {
+        List<TableInfo> tableInfoList2 = new ArrayList<>();
+        String fileName1="";
+        if (ListUtils.isNotEmpty(tableInfoList)) {
+            //施工资料填报
+            String pkids = "";
+            StringBuilder log = new StringBuilder("异常:");
+            StringBuilder saveData = new StringBuilder(tableInfoList.toString());
+            try {
+                Set<Long> pKeyIds = tableInfoList.stream().filter(item -> StringUtil.isNumeric(item.getPkeyId())).map(item -> Long.parseLong(item.getPkeyId())).collect(Collectors.toSet());
+                Map<String, WbsTreeContract> contractMap = new HashMap<>();
+                WbsTreeContract wbsTreeContractByP = null;
+                if (!pKeyIds.isEmpty()) {
+                    List<WbsTreeContract> list = wbsTreeContractService.list(Wrappers.<WbsTreeContract>query().lambda().in(WbsTreeContract::getPKeyId, pKeyIds));
+                    contractMap = list.stream().collect(toMap(item -> item.getPKeyId() + "", item -> item, (k1, k2) -> k1));
+                    Set<Long> pIds = list.stream().filter(item -> item.getPId() != null && item.getPId() > 0).map(WbsTreeContract::getPId).collect(Collectors.toSet());
+                    if (!pIds.isEmpty()) {
+                        wbsTreeContractByP = wbsTreeContractService.getOne(Wrappers.<WbsTreeContract>query().lambda().in(WbsTreeContract::getPKeyId, pIds).last( " limit 1"));
+                    }
+                }
+                if (wbsTreeContractByP == null) {
+                    return R.fail("没有找到表单数据对应的节点");
+                }
+                for (TableInfo tableInfo : tableInfoList) {
+                    WbsTreeContract wbsTreeContract = contractMap.get(tableInfo.getPkeyId());
+                    StringBuilder tableName = new StringBuilder("");
+                    if (wbsTreeContract == null) {
+                        continue;
+                    }
+                    tableInfo.setIsTypePrivatePid(wbsTreeContract.getExcelId()+"");
+                    tableInfoList2.add(tableInfo);
+                    pkids += tableInfo.getPkeyId() + ",";
+                    String tabName = wbsTreeContract.getInitTableName();
+                    // 判读修改还是 添加
+                    String delSql = "delete from " + tabName + " where p_key_id=" + tableInfo.getPkeyId();
+                    String sqlInfo = "";
+                    LinkedHashMap<String, String> dataMap2 = tableInfo.getDataMap();
+                    /*检查发现有p_key_id缺失的情况,导致表单数据丢失,所以强制覆盖*/
+                    dataMap2.put("p_key_id", tableInfo.getPkeyId());
+                    dataMap2=isPartition(wbsTreeContract,tabName,dataMap2);
+                    sqlInfo = buildMTableInsertSql(tabName, dataMap2, SnowFlakeUtil.getId(), null, null).toString();
+
+                    UpdateWrapper<WbsTreeContract> updateWrapper = new UpdateWrapper<>();
+                    updateWrapper.in("p_key_id", tableInfo.getPkeyId());
+                    updateWrapper.set("is_tab_pdf", 2);
+                    BladeUser user = AuthUtil.getUser();
+                    TransactionStatus transactionStatus = this.beginTransaction(transactionManager1);
+                    try {
+                        wbsTreeContractService.update(updateWrapper);
+                        //添加被张表的操作日志
+                        StringBuffer sb = new StringBuffer();
+                        String sqlInfoNew = sqlInfo.replace("\"", "'");
+                        sb.append("insert into blade_tab_sql(p_key_id,user_id,create_time,sql_info) VALUES(");
+                        sb.append(tableInfo.getPkeyId());sb.append(",");sb.append(user.getUserId());
+                        sb.append(","); sb.append("SYSDATE()");sb.append(",\"");sb.append(sqlInfoNew);
+                        sb.append("\")");
+
+                        jdbcTemplate.execute(delSql);
+                        jdbcTemplate.execute(sqlInfo.replace("\\","\\\\"));
+                        jdbcTemplate.execute(sb.toString());
+
+                        transactionManager1.commit(transactionStatus);
+                    } catch (Exception e) {
+                        //是否回滚
+                        if(flag){
+                            transactionManager1.rollback(transactionStatus);
+                            log.append(e.getMessage()).append("@@");
+                            e.printStackTrace();
+                            return R.fail(reason(e.getMessage()));
+                        }else {
+                            tableName.append(wbsTreeContract.getNodeName()+",");
+                            RandomNumberHolder.setLogMessage(tableName.toString());
+                        }
+                    }
+                }
+                //处理文件提名
+                fileName1= this.wbsParamService.createFileTitle(wbsTreeContractByP);
+                if(wbsTreeContractByP.getMajorDataType()!=null&&wbsTreeContractByP.getMajorDataType()==4){
+                    String sql1="Select sg_suffix,jl_suffix from m_project_info where id="+wbsTreeContractByP.getProjectId()+" and is_deleted=0";
+                    List<ProjectInfo> query = jdbcTemplate.query(sql1, new BeanPropertyRowMapper<>(ProjectInfo.class));
+                    if(query.size()>0){
+                        if(tableInfoList.get(0).getClassify()!=null&&tableInfoList.get(0).getClassify().equals("1")){
+                            fileName1=fileName1+(query.get(0).getSgSuffix()==null?"":query.get(0).getSgSuffix());
+                        }else {
+                            fileName1=fileName1+(query.get(0).getJlSuffix()==null?"":query.get(0).getJlSuffix());
+                        }
+                    }
+                }
+                //huangjn 保存成功后调用生成资料查询列表数据
+                this.informationQueryClient.saveOrUpdateInformationQueryData(wbsTreeContractByP.getPKeyId() + "", "首件使用字段", "业务ID(主要将来给首件使用)", fileName1, Integer.parseInt(tableInfoList.get(0).getClassify()), 2, "false", "源文件(首件字段)", "pdf文件(首件字段)", "首件上传总结报告名称", new ArrayList<>());
+                JSONObject json = new JSONObject();
+                json.put("operationObjIds", Func.toStrList(pkids));
+                json.put("operationObjName", wbsTreeContractByP.getNodeName() + "节点数据操作");
+                json.put("saveData", saveData.toString());
+                json.put("projectId", wbsTreeContractByP.getProjectId());
+                json.put("contractId", wbsTreeContractByP.getContractId());
+
+                //保存操作记录
+                this.operationLogClient.saveUserOperationLog(1, "资料填报", "工序填报页面", json);
+            } catch (Exception e) {
+                e.printStackTrace();
+                return R.fail("操作失败");
+            }
+            if (log.length() > 5) {
+                return R.fail(reason(log.toString()));
+            }
+        }
+        return R.data(tableInfoList2);
+    }
     public LinkedHashMap<String ,String> isPartition(WbsTreeContract wbsTreeContract,String tabName,LinkedHashMap<String, String> dataMap2){
         //判断是否需要移除编号 当工序 子分项 分项的划分编码有一个不为null就移除编号
         String sqlContractInfo="select * from m_contract_info where id="+wbsTreeContract.getContractId();
@@ -2849,8 +2996,10 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
             if (xx >= all) {
                 int fisRow = mergedCell.getFirstRow();
                 int firsrCol = mergedCell.getFirstColumn();
-
                 Cell cell = sheet.getRow(fisRow).getCell(firsrCol);
+                if(cell==null){
+                    continue;
+                }
                 short fontIndex = cell.getCellStyle().getFontIndex();
 
                 Font oldfontAt = workbook.getFontAt(fontIndex);
@@ -3302,7 +3451,8 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
     public void getBussPdfs(String nodeId, String classify, String contractId, String projectId) throws Exception {
         String file_path = FileUtils.getSysLocalFileUrl();
         // 获取有权限的节点信息
-        List<AppWbsTreeContractVO> wbsTreeContractList = wbsTreeContractService.searchNodeAllTable(nodeId, classify, contractId, projectId, null);
+//        List<AppWbsTreeContractVO> wbsTreeContractList = wbsTreeContractService.searchNodeAllTable(nodeId, classify, contractId, projectId, null);
+        List<AppWbsTreeContractVO> wbsTreeContractList = wbsTreeContractService.searchNodeAllTable(nodeId, classify);
         List<String> data = new ArrayList<>();
         if (nodeId.indexOf(":") >= 0) {
             nodeId = nodeId.split(":")[0];
@@ -3332,8 +3482,12 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
         }
         if (data.size() >= 1) {
             //资料填报原始pdf合并
-            FileUtils.mergePdfPublicMethods(data, listPdf);
+//            FileUtils.mergePdfPublicMethods(data, listPdf);
+            long startTime = System.currentTimeMillis();
+            FileUtils.mergePDFParallel(data, listPdf);
+            long endTime = System.currentTimeMillis();
             BladeFile bladeFile = this.newIOSSClient.uploadFile(nodeId + ".pdf", listPdf);
+            System.out.println("pdf合并耗时:" + (endTime - startTime) + "ms, pdf合并个数:" + data.size() + ", pdf 上传耗时:" + (System.currentTimeMillis() - endTime) + "ms");
             if(bladeFile == null){
                 System.out.println("Oss上传失败");
             }

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

@@ -236,7 +236,7 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
             tec.constantMap.put(WP, getWpMap(one, tec));
 
             /*表格名称*/
-            List<AppWbsTreeContractVO> tableList = wbsTreeContractService.searchNodeAllTable(one.getPkId().toString(), "1", tec.getContractId().toString(), tec.getProjectId().toString(), null);
+            List<AppWbsTreeContractVO> tableList = wbsTreeContractService.searchNodeAllTable(one.getPkId().toString(), "1");
             tec.constantMap.put(TABLE_LIST, tableList);
 
             /*监表质量附件,过滤掉隐藏表格*/

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

@@ -673,6 +673,67 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
         return resultTabs;
     }
 
+    /**
+     * 根据节点pKeyId获取节点下所属 tableOwer 表单
+     * 没有用户填报信息
+     */
+    @Override
+    public List<AppWbsTreeContractVO> searchNodeAllTable(String primaryKeyId, String tableOwner) {
+        WbsTreeContract wbsTreeContract = baseMapper.selectOne(Wrappers.<WbsTreeContract>query().lambda()
+                .eq(WbsTreeContract::getPKeyId, primaryKeyId));
+        if (wbsTreeContract == null) {
+            return Collections.emptyList();
+        }
+        //接口请求表单类型(施工质检 或 监理抽检)
+        Set<String> tabTableOwnerSets = new HashSet<>();
+        /*tableOwner!=null,表示从资料填报查询,查权限数据,roleTableOwnerSets=取交集后*/
+        if (StringUtils.isNotEmpty(tableOwner)) {
+            String tableOwners;
+            if (tableOwner.equals("1")) {
+                tableOwners = "1,2,3";
+            } else if (tableOwner.equals("2")) {
+                tableOwners = "4,5,6";
+            } else {
+                tableOwners = "7,8,9";
+            }
+            tabTableOwnerSets.addAll(Func.toStrList(tableOwners));
+        }
+        //判断是客户端还是APP
+        List<AppWbsTreeContractVO> resultTabs;
+        //其他接口调用默认保持原始调用方式查询
+        if (!tabTableOwnerSets.isEmpty()) {
+            List<WbsTreeContract> wbsTreeContracts = baseMapper.selectList(Wrappers.<WbsTreeContract>lambdaQuery()
+                    .eq(WbsTreeContract::getProjectId, wbsTreeContract.getProjectId()).eq(WbsTreeContract::getWbsId, wbsTreeContract.getWbsId())
+                    .eq(WbsTreeContract::getContractId, wbsTreeContract.getContractId()).eq(WbsTreeContract::getParentId, wbsTreeContract.getId()).eq(WbsTreeContract::getType, 2)
+                    .eq(WbsTreeContract::getStatus, 1).eq(StringUtil.hasText(wbsTreeContract.getContractIdRelation()) , WbsTreeContract::getContractId, wbsTreeContract.getContractIdRelation())
+                    .in(WbsTreeContract::getTableOwner, tabTableOwnerSets).last(" ORDER BY sort,full_name,create_time"));
+            resultTabs = wbsTreeContracts.stream().map(item -> {
+                AppWbsTreeContractVO appWbsTreeContractVO = new AppWbsTreeContractVO();
+                BeanUtil.copy(item, appWbsTreeContractVO);
+                return appWbsTreeContractVO;
+            }).collect(Collectors.toList());
+        } else {
+            resultTabs = new ArrayList<>();
+        }
+        if (ObjectUtil.isNotEmpty(wbsTreeContract.getMajorDataType()) && wbsTreeContract.getMajorDataType().equals(2)) {
+            resultTabs.sort(Comparator.comparing((WbsTreeContract contract) -> contract.getNodeName().contains("JS107"))
+                    .thenComparing(WbsTreeContract::getNodeName));
+        }
+        if (Optional.ofNullable(wbsTreeContract.getIsUseSort()).orElse(0) == 0) {
+            //表单排序
+            if (!resultTabs.isEmpty()) {
+                sortTabsByIsTypePrivatePid(resultTabs);
+                // 使用自定义 Comparator 进行排序
+                resultTabs.sort(new WbsTreeContractComparator());
+                List<AppWbsTreeContractVO> resultTabsToCopy = this.sortTabs(resultTabs, "__"); //复制表排序
+                return this.sortTabs(resultTabsToCopy, "_PL_"); //频率表排序
+            }
+        }
+        // 使用自定义 Comparator 进行排序
+        resultTabs.sort(new WbsTreeContractComparator());
+        return resultTabs;
+    }
+
     private void sortTabsByIsTypePrivatePid(List<AppWbsTreeContractVO> resultTabs) {
         if(!resultTabs.isEmpty()){
            StringBuilder ids=new StringBuilder("");
@@ -3146,6 +3207,7 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
             }
             int i = 0;
             int size = list.size();
+            Long importId=SnowFlakeUtil.getId();
             try{
                 String sqlList1 = "Select parent_id,node_name,p_id from m_wbs_tree_contract where contract_id=" + wbsTreeContractRoot.getContractId() + " and wbs_id=" + wbsTreeContractRoot.getWbsId() + " and is_deleted=0";
                 List<WbsTreeContract> WbsTreeContractList = jdbcTemplate.query(sqlList1, new BeanPropertyRowMapper<>(WbsTreeContract.class));
@@ -3176,6 +3238,7 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                             unit.setDateIsComplete(null);
                             unit.setPId(wbsTreeContractRoot.getPKeyId());
                             unit.setAncestorsPId(wbsTreeContractRoot.getAncestorsPId() + "," + wbsTreeContractRoot.getPKeyId());
+                            unit.setImportId(importId);
                             baseMapper.insert(unit);
                             insertList.add(unit);
                             WbsTreeContractList.add(unit);
@@ -3204,6 +3267,7 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                             subUnit.setDateIsComplete(null);
                             subUnit.setPId(fatherNode.getPKeyId());
                             subUnit.setAncestorsPId(fatherNode.getAncestorsPId() + "," + fatherNode.getPKeyId());
+                            subUnit.setImportId(importId);
                             baseMapper.insert(subUnit);
                             insertList.add(subUnit);
                             WbsTreeContractList.add(subUnit);
@@ -3252,6 +3316,7 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                                         division.setDateIsComplete(null);
                                         division.setPId(contract.getPKeyId());
                                         division.setAncestorsPId(contract.getAncestorsPId() + "," + contract.getPKeyId());
+                                        division.setImportId(importId);
                                         baseMapper.insert(division);
                                         insertList.add(division);
                                         WbsTreeContractList.add(division);
@@ -3307,6 +3372,7 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                                         subDivision.setDateIsComplete(null);
                                         subDivision.setPId(contract.getPKeyId());
                                         subDivision.setAncestorsPId(contract.getAncestorsPId() + "," + contract.getPKeyId());
+                                        subDivision.setImportId(importId);
                                         baseMapper.insert(subDivision);
                                         insertList.add(subDivision);
                                         WbsTreeContractList.add(subDivision);
@@ -3365,6 +3431,7 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                                         item.setDateIsComplete(null);
                                         item.setPId(contract.getPKeyId());
                                         item.setAncestorsPId(contract.getAncestorsPId() + "," + contract.getPKeyId());
+                                        item.setImportId(importId);
                                         baseMapper.insert(item);
                                         insertList.add(item);
                                         WbsTreeContractList.add(item);
@@ -3426,6 +3493,7 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                                         subItem.setDateIsComplete(null);
                                         subItem.setPId(contract.getPKeyId());
                                         subItem.setAncestorsPId(contract.getAncestorsPId() + "," + contract.getPKeyId());
+                                        subItem.setImportId(importId);
                                         baseMapper.insert(subItem);
                                         insertList.add(subItem);
                                         WbsTreeContractList.add(subItem);
@@ -3440,7 +3508,6 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
             } catch (Exception e) {
                 bladeRedis.del("import:projectId:"+wbsTreeContractRoot.getProjectId()+"contractId:"+wbsTreeContractRoot.getContractId());
             }finally {
-                bladeRedis.del("import:projectId:"+wbsTreeContractRoot.getProjectId()+"contractId:"+wbsTreeContractRoot.getContractId());
                 try {
                     if (!insertList.isEmpty()) {
                         wbsTreeContractStatisticsClient.updateWbsTreeContractNodes(insertList.stream().map(item -> item.getPKeyId() + "").collect(Collectors.joining(",")));
@@ -3449,11 +3516,28 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                     e.printStackTrace();
                 }
             }
+            if(!insertList.isEmpty()){
+                int x=insertList.size()/5;
+                int y=0;
+                boolean flag=true;
+                while (flag){
+                    y++;
+                    Thread.sleep(5000);
+                    Integer importSize=baseMapper.selectImportSize(importId);
+                    if(importSize==insertList.size()||y==x){
+                       flag=false;
+                   }
+                }
+            }
             bladeRedis.setEx("import:projectId:"+wbsTreeContractRoot.getProjectId()+"contractId:"+wbsTreeContractRoot.getContractId(), "100",7L);
             return R.success("新增了" + insertList.size() + "个节点" + "," + String.join(",", updateList) + "节点编号已被修改");
         } catch (IOException e) {
             bladeRedis.del("import:projectId:"+wbsTreeContractRoot.getProjectId()+"contractId:"+wbsTreeContractRoot.getContractId());
             return R.fail("文件处理失败: " + e.getMessage());
+        } catch (InterruptedException e) {
+            throw new RuntimeException(e);
+        }finally {
+            bladeRedis.del("import:projectId:"+wbsTreeContractRoot.getProjectId()+"contractId:"+wbsTreeContractRoot.getContractId());
         }
     }
 

+ 110 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/utils/FileUtils.java

@@ -28,6 +28,7 @@ import org.apache.poi.xssf.usermodel.XSSFWorkbook;
 import org.jsoup.Jsoup;
 import org.jsoup.nodes.Element;
 import org.jsoup.select.Elements;
+import org.springblade.business.utils.DigestUtil;
 import org.springblade.common.constant.CommonConstant;
 import org.springblade.common.utils.CommonUtil;
 import org.springblade.common.utils.SnowFlakeUtil;
@@ -55,6 +56,7 @@ import java.net.URLEncoder;
 import java.nio.file.*;
 import java.util.List;
 import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.regex.Matcher;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipOutputStream;
@@ -302,6 +304,114 @@ public class FileUtils {
             doc.close();
         }
     }
+    private static void mergeChunkSequentially(List<String> urlList, String outputFile) {
+        Document doc = new Document();
+        PdfCopy pdfCopy = null;
+        try {
+            pdfCopy = new PdfCopy(doc, Files.newOutputStream(Paths.get(outputFile)));
+            doc.open();
+            for (String urlStr : urlList) {
+                try (InputStream inputStream = CommonUtil.getOSSInputStream(urlStr)) {
+                    if (inputStream == null) {
+                        continue;
+                    }
+                    PdfReader reader = new PdfReader(inputStream);
+                    PdfReader.unethicalreading = true;
+
+                    int pageCount = reader.getNumberOfPages();
+                    for (int i = 1; i <= pageCount; i++) {
+                        pdfCopy.addPage(pdfCopy.getImportedPage(reader, i));
+                    }
+                    reader.close();
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        } finally {
+            doc.close();
+            if (pdfCopy != null) {
+                pdfCopy.close();
+            }
+        }
+    }
+
+    private static void mergeTempFiles(List<String> tempFiles, String outputFile) {
+        Document doc = new Document();
+        PdfCopy pdfCopy = null;
+        try {
+            pdfCopy = new PdfCopy(doc, new FileOutputStream(outputFile));
+            doc.open();
+
+            for (String tempFile : tempFiles) {
+                try (FileInputStream fis = new FileInputStream(tempFile)) {
+                    PdfReader reader = new PdfReader(fis);
+                    int pageCount = reader.getNumberOfPages();
+                    for (int i = 1; i <= pageCount; i++) {
+                        pdfCopy.addPage(pdfCopy.getImportedPage(reader, i));
+                    }
+                    reader.close();
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        } finally {
+            doc.close();
+            if (pdfCopy != null) {
+                pdfCopy.close();
+            }
+        }
+    }
+    public static void mergePDFParallel(List<String> urlList, String localImgUrl) {
+        int chunkSize = 50; // 每块处理的PDF数量
+        long tempId = SnowFlakeUtil.getId();
+        try {
+            if (urlList.size() % chunkSize != 0) {
+                int numChunks =  urlList.size() / chunkSize + 1;
+                chunkSize = urlList.size() / numChunks + 1;
+            }
+            // 将URL列表分块
+            List<Map<Integer, List<String>>> chunks = new ArrayList<>();
+            for (int i = 0; i < urlList.size(); i += chunkSize) {
+                int end = Math.min(i + chunkSize, urlList.size());
+                Map<Integer, List<String>> chunkMap = new HashMap<>();
+                chunkMap.put(i,urlList.subList(i, end));
+                chunks.add(chunkMap);
+            }
+            // 并行处理每个块,生成临时文件
+            Map<String, Integer> tempFilesSortMap = new ConcurrentHashMap<>();
+            chunks.parallelStream().forEach(chunk -> {
+                try {
+                    String tempFile = System.getProperty("java.io.tmpdir") + "/temp_" + tempId + "_" + SnowFlakeUtil.getId() + ".pdf";
+                    chunk.forEach((key, value) -> {
+                        tempFilesSortMap.put(tempFile, key);
+                        mergeChunkSequentially(value, tempFile);
+                    });
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            });
+            if (!tempFilesSortMap.isEmpty()) {
+                List<String> tempFiles = new ArrayList<>(tempFilesSortMap.keySet());
+                tempFiles.sort(Comparator.comparingInt(tempFilesSortMap::get));
+                // 最后合并所有临时文件
+                mergeTempFiles(tempFiles, localImgUrl);
+                // 清理临时文件
+                tempFiles.forEach(tempFile -> {
+                    try {
+                        Files.deleteIfExists(Paths.get(tempFile));
+                    } catch (IOException e) {
+                        // ignore
+                    }
+                });
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
 
     /**
      * Excel 转 PDF(完整缩放到 A4 纸张)

+ 4 - 4
blade-service/blade-meter/src/main/java/org/springblade/meter/mapper/FormPeriodMapper.xml

@@ -2,11 +2,11 @@
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="org.springblade.meter.mapper.FormPeriodMapper">
     <delete id="removeByContractId">
-        delete from s_form_period where contract_id = #{contractId}
-    </delete>
-    <delete id="removeById">
-        delete from s_form_period where id = #{id}
+        delete from s_form_period where contract_id = #{contractId} and is_deleted = 0
     </delete>
+    <update id="removeById">
+        update s_form_period set is_deleted = 1 where id = #{id}
+    </update>
 
 
     <select id="periodPage" resultType="org.springblade.meter.vo.FormPeriodVO">

+ 1 - 0
blade-service/blade-meter/src/main/java/org/springblade/meter/service/impl/FormPeriodServiceImpl.java

@@ -98,6 +98,7 @@ public class FormPeriodServiceImpl extends BaseServiceImpl<FormPeriodMapper, For
                 throw new ServiceException("删除失败:当前资金预算期已经被引用");
             }
             baseMapper.removeById(formPeriodId);
+
         }
     }
 }