Browse Source

优化日志查询

cr 7 hours ago
parent
commit
dbd5ac949e

+ 2 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/feign/ContractLogClient.java

@@ -63,4 +63,6 @@ public interface ContractLogClient {
     @PostMapping(API_PREFIX + "/saveLogWbsList")
     String saveLogWbsList(@RequestBody SaveContractLogVO saveContractLogVO);
 
+    @PostMapping(API_PREFIX + "/queryContractLogByIds1")
+    List<ContractLog> queryContractLogByIds1(List<String> theLogIds);
 }

+ 6 - 0
blade-service/blade-business/src/main/java/org/springblade/business/feignClient/ContractLogClientImpl.java

@@ -24,6 +24,7 @@ import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.web.bind.annotation.RestController;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Date;
 import java.util.List;
 
@@ -208,6 +209,11 @@ public class ContractLogClientImpl implements ContractLogClient {
         return "success";
     }
 
+    @Override
+    public List<ContractLog> queryContractLogByIds1(List<String> theLogIds) {
+        return this.contractLogService.list(Wrappers.<ContractLog>lambdaQuery().in(ContractLog::getId, theLogIds));
+    }
+
     private ContractLogWbs createContractLogWbs(JSONObject json, ContractLog contractLog) {
         ContractLogWbs newLogWbs = new ContractLogWbs();
         newLogWbs.setId(SnowFlakeUtil.getId());

+ 582 - 339
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ExcelTabController.java

@@ -1,5 +1,7 @@
 package org.springblade.manager.controller;
 
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.StrUtil;
 import cn.hutool.http.HttpUtil;
 import cn.hutool.log.StaticLog;
 import com.alibaba.fastjson.JSON;
@@ -2860,7 +2862,7 @@ public class ExcelTabController extends BladeController {
                 }
 
                 //获取数据
-                List<Map<String, Object>> businessDataMapList = this.getTheLogBusinessData(dataId, nodePrimaryKeyId, recordTime, contractId).getData();
+                List<Map<String, Object>> businessDataMapList = this.getTheLogBusinessData(new ArrayList<String>(Collections.singleton(dataId)), nodePrimaryKeyId, recordTime, contractId).getData();
                 ProjectInfo projectInfo = projectInfoService.getById(tableNode.getProjectId());
                 //处理数据
                 for (Map<String, Object> dataMap : businessDataMapList) {
@@ -3128,366 +3130,607 @@ public class ExcelTabController extends BladeController {
             @ApiImplicitParam(name = "recordTime", value = "当前选择的填写日期,即右侧日期控件所选日期,格式为 yyyy-MM-dd"),
             @ApiImplicitParam(name = "contractId", value = "合同段id")
     })
-    public R<List<Map<String, Object>>> getTheLogBusinessData(String theLogId, String nodePrimaryKeyId, String recordTime, String contractId) {
-        List<Map<String, Object>> resultMapList = new ArrayList<>();
-        //数据结果
-        String logId2 = "";
-
-        //获取对应的记录
-        String dataIds;
-        if (StringUtils.isNotEmpty(theLogId)) {
-            String[] split = theLogId.split(",");
-            List<String> ids = new LinkedList<>();
-            for (String logId : split) {
-                ContractLog contractLog = this.contractLogClient.queryContractLogByIdToObj(logId);
-                ids.add(contractLog.getDataId().toString());
-            }
-            dataIds = ids.stream().filter(Objects::nonNull).collect(Collectors.joining(","));
-        } else {
-            List<ContractLog> contractLogs = this.contractLogClient.queryContractLogByPrimaryKeyIdAndRecordTimeList(nodePrimaryKeyId, recordTime, contractId,null);
-            if (contractLogs.size() == 0) {
-                logId2 = "";
-            } else {
-                logId2 = contractLogs.get(0).getId() + "";
-            }
-            dataIds = contractLogs.stream().map(ContractLog::getDataId).filter(Objects::nonNull).map(String::valueOf).collect(Collectors.joining(","));
-        }
+//    public R<List<Map<String, Object>>> getTheLogBusinessData(String theLogId, String nodePrimaryKeyId, String recordTime, String contractId) {
+//        List<Map<String, Object>> resultMapList = new ArrayList<>();
+//        //数据结果
+//        String logId2 = "";
+//
+//        //获取对应的记录
+//        String dataIds;
+//        if (StringUtils.isNotEmpty(theLogId)) {
+//            String[] split = theLogId.split(",");
+//            List<String> ids = new LinkedList<>();
+//            for (String logId : split) {
+//                ContractLog contractLog = this.contractLogClient.queryContractLogByIdToObj(logId);
+//                ids.add(contractLog.getDataId().toString());
+//            }
+//            dataIds = ids.stream().filter(Objects::nonNull).collect(Collectors.joining(","));
+//        } else {
+//            List<ContractLog> contractLogs = this.contractLogClient.queryContractLogByPrimaryKeyIdAndRecordTimeList(nodePrimaryKeyId, recordTime, contractId,null);
+//            if (contractLogs.size() == 0) {
+//                logId2 = "";
+//            } else {
+//                logId2 = contractLogs.get(0).getId() + "";
+//            }
+//            dataIds = contractLogs.stream().map(ContractLog::getDataId).filter(Objects::nonNull).map(String::valueOf).collect(Collectors.joining(","));
+//        }
+//
+//        WbsTreePrivate node;
+//        WbsTreePrivate tableNode2;
+//        try{
+//            node = this.wbsTreePrivateService.getOne(Wrappers.<WbsTreePrivate>lambdaQuery().eq(WbsTreePrivate::getPKeyId, nodePrimaryKeyId));
+//            tableNode2= this.wbsTreePrivateService.getOne(Wrappers.<WbsTreePrivate>lambdaQuery()
+//                .eq(WbsTreePrivate::getParentId, node.getId()).eq(WbsTreePrivate::getProjectId, node.getProjectId()));
+//        } catch (Exception e) {
+//            throw new ServiceException("表单重复,请确认表单");
+//        }
+//        if (StringUtils.isNotEmpty(dataIds)) {
+//            if (dataIds.startsWith(",")) {
+//                dataIds = dataIds.substring(1);
+//            }
+//            for (String dataId : dataIds.split(",")) {
+//                Map<String, Object> reData = new HashMap<>();
+//                reData.put("", logId2);
+//                //检查实体表是否存在
+//                String tabName = tableNode2.getInitTableName();
+//                String isExitSql = " select * from information_schema.TABLES where TABLE_NAME='" + tabName + "'";
+//
+//                List<Map<String, Object>> tabList = this.jdbcTemplate.queryForList(isExitSql);
+//                if (tabList.size() <= 0) {
+//                    return R.fail("无实体表对应");
+//                }
+//
+//                //查询数据
+//                String querySql = "SELECT * FROM " + tabName + " WHERE id = " + dataId + " and group_id = " + tableNode2.getPKeyId();
+//
+//                List<Map<String, Object>> businessDataMap = this.jdbcTemplate.queryForList(querySql);
+//
+//                if (businessDataMap.size() > 0) {
+//                    DataStructureFormatUtils.parseDataByKey(businessDataMap);
+//                    // 匹配关联
+//                    try {
+//                        if (tableNode2.getHtmlUrl() != null) {
+//                            InputStream inputStreamByUrl = FileUtils.getInputStreamByUrl(tableNode2.getHtmlUrl());
+//                            String htmlString = IoUtil.readToString(inputStreamByUrl);
+//                            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~=^项目名称]");
+//
+//
+//                            /**
+//                             * 承包单位 承包单位、施工单位:引用施工单位名称 ,
+//                             * 监理单位:引用监理单位名称
+//                             * 合同段、所属建设项目(合同段):引用合同段编号
+//                             *
+//                             * 施工单位:施工单位 和 安装单位
+//                             *
+//                             */
+//                            ContractInfo contractInfo = contractInfoService.getById(contractId);
+//                            // 施工单位名称
+//                            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 (htdtitle.size() >= 1) {
+//                                for (Element element : htdtitle) {
+//                                    int trindex = Integer.parseInt(element.attr("trindex"));
+//                                    if (trindex <= 8) {
+//                                        reData.put(element.attr("keyName"), contractInfo.getContractNumber());
+//                                    }
+//                                }
+//                            }
+//                            // 监理单位名称
+//                            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());
+//                                    }
+//                                }
+//                            }
+//
+//                            // 项目名称
+//                            if (xmtitle.size() >= 1) {
+//                                for (Element element : xmtitle) {
+//                                    int trindex = Integer.parseInt(element.attr("trindex"));
+//                                    if (trindex <= 6) {
+//                                        ProjectInfo projectInfo = projectInfoService.getById(tableNode2.getProjectId());
+//                                        reData.put(element.attr("keyName"), projectInfo.getProjectName());
+//
+//                                    }
+//                                }
+//                            }
+//
+//                            // 日期默认值
+//                            Elements dateTitle = doc.select("el-date-picker[placeholder~=日期]");
+//                            //日期默认
+//                            if (dateTitle.size() >= 1) {
+//                                for (Element element : dateTitle) {
+//                                    int trindex = Integer.parseInt(element.attr("trindex"));
+//                                    if (trindex <= 10) {
+//                                        reData.put(element.attr("keyName"), recordTime);
+//                                    }
+//                                }
+//                            }
+//
+//                            // 添加默认值
+//                            Elements elements = doc.getElementsByAttribute("defText");
+//                            if (Func.isNotEmpty(elements) && elements.size() >= 1) {
+//                                for (Element eleme : elements) {
+//                                    String id = Func.isNull(eleme.attr("id")) ? eleme.attr("keyname") : eleme.attr("id");
+//                                    if (Func.isNotEmpty(id)) {
+//                                        reData.put(id, eleme.attr("defText"));
+//                                    }
+//                                }
+//                            }
+//                        }
+//                    } catch (Exception e) {
+//                        e.printStackTrace();
+//                    }
+//                    for (Map<String, Object> mysqlData : businessDataMap) {
+//                        String querySqlx = "SELECT tree_primary_key_id as primaryKeyId,title as path from u_contract_log_wbs where  business_id ='" + dataId + "' and is_deleted = 0";
+//                        List<Map<String, Object>> businessDat = this.jdbcTemplate.queryForList(querySqlx);
+//                        reData.put("linkTabIds", businessDat);
+//                        for (String key : mysqlData.keySet()) {
+//                            String tabVal = mysqlData.get(key) + "";
+//                            // 时间段处理
+//                            if (StringUtils.isNotEmpty(tabVal) && !tabVal.equals("null")) {
+//                                if (tabVal.indexOf("T") >= 0 && tabVal.indexOf(".000Z]") >= 0) {
+//                                    String[] tabData = tabVal.split("_\\^_");
+//                                    if (reData.containsKey("pickerKey")) {
+//                                        String pickerKey = reData.get("pickerKey") + "," + key + "__" + tabData[1];
+//                                        reData.put("pickerKey", pickerKey);
+//                                    } else {
+//                                        reData.put("pickerKey", key + "__" + tabData[1]);
+//                                    }
+//                                    String sql = tabData[0];
+//                                    sql = sql.replaceAll("\\[", "['");
+//                                    sql = sql.replaceAll("]", "']");
+//                                    sql = sql.replaceAll("000Z,", "000Z',");
+//                                    sql = sql.replaceAll(", 20", ", '20");
+//                                    sql = sql.replaceAll("'", "");
+//                                    reData.put(key + "__" + tabData[1], sql);
+//                                } else if (tabVal.indexOf("T") >= 0 && tabVal.indexOf(".000Z") >= 0) { //时间
+//                                    String[] tabData = tabVal.split("_\\^_");
+//                                    reData.put(key + "__" + tabData[1], tabData[0]);
+//                                } else if (tabVal.indexOf("☆") >= 0) {
+//                                    String[] mysql = tabVal.split("☆");
+//                                    for (String data : mysql) {
+//                                        String[] tabData = data.split("_\\^_");
+//                                        reData.put(key + "__" + tabData[1], tabData[0]);
+//                                    }
+//                                } else if (tabVal.indexOf("_^_") >= 0) { //数组处理方式
+//                                    String[] tabData = tabVal.split("_\\^_");
+//                                    if (StringUtils.isNotEmpty(tabData[0])) {
+//                                        if (tabVal.contains("[") && tabVal.contains("年")) {
+//                                            String[] strings = StringUtils.strip(tabData[0], "[]").split(",");
+//                                            reData.put(key + "__" + tabData[1], strings);
+//                                        }
+//                                        if (tabVal.contains("[") && tabVal.contains("]") && tabVal.indexOf(",") >= 0) {
+//                                            String[] strings = StringUtils.strip(tabData[0], "[]").split(",");
+//                                            reData.put(key + "__" + tabData[1], strings);
+//                                        } else {
+//                                            if (tabVal.contains("[") && tabVal.contains("]")) {
+//                                                String[] strings = new String[]{tabData[0].replaceAll("\\[","").replaceAll("]","")};
+//                                                reData.put(key + "__" + tabData[1],strings);
+//                                            } else {
+//                                                reData.put(key + "__" + tabData[1], tabData[0]);
+//                                            }
+//                                        }
+//                                    }
+//                                } else {
+//                                    reData.put(key, tabVal);
+//                                }
+//                            }
+//                        }
+//
+//                        //移除id和p_key_id
+//                        reData.remove("p_key_id");
+//                        reData.remove("classify");
+//                        reData.remove("contractId");
+//                        reData.remove("pkeyId");
+//                        reData.remove("projectId");
+//
+//                    }
+//                    if (reData.size() > 0) {
+//                        resultMapList.add(reData);
+//                    }
+//                } else {
+//                    Map<String, Object> reData2 = new HashMap<>();
+//                    //获取默认值
+//
+//                }
+//            }
+//        } else {
+//            // 匹配关联
+//            Map<String, Object> reData = new HashMap<>();
+//            try {
+//                if (tableNode2.getHtmlUrl() != null) {
+//                    InputStream inputStreamByUrl = FileUtils.getInputStreamByUrl(tableNode2.getHtmlUrl());
+//                    String htmlString = IoUtil.readToString(inputStreamByUrl);
+//                    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 jltit = doc.select("el-input[placeholder~=监理机构.*]");
+//                    jltitle.addAll(jltit);
+//
+//                    Elements bhtitle = doc.select("el-input[placeholder~=^编号]");
+//                    Elements bhtitle1 = doc.select("el-input[placeholder~=合同编号.*]");
+//                    bhtitle.addAll(bhtitle1);
+//
+//
+//                    Elements xmtitle = doc.select("el-input[placeholder~=^项目名称]");
+//
+//                    // 日期默认值
+//                    Elements dateTitle = doc.select("el-date-picker[placeholder~=日期]");
+//
+//
+//                    /**
+//                     * 承包单位 承包单位、施工单位:引用施工单位名称 ,
+//                     * 监理单位:引用监理单位名称
+//                     * 合同段、所属建设项目(合同段):引用合同段编号
+//                     *
+//                     * 施工单位:施工单位 和 安装单位
+//                     *
+//                     */
+//                    ContractInfo contractInfo = contractInfoService.getById(contractId);
+//                    // 施工单位名称
+//                    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 (htdtitle.size() >= 1) {
+//                        for (Element element : htdtitle) {
+//                            int trindex = Integer.parseInt(element.attr("trindex"));
+//                            if (trindex <= 8) {
+//                                reData.put(element.attr("keyName"), contractInfo.getContractNumber());
+//                            }
+//                        }
+//                    }
+//                    // 监理单位名称
+//                    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());
+//                            }
+//                        }
+//                    }
+//
+//                    // 项目名称
+//                    if (xmtitle.size() >= 1) {
+//                        for (Element element : xmtitle) {
+//                            int trindex = Integer.parseInt(element.attr("trindex"));
+//                            if (trindex <= 6) {
+//                                ProjectInfo projectInfo = projectInfoService.getById(tableNode2.getProjectId());
+//                                reData.put(element.attr("keyName"), projectInfo.getProjectName());
+//                            }
+//                        }
+//                    }
+//
+//                    //日期默认
+//                    if (dateTitle.size() >= 1) {
+//                        for (Element element : dateTitle) {
+//                            int trindex = Integer.parseInt(element.attr("trindex"));
+//                            if (trindex <= 10) {
+//                                reData.put(element.attr("keyName"), recordTime);
+//                            }
+//                        }
+//                    }
+//
+//
+//                    // 添加默认值
+//                    Elements elements = doc.getElementsByAttribute("defText");
+//                    if (Func.isNotEmpty(elements) && elements.size() >= 1) {
+//                        for (Element eleme : elements) {
+//                            String id = Func.isNull(eleme.attr("id")) ? eleme.attr("keyname") : eleme.attr("id");
+//                            if (Func.isNotEmpty(id)) {
+//                                reData.put(id, eleme.attr("defText"));
+//                            }
+//                        }
+//                    }
+//                }
+//            } catch (Exception e) {
+//                e.printStackTrace();
+//            }
+//            if (reData.size() > 0) {
+//                resultMapList.add(reData);
+//            }
+//        }
+//        return R.data(resultMapList);
+//    }
 
+    public R<List<Map<String, Object>>> getTheLogBusinessData(
+            List<String> theLogIds, String nodePrimaryKeyId, String recordTime, String contractId) {
+        List<Map<String, Object>> resultMapList = new ArrayList<>();
+        if (CollUtil.isEmpty(theLogIds)) {
+            return R.data(resultMapList);
+        }
+
+        // ========================= 1. 批量获取 dataId(替代逐个查询 ContractLog)=========================
+        // 批量查询 ContractLog,避免循环调用客户端
+        List<ContractLog> contractLogs = this.contractLogClient.queryContractLogByIds1(theLogIds);
+        if (CollUtil.isEmpty(contractLogs)) {
+            return R.data(resultMapList);
+        }
+        // 映射:logId -> dataId(用于后续填充 logId2)
+        Map<String, String> logIdToDataIdMap = contractLogs.stream()
+                .filter(cl -> cl.getDataId() != null)
+                .collect(Collectors.toMap(
+                        cl -> cl.getId().toString(),
+                        cl -> cl.getDataId().toString(),
+                        (k1, k2) -> k1 // 去重(若有重复logId)
+                ));
+        List<String> dataIds = new ArrayList<>(logIdToDataIdMap.values());
+        if (CollUtil.isEmpty(dataIds)) {
+            return R.data(resultMapList);
+        }
+        String logId2 = contractLogs.get(0).getId().toString(); // 取第一个logId作为默认
+
+        // ========================= 2. 一次性查询 Wbs 节点(仅1次)=========================
         WbsTreePrivate node;
         WbsTreePrivate tableNode2;
-        try{
-            node = this.wbsTreePrivateService.getOne(Wrappers.<WbsTreePrivate>lambdaQuery().eq(WbsTreePrivate::getPKeyId, nodePrimaryKeyId));
-            tableNode2= this.wbsTreePrivateService.getOne(Wrappers.<WbsTreePrivate>lambdaQuery()
-                .eq(WbsTreePrivate::getParentId, node.getId()).eq(WbsTreePrivate::getProjectId, node.getProjectId()));
+        try {
+            node = this.wbsTreePrivateService.getOne(
+                    Wrappers.<WbsTreePrivate>lambdaQuery().eq(WbsTreePrivate::getPKeyId, nodePrimaryKeyId)
+            );
+            if (node == null) {
+                throw new ServiceException("未找到Wbs节点");
+            }
+            tableNode2 = this.wbsTreePrivateService.getOne(
+                    Wrappers.<WbsTreePrivate>lambdaQuery()
+                            .eq(WbsTreePrivate::getParentId, node.getId())
+                            .eq(WbsTreePrivate::getProjectId, node.getProjectId())
+            );
+            if (tableNode2 == null) {
+                throw new ServiceException("未找到子Wbs节点");
+            }
         } catch (Exception e) {
-            throw new ServiceException("表单重复,请确认表单");
+            throw new ServiceException("表单重复,请确认表单:" + e.getMessage());
+        }
+        String tabName = tableNode2.getInitTableName();
+        if (StrUtil.isEmpty(tabName)) {
+            return R.fail("实体表名称为空");
         }
-        if (StringUtils.isNotEmpty(dataIds)) {
-            if (dataIds.startsWith(",")) {
-                dataIds = dataIds.substring(1);
-            }
-            for (String dataId : dataIds.split(",")) {
-                Map<String, Object> reData = new HashMap<>();
-                reData.put("", logId2);
-                //检查实体表是否存在
-                String tabName = tableNode2.getInitTableName();
-                String isExitSql = " select * from information_schema.TABLES where TABLE_NAME='" + tabName + "'";
-
-                List<Map<String, Object>> tabList = this.jdbcTemplate.queryForList(isExitSql);
-                if (tabList.size() <= 0) {
-                    return R.fail("无实体表对应");
-                }
-
-                //查询数据
-                String querySql = "SELECT * FROM " + tabName + " WHERE id = " + dataId + " and group_id = " + tableNode2.getPKeyId();
-
-                List<Map<String, Object>> businessDataMap = this.jdbcTemplate.queryForList(querySql);
-
-                if (businessDataMap.size() > 0) {
-                    DataStructureFormatUtils.parseDataByKey(businessDataMap);
-                    // 匹配关联
-                    try {
-                        if (tableNode2.getHtmlUrl() != null) {
-                            InputStream inputStreamByUrl = FileUtils.getInputStreamByUrl(tableNode2.getHtmlUrl());
-                            String htmlString = IoUtil.readToString(inputStreamByUrl);
-                            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~=^项目名称]");
-
-
-                            /**
-                             * 承包单位 承包单位、施工单位:引用施工单位名称 ,
-                             * 监理单位:引用监理单位名称
-                             * 合同段、所属建设项目(合同段):引用合同段编号
-                             *
-                             * 施工单位:施工单位 和 安装单位
-                             *
-                             */
-                            ContractInfo contractInfo = contractInfoService.getById(contractId);
-                            // 施工单位名称
-                            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 (htdtitle.size() >= 1) {
-                                for (Element element : htdtitle) {
-                                    int trindex = Integer.parseInt(element.attr("trindex"));
-                                    if (trindex <= 8) {
-                                        reData.put(element.attr("keyName"), contractInfo.getContractNumber());
-                                    }
-                                }
-                            }
-                            // 监理单位名称
-                            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());
-                                    }
-                                }
-                            }
-
-                            // 项目名称
-                            if (xmtitle.size() >= 1) {
-                                for (Element element : xmtitle) {
-                                    int trindex = Integer.parseInt(element.attr("trindex"));
-                                    if (trindex <= 6) {
-                                        ProjectInfo projectInfo = projectInfoService.getById(tableNode2.getProjectId());
-                                        reData.put(element.attr("keyName"), projectInfo.getProjectName());
-
-                                    }
-                                }
-                            }
-
-                            // 日期默认值
-                            Elements dateTitle = doc.select("el-date-picker[placeholder~=日期]");
-                            //日期默认
-                            if (dateTitle.size() >= 1) {
-                                for (Element element : dateTitle) {
-                                    int trindex = Integer.parseInt(element.attr("trindex"));
-                                    if (trindex <= 10) {
-                                        reData.put(element.attr("keyName"), recordTime);
-                                    }
-                                }
-                            }
 
-                            // 添加默认值
-                            Elements elements = doc.getElementsByAttribute("defText");
-                            if (Func.isNotEmpty(elements) && elements.size() >= 1) {
-                                for (Element eleme : elements) {
-                                    String id = Func.isNull(eleme.attr("id")) ? eleme.attr("keyname") : eleme.attr("id");
-                                    if (Func.isNotEmpty(id)) {
-                                        reData.put(id, eleme.attr("defText"));
-                                    }
-                                }
-                            }
-                        }
-                    } catch (Exception e) {
-                        e.printStackTrace();
-                    }
-                    for (Map<String, Object> mysqlData : businessDataMap) {
-                        String querySqlx = "SELECT tree_primary_key_id as primaryKeyId,title as path from u_contract_log_wbs where  business_id ='" + dataId + "' and is_deleted = 0";
-                        List<Map<String, Object>> businessDat = this.jdbcTemplate.queryForList(querySqlx);
-                        reData.put("linkTabIds", businessDat);
-                        for (String key : mysqlData.keySet()) {
-                            String tabVal = mysqlData.get(key) + "";
-                            // 时间段处理
-                            if (StringUtils.isNotEmpty(tabVal) && !tabVal.equals("null")) {
-                                if (tabVal.indexOf("T") >= 0 && tabVal.indexOf(".000Z]") >= 0) {
-                                    String[] tabData = tabVal.split("_\\^_");
-                                    if (reData.containsKey("pickerKey")) {
-                                        String pickerKey = reData.get("pickerKey") + "," + key + "__" + tabData[1];
-                                        reData.put("pickerKey", pickerKey);
-                                    } else {
-                                        reData.put("pickerKey", key + "__" + tabData[1]);
-                                    }
-                                    String sql = tabData[0];
-                                    sql = sql.replaceAll("\\[", "['");
-                                    sql = sql.replaceAll("]", "']");
-                                    sql = sql.replaceAll("000Z,", "000Z',");
-                                    sql = sql.replaceAll(", 20", ", '20");
-                                    sql = sql.replaceAll("'", "");
-                                    reData.put(key + "__" + tabData[1], sql);
-                                } else if (tabVal.indexOf("T") >= 0 && tabVal.indexOf(".000Z") >= 0) { //时间
-                                    String[] tabData = tabVal.split("_\\^_");
-                                    reData.put(key + "__" + tabData[1], tabData[0]);
-                                } else if (tabVal.indexOf("☆") >= 0) {
-                                    String[] mysql = tabVal.split("☆");
-                                    for (String data : mysql) {
-                                        String[] tabData = data.split("_\\^_");
-                                        reData.put(key + "__" + tabData[1], tabData[0]);
-                                    }
-                                } else if (tabVal.indexOf("_^_") >= 0) { //数组处理方式
-                                    String[] tabData = tabVal.split("_\\^_");
-                                    if (StringUtils.isNotEmpty(tabData[0])) {
-                                        if (tabVal.contains("[") && tabVal.contains("年")) {
-                                            String[] strings = StringUtils.strip(tabData[0], "[]").split(",");
-                                            reData.put(key + "__" + tabData[1], strings);
-                                        }
-                                        if (tabVal.contains("[") && tabVal.contains("]") && tabVal.indexOf(",") >= 0) {
-                                            String[] strings = StringUtils.strip(tabData[0], "[]").split(",");
-                                            reData.put(key + "__" + tabData[1], strings);
-                                        } else {
-                                            if (tabVal.contains("[") && tabVal.contains("]")) {
-                                                String[] strings = new String[]{tabData[0].replaceAll("\\[","").replaceAll("]","")};
-                                                reData.put(key + "__" + tabData[1],strings);
-                                            } else {
-                                                reData.put(key + "__" + tabData[1], tabData[0]);
-                                            }
-                                        }
-                                    }
-                                } else {
-                                    reData.put(key, tabVal);
-                                }
-                            }
-                        }
+        // ========================= 3. 检查实体表存在(参数化查询,避免SQL注入)=========================
+        String checkTableSql = "SELECT 1 FROM information_schema.TABLES WHERE TABLE_NAME = ?";
+        List<Map<String, Object>> tabExist = this.jdbcTemplate.queryForList(checkTableSql, tabName);
+        if (CollUtil.isEmpty(tabExist)) {
+            return R.fail("无实体表对应:" + tabName);
+        }
 
-                        //移除id和p_key_id
-                        reData.remove("p_key_id");
-                        reData.remove("classify");
-                        reData.remove("contractId");
-                        reData.remove("pkeyId");
-                        reData.remove("projectId");
+        // ========================= 4. 预加载HTML模板(仅1次下载+解析)=========================
+        Document htmlDoc = null;
+        if (StrUtil.isNotEmpty(tableNode2.getHtmlUrl())) {
+            try (InputStream inputStream = FileUtils.getInputStreamByUrl(tableNode2.getHtmlUrl())) {
+                String htmlString = IoUtil.readToString(inputStream, StandardCharsets.UTF_8);
+                htmlDoc = Jsoup.parse(htmlString);
+            } catch (Exception e) {
+                System.out.println("HTML模板加载失败"+e);;
+            }
+        }
 
-                    }
-                    if (reData.size() > 0) {
-                        resultMapList.add(reData);
-                    }
-                } else {
-                    Map<String, Object> reData2 = new HashMap<>();
-                    //获取默认值
+        // ========================= 5. 预查询公共数据(仅1次)=========================
+        ContractInfo contractInfo = contractInfoService.getById(contractId);
+        ProjectInfo projectInfo = projectInfoService.getById(tableNode2.getProjectId());
+        // 预加载默认值(承包单位、日期等,仅解析1次DOM)
+        Map<String, String> defaultData = preloadDefaultData(htmlDoc, contractInfo, projectInfo, recordTime);
 
+        // ========================= 6. 批量查询业务数据(1次查询替代N次,参数化避免注入)=========================
+        // 6.1 批量查询主业务数据
+        String batchBizSql = "SELECT * FROM " + tabName + " WHERE id IN (?) AND group_id = ?";
+        List<Map<String, Object>> businessDataList = this.jdbcTemplate.queryForList(
+                batchBizSql,
+                String.join(",", dataIds),
+                tableNode2.getPKeyId()
+        );
+        DataStructureFormatUtils.parseDataByKey(businessDataList);
+
+        // 6.2 批量查询关联WBS数据(1次查询替代N次)
+        String batchWbsSql = "SELECT tree_primary_key_id as primaryKeyId, title as path, business_id " +
+                "FROM u_contract_log_wbs WHERE business_id IN (?) AND is_deleted = 0";
+        List<Map<String, Object>> wbsDataList = this.jdbcTemplate.queryForList(
+                batchWbsSql,
+                String.join(",", dataIds)
+        );
+        Map<String, List<Map<String, Object>>> businessIdToWbsMap = wbsDataList.stream()
+                .collect(Collectors.groupingBy(map -> map.get("business_id").toString()));
+
+        // ========================= 7. 数据组装(内存操作,无额外IO)=========================
+        for (Map<String, Object> mysqlData : businessDataList) {
+            String dataId = mysqlData.get("id").toString();
+            // 找到对应的logId(用于填充logId2)
+            String currentLogId = logIdToDataIdMap.entrySet().stream()
+                    .filter(entry -> entry.getValue().equals(dataId))
+                    .map(Map.Entry::getKey)
+                    .findFirst()
+                    .orElse(logId2);
+
+            Map<String, Object> reData = new HashMap<>(defaultData);
+            reData.put("", currentLogId); // 填充logId2
+            // 关联WBS数据
+            reData.put("linkTabIds", businessIdToWbsMap.getOrDefault(dataId, Collections.emptyList()));
+
+            // 处理字段值(时间、数组、特殊格式)
+            for (Map.Entry<String, Object> entry : mysqlData.entrySet()) {
+                String key = entry.getKey();
+                String tabVal = entry.getValue()==null? "":entry.getValue().toString();
+                if (StrUtil.isEmpty(tabVal) || "null".equals(tabVal)) {
+                    continue;
                 }
+                handleFieldValue(reData, key, tabVal);
             }
-        } else {
-            // 匹配关联
-            Map<String, Object> reData = new HashMap<>();
-            try {
-                if (tableNode2.getHtmlUrl() != null) {
-                    InputStream inputStreamByUrl = FileUtils.getInputStreamByUrl(tableNode2.getHtmlUrl());
-                    String htmlString = IoUtil.readToString(inputStreamByUrl);
-                    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 jltit = doc.select("el-input[placeholder~=监理机构.*]");
-                    jltitle.addAll(jltit);
-
-                    Elements bhtitle = doc.select("el-input[placeholder~=^编号]");
-                    Elements bhtitle1 = doc.select("el-input[placeholder~=合同编号.*]");
-                    bhtitle.addAll(bhtitle1);
-
-
-                    Elements xmtitle = doc.select("el-input[placeholder~=^项目名称]");
-
-                    // 日期默认值
-                    Elements dateTitle = doc.select("el-date-picker[placeholder~=日期]");
-
-
-                    /**
-                     * 承包单位 承包单位、施工单位:引用施工单位名称 ,
-                     * 监理单位:引用监理单位名称
-                     * 合同段、所属建设项目(合同段):引用合同段编号
-                     *
-                     * 施工单位:施工单位 和 安装单位
-                     *
-                     */
-                    ContractInfo contractInfo = contractInfoService.getById(contractId);
-                    // 施工单位名称
-                    if (dwtitle.size() >= 1) {
-                        int y = Integer.parseInt(dwtitle.attr("trindex"));
-                        if (y <= 10) {
-                            reData.put(dwtitle.attr("keyName"), contractInfo.getConstructionUnitName());
-                        }
+            // 移除无用字段
+            reData.remove("p_key_id");
+            reData.remove("classify");
+            reData.remove("contractId");
+            reData.remove("pkeyId");
+            reData.remove("projectId");
 
-                    }
-                    if (sgtitle.size() >= 1) {
-                        int y = Integer.parseInt(sgtitle.attr("trindex"));
-                        if (y <= 10) {
-                            reData.put(sgtitle.attr("keyName"), contractInfo.getConstructionUnitName());
-                        }
-                    }
+            resultMapList.add(reData);
+        }
 
-                    // 合同段名称
-                    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());
-                            }
-                        }
-                    }
-                    // 监理单位名称
-                    if (jltitle.size() >= 1) {
-                        for (Element element : jltitle) {
-                            int trindex = Integer.parseInt(element.attr("trindex"));
-                            if (trindex <= 10) {
+        // 补充无业务数据的默认值(若需要)
+        if (CollUtil.isEmpty(businessDataList)) {
+            Map<String, Object> defaultReData = new HashMap<>(defaultData);
+            defaultReData.put("", logId2);
+            resultMapList.add(defaultReData);
+        }
 
-                                reData.put(element.attr("keyName"), contractInfo.getSupervisionUnitName());
-                            }
-                        }
-                    }
+        return R.data(resultMapList);
+    }
 
-                    // 项目名称
-                    if (xmtitle.size() >= 1) {
-                        for (Element element : xmtitle) {
-                            int trindex = Integer.parseInt(element.attr("trindex"));
-                            if (trindex <= 6) {
-                                ProjectInfo projectInfo = projectInfoService.getById(tableNode2.getProjectId());
-                                reData.put(element.attr("keyName"), projectInfo.getProjectName());
-                            }
-                        }
-                    }
+    /**
+     * 预加载默认值(消除重复DOM解析)
+     */
+    private Map<String, String> preloadDefaultData(Document doc, ContractInfo contractInfo, ProjectInfo projectInfo, String recordTime) {
+        Map<String, String> defaultData = new HashMap<>();
+        if (doc == null) {
+            return defaultData;
+        }
+
+        // 1. 承包单位/施工单位
+        Elements dwtitle = doc.select("el-input[placeholder~=.*承包单位]");
+        Elements sgtitle = doc.select("el-input[placeholder~=^施工单位],el-input[placeholder=安装单位]");
+        addDefaultValue(defaultData, dwtitle, contractInfo != null ? contractInfo.getConstructionUnitName() : "", 10);
+        addDefaultValue(defaultData, sgtitle, contractInfo != null ? contractInfo.getConstructionUnitName() : "", 10);
+
+        // 2. 合同段/合同号
+        Elements htdtitle = doc.select("el-input[placeholder~=.*合同号.*],el-input[placeholder~=合同段.*]");
+        addDefaultValue(defaultData, htdtitle, contractInfo != null ? contractInfo.getContractNumber() : "", 8);
+
+        // 3. 监理单位
+        Elements jltitle = doc.select("el-input[placeholder~=监理单位.*],el-input[placeholder~=监理机构.*]");
+        addDefaultValue(defaultData, jltitle, contractInfo != null ? contractInfo.getSupervisionUnitName() : "", 10);
+
+        // 4. 项目名称
+        Elements xmtitle = doc.select("el-input[placeholder~=^项目名称]");
+        addDefaultValue(defaultData, xmtitle, projectInfo != null ? projectInfo.getProjectName() : "", 6);
+
+        // 5. 日期默认值
+        Elements dateTitle = doc.select("el-date-picker[placeholder~=日期]");
+        addDefaultValue(defaultData, dateTitle, recordTime, 10);
+
+        // 6. 自定义默认值
+        Elements defTextElements = doc.getElementsByAttribute("defText");
+        for (Element ele : defTextElements) {
+            String id = StrUtil.isEmpty(ele.attr("id")) ? ele.attr("keyname") : ele.attr("id");
+            if (StrUtil.isNotEmpty(id)) {
+                defaultData.put(id, ele.attr("defText"));
+            }
+        }
 
-                    //日期默认
-                    if (dateTitle.size() >= 1) {
-                        for (Element element : dateTitle) {
-                            int trindex = Integer.parseInt(element.attr("trindex"));
-                            if (trindex <= 10) {
-                                reData.put(element.attr("keyName"), recordTime);
-                            }
-                        }
-                    }
+        return defaultData;
+    }
 
+    /**
+     * 统一添加默认值(消除重复循环)
+     */
+    private void addDefaultValue(Map<String, String> defaultData, Elements elements, String value, int maxTrIndex) {
+        if (CollUtil.isEmpty(elements) || StrUtil.isEmpty(value)) {
+            return;
+        }
+        for (Element ele : elements) {
+            int trindex = Func.toInt(ele.attr("trindex"), 0);
+            if (trindex <= maxTrIndex) {
+                defaultData.put(ele.attr("keyName"), value);
+            }
+        }
+    }
 
-                    // 添加默认值
-                    Elements elements = doc.getElementsByAttribute("defText");
-                    if (Func.isNotEmpty(elements) && elements.size() >= 1) {
-                        for (Element eleme : elements) {
-                            String id = Func.isNull(eleme.attr("id")) ? eleme.attr("keyname") : eleme.attr("id");
-                            if (Func.isNotEmpty(id)) {
-                                reData.put(id, eleme.attr("defText"));
-                            }
-                        }
-                    }
-                }
-            } catch (Exception e) {
-                e.printStackTrace();
+    /**
+     * 统一处理字段值格式(时间、数组、特殊标识)
+     */
+    private void handleFieldValue(Map<String, Object> reData, String key, String tabVal) {
+        if (tabVal.contains("T") && tabVal.contains(".000Z]")) {
+            String[] tabData = tabVal.split("_\\^_");
+            if (tabData.length < 2) return;
+            String pickerKey = reData.get("pickerKey")==null?"":reData.get("pickerKey").toString();
+            reData.put("pickerKey", StrUtil.isEmpty(pickerKey) ? key + "__" + tabData[1] : pickerKey + "," + key + "__" + tabData[1]);
+            String sql = tabData[0].replaceAll("\\[", "['")
+                    .replaceAll("]", "']")
+                    .replaceAll("000Z,", "000Z',")
+                    .replaceAll(", 20", ", '20")
+                    .replaceAll("'", "");
+            reData.put(key + "__" + tabData[1], sql);
+        } else if (tabVal.contains("T") && tabVal.contains(".000Z")) {
+            String[] tabData = tabVal.split("_\\^_");
+            if (tabData.length < 2) return;
+            reData.put(key + "__" + tabData[1], tabData[0]);
+        } else if (tabVal.contains("☆")) {
+            String[] mysql = tabVal.split("☆");
+            for (String data : mysql) {
+                String[] tabData = data.split("_\\^_");
+                if (tabData.length < 2) continue;
+                reData.put(key + "__" + tabData[1], tabData[0]);
             }
-            if (reData.size() > 0) {
-                resultMapList.add(reData);
+        } else if (tabVal.contains("_^_")) {
+            String[] tabData = tabVal.split("_\\^_");
+            if (tabData.length < 2 || StrUtil.isEmpty(tabData[0])) return;
+            if (tabVal.contains("[") && (tabVal.contains("年") || tabVal.contains(","))) {
+                String[] strings = StringUtils.strip(tabData[0], "[]").split(",");
+                reData.put(key + "__" + tabData[1], strings);
+            } else if (tabVal.contains("[")) {
+                reData.put(key + "__" + tabData[1], new String[]{tabData[0].replaceAll("\\[|]", "")});
+            } else {
+                reData.put(key + "__" + tabData[1], tabData[0]);
             }
+        } else {
+            reData.put(key, tabVal);
         }
-        return R.data(resultMapList);
     }
-
     /**
      * 获取新增时的表头数据
      * @param theLogId
@@ -3835,7 +4078,7 @@ public class ExcelTabController extends BladeController {
                 throw new ServiceException("数据构造失败");
             }
             //返回当前复制的表数据
-            return this.getTheLogBusinessData(StringUtils.join(logIds, ","), nodePrimaryKeyId, currentTime, contractId);
+            return this.getTheLogBusinessData(logIds, nodePrimaryKeyId, currentTime, contractId);
         }
         return null;
     }