Browse Source

Merge branch 'test-merge' of http://219.151.181.73:3000/zhuwei/bladex into test-merge

lvy 15 hours ago
parent
commit
b0562ae595
13 changed files with 276 additions and 241 deletions
  1. 1 1
      blade-ops/blade-resource/src/main/java/org/springblade/resource/builder/oss/OssBuilder.java
  2. 5 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/ExceTabTreVO.java
  3. 1 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ArchiveTreeContractController.java
  4. 166 173
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/WbsTreePrivateController.java
  5. 2 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/ArchiveTreeContractMapper.java
  6. 8 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/ArchiveTreeContractMapper.xml
  7. 1 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/ExcelTabMapper.xml
  8. 1 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsTreePrivateMapper.java
  9. 32 39
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsTreePrivateMapper.xml
  10. 49 9
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ArchiveTreeContractServiceImpl.java
  11. 3 3
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ExcelTabServiceImpl.java
  12. 2 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsFormElementServiceImpl.java
  13. 5 13
      blade-service/blade-user/src/main/java/org/springblade/system/user/service/impl/UserServiceImpl.java

+ 1 - 1
blade-ops/blade-resource/src/main/java/org/springblade/resource/builder/oss/OssBuilder.java

@@ -98,7 +98,7 @@ public class OssBuilder {
                 oss.setEndpoint("https://xinan1.zos.ctyun.cn");
             }
         }
-		oss.setEndpoint("https://xinan1.zos.ctyun.cn");
+		//oss.setEndpoint("https://xinan1.zos.ctyun.cn");
 		System.out.println("oss111="+oss.getEndpoint());
 		Oss ossCached = ossPool.get(tenantId);
 		OssTemplate template = templatePool.get(tenantId);

+ 5 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/ExceTabTreVO.java

@@ -85,4 +85,9 @@ public class ExceTabTreVO extends ExcelTab implements INode<ExceTabTreVO> {
      */
     private String deptCategoryName;
 
+    /**
+     * 元素表名称
+     */
+    private String tabChName;
+
 }

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

@@ -249,7 +249,7 @@ public class ArchiveTreeContractController extends BladeController {
     @ApiOperationSupport(order = 7)
     @ApiOperation(value = "逻辑删除", notes = "传入id")
     public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String id) {
-        List<ArchiveTreeContract> archiveTrees = archiveTreeContractService.selectByParentIdOrId(id);
+//        List<ArchiveTreeContract> archiveTrees = archiveTreeContractService.selectByParentIdOrId(id);
 //		archiveTrees.forEach(archiveTree -> {
 //			if (archiveTree.getParentId() == Long.parseLong(id)) {
 //				throw new ServiceException("当前节点下存在子节点,删除失败");

+ 166 - 173
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/WbsTreePrivateController.java

@@ -317,208 +317,201 @@ public class WbsTreePrivateController extends BladeController {
         return R.fail("操作失败");
     }
 
+//
+    /**
+     * 查询当前节点下所有表单(根据节点ID查询当前表单)
+     */
     @GetMapping("/get-node-tables")
     @ApiOperationSupport(order = 3)
     @ApiOperation(value = "查询当前节点下所有元素表", notes = "传入父节点id、wbsId、projectId")
-    public R<List<WbsNodeTableVO>> findNodeTableByCondition(
-            @RequestParam("parentId") String parentId,
-            @RequestParam("wbsId") String wbsId,
-            @RequestParam("projectId") String projectId) {
+    public R<List<WbsNodeTableVO>> findNodeTableByCondition(@RequestParam("parentId") String parentId,
+                                                            @RequestParam("wbsId") String wbsId,
+                                                            @RequestParam("projectId") String projectId) {
         List<WbsNodeTableVO> rs = wbsTreePrivateService.selectByNodeTable(parentId, wbsId, projectId);
-        // 仅处理isLinkTable标记(SQL无法处理的逻辑)
-        if (CollectionUtil.isNotEmpty(rs)) {
-            rs.forEach(r -> {
+        if (rs.size() > 0) {
+            /*表单对应的initTableIdMaps*/
+            Set<String> ids = rs.stream().map(WbsNodeTableVO::getId).collect(Collectors.toSet());
+            Map<Long, Long> initTableIdMaps = wbsTreeService.getBaseMapper().selectList(Wrappers.<WbsTree>lambdaQuery()
+                            .select(WbsTree::getInitTableId, WbsTree::getId)
+                            .in(WbsTree::getId, ids))
+                    .stream()
+                    .filter(wbsTree -> wbsTree.getId() != null && wbsTree.getInitTableId() != null)
+                    .collect(Collectors.toMap(WbsTree::getId, WbsTree::getInitTableId));
+
+            /*元素FidSet,统计数量*/
+            Set<Long> formElementFids = new HashSet<>();
+
+            /*initTabId赋值*/
+            for (WbsNodeTableVO r : rs) {
                 if (StringUtil.isBlank(r.getHtmlUrl())) {
                     r.setIsLinkTable(1);
                 }
-            });
-            return R.data(rs);
-        }
-        return R.fail(404, "未查询到数据"); // 200是成功码,失败用404更规范
-    }
+                if (StringUtil.isBlank(r.getInitTableId())) {
 
-    @GetMapping("/get-group-node-tables")
-    @ApiOperationSupport(order = 3)
-    @ApiOperation(value = "查询当前节点下所有元素表并分类", notes = "传入父节点id、wbsId、projectId")
-    public R<List<WbsTreePrivateTableVO>> findAndGroupNodeTableByCondition(
-            @RequestParam("parentId") String parentId,
-            @RequestParam("wbsId") String wbsId,
-            @RequestParam("projectId") String projectId) {
-        // 2. 获取基础数据(已优化SQL,无冗余)
-        R<List<WbsNodeTableVO>> r = findNodeTableByCondition(parentId, wbsId, projectId);
-        List<WbsNodeTableVO> data = r.getData();
-        if (CollectionUtil.isEmpty(data)) {
-            return R.fail(404, "未查询到数据");
-        }
+                    /*提出去,不for循环查询
+                    WbsTree wbsTree = wbsTreeService.getById(r.getId());*/
 
-        // 3. 批量处理HTML解析(核心优化:批量查询→并行处理)
-        processHtmlElementsBatch(data);
+                    Long initTabId = initTableIdMaps.getOrDefault(Long.parseLong(r.getId()), null);
 
-        // 4. 简化分组逻辑(减少重复计算)
-        List<WbsTreePrivateTableVO> list = groupNodeTables(data);
+                    if (initTabId != null) {
+                        r.setInitTableId(String.valueOf(initTabId));
 
-        return R.data(list);
-    }
+                        formElementFids.add(initTabId);
 
-    /**
-     * 批量处理HTML元素校验(解决N+1查询+串行解析)
-     */
-    private void processHtmlElementsBatch(List<WbsNodeTableVO> data) {
-        // 步骤1:批量收集需要查询的initTableId和pKeyId(避免循环内查询)
-        Map<String, WbsNodeTableVO> initTableId2Vo = new HashMap<>();
-        Set<String> pKeyIds = new HashSet<>();
-        for (WbsNodeTableVO f : data) {
-            String htmlUrl = f.getHtmlUrl();
-            String initTableId = f.getInitTableId();
-            if (StringUtil.isNotBlank(htmlUrl) && StringUtils.isNotEmpty(initTableId)) {
-                initTableId2Vo.put(initTableId, f);
-                pKeyIds.add(f.getPKeyId()+"");
-            }
-        }
-        if (initTableId2Vo.isEmpty()) {
-            return;
-        }
+                        /*提出去,不for循环查询
+                        r.setElementTotal(Math.toIntExact(wbsFormElementService.count(
+                                new LambdaQueryWrapper<WbsFormElement>().eq(WbsFormElement::getFId, r.getInitTableId()))));*/
 
-        // 步骤2:批量查询wbsFormElement(替代循环内N+1查询)
-        List<WbsFormElement> wbsFormElements = wbsFormElementService.getBaseMapper().selectList(
-                Wrappers.<WbsFormElement>lambdaQuery()
-                        .in(WbsFormElement::getFId, initTableId2Vo.keySet())
-                        .eq(WbsFormElement::getIsDeleted, 0)
-        );
-        // 构建initTableId→eKey集合的映射
-        Map<String, Set<String>> initTableId2Keys = wbsFormElements.stream()
-                .collect(Collectors.groupingBy(
-                        WbsFormElement::getFId,
-                        Collectors.mapping(WbsFormElement::getEKey, Collectors.toSet())
-                ));
-
-        // 步骤3:批量获取HTML内容(建议对excelHtml结果加本地缓存,比如Caffeine)
-        Map<String, String> pKeyId2Html = new HashMap<>();
-        if (CollectionUtil.isNotEmpty(pKeyIds)) {
-            // 并行获取HTML(如果getExcelHtml是远程调用/耗时操作,并行可提升效率)
-            pKeyIds.parallelStream().forEach(pKeyId -> {
-                try {
-                    R excelHtml = excelTabController.getExcelHtml(Long.parseLong(pKeyId));
-                    if (excelHtml.isSuccess() && excelHtml.getData() != null) {
-                        pKeyId2Html.put(pKeyId, excelHtml.getData().toString());
+                    } else {
+                        r.setInitTableId("");
                     }
-                } catch (Exception e) {
-                    System.out.println("获取HTML失败,pKeyId="+pKeyId); // 增加日志,避免空catch
                 }
-            });
-        }
-
-        // 步骤4:并行解析HTML(CPU密集型操作,并行提升效率)
-        data.parallelStream().forEach(f -> {
-            String htmlUrl = f.getHtmlUrl();
-            String initTableId = f.getInitTableId();
-            if (StringUtil.isBlank(htmlUrl) || StringUtils.isEmpty(initTableId)) {
-                return;
             }
-            // 获取缓存的HTML内容
-            String htmlString = pKeyId2Html.get(f.getPKeyId());
-            if (StringUtil.isEmpty(htmlString)) {
-                return;
-            }
-            // 获取预查询的eKey集合
-            Set<String> keys = initTableId2Keys.getOrDefault(initTableId, Collections.emptySet());
 
-            // Jsoup解析(简化标签选择+批量判断)
-            Document doc = Jsoup.parse(htmlString);
-            String[] tagNames = {"el-input", "el-date-picker", "el-time-picker", "hc-form-select-search",
-                    "hc-table-form-upload", "hc-form-checkbox-group", "el-radio-group", "el-select"};
-            Elements inputs = new Elements();
-            for (String tagName : tagNames) {
-                inputs.addAll(doc.select(tagName));
-            }
+            if (formElementFids.size() > 0) {
+                /*查询所有相关的元素记录*/
+                List<WbsFormElement> wbsFormElements = wbsFormElementService.getBaseMapper().selectList(Wrappers.<WbsFormElement>lambdaQuery()
+                        .select(WbsFormElement::getFId)
+                        .in(WbsFormElement::getFId, formElementFids));
 
-            // 标记是否有错误(只要有一个标签不合法,就标记为1)
-            boolean hasError = inputs.stream().anyMatch(input -> {
-                String id = input.attr("id");
-                if (StringUtils.isEmpty(id)) {
-                    return true;
-                }
-                // 预编译分割逻辑,减少重复split(核心优化)
-                String[] idParts = id.split("__", 2); // 只分割一次
-                if (idParts.length != 2) {
-                    return true;
-                }
-                String keyPart = idParts[0];
-                String coordPart = idParts[1];
-                // 1. 检查keyPart格式:key_+数字
-                if (!keyPart.startsWith("key_") || !StringUtils.isNumber(keyPart.replace("key_", ""))) {
-                    return true;
-                }
-                // 2. 检查coordPart格式:数字_数字
-                String[] coordParts = coordPart.split("_", 2);
-                if (coordParts.length != 2 || !StringUtils.isNumber(coordParts[0]) || !StringUtils.isNumber(coordParts[1])) {
-                    return true;
-                }
-                // 3. 检查key是否存在
-                return !keys.contains(keyPart);
-            });
+                /*elementCountMap分组*/
+                Map<String, Integer> elementCountMap = wbsFormElements.stream()
+                        .collect(Collectors.groupingBy(WbsFormElement::getFId, Collectors.collectingAndThen(Collectors.counting(), Long::intValue)));
 
-            if (hasError) {
-                f.setHtmlElementError(1);
+                /*元素数量赋值*/
+                for (WbsNodeTableVO r : rs) {
+                    if (StringUtil.isNotBlank(r.getInitTableId())) {
+                        r.setElementTotal(elementCountMap.getOrDefault(r.getInitTableId(), 0));
+                    }
+                }
             }
-        });
+
+            return R.data(rs);
+        }
+        return R.fail(200, "未查询到数据");
     }
 
     /**
-     * 简化分组逻辑(减少重复判断
+     * 查询当前节点下所有表单(根据节点ID查询当前表单)
      */
-    private List<WbsTreePrivateTableVO> groupNodeTables(List<WbsNodeTableVO> data) {
+    @GetMapping("/get-group-node-tables")
+    @ApiOperationSupport(order = 3)
+    @ApiOperation(value = "查询当前节点下所有元素表并分类", notes = "传入父节点id、wbsId、projectId")
+    public R<List<WbsTreePrivateTableVO>> findAndGroupNodeTableByCondition(@RequestParam("parentId") String parentId,
+                                                                           @RequestParam("wbsId") String wbsId,
+                                                                           @RequestParam("projectId") String projectId) {
+        R<List<WbsNodeTableVO>> r = findNodeTableByCondition(parentId, wbsId, projectId);
+        List<WbsNodeTableVO> data = r.getData();
         List<WbsTreePrivateTableVO> list = new ArrayList<>();
-        Integer wbsType = data.get(0).getWbsType();
-        if (wbsType == null) {
-            list.add(new WbsTreePrivateTableVO("", data));
-            return list;
-        }
-
-        // 预定义分组规则(避免嵌套if)
-        Function<WbsNodeTableVO, Integer> groupFunction;
-        String[] titles;
-        if (wbsType == 1) {
-            // 施工方/监理方/其他分组
-            groupFunction = vo -> {
-                String tableOwner = vo.getTableOwner();
-                if (StringUtil.isNumeric(tableOwner)) {
-                    int i = Integer.parseInt(tableOwner);
-                    if (i >= 1 && i <= 3) return 1;
-                    if (i >= 4 && i <= 6) return 2;
-                }
-                return 3;
-            };
-            titles = new String[]{"施工方", "监理方", "其他"};
-        } else if (wbsType == 2) {
-            // 报告表/记录表/其他分组
-            groupFunction = vo -> {
-                String tableType = vo.getTableType();
-                if (StringUtil.isNumeric(tableType)) {
-                    int i = Integer.parseInt(tableType);
-                    if (i == 1) return 2;
-                    if (i == 2) return 1;
+        if (data != null && !data.isEmpty()) {
+            //解析html
+            data.forEach(f -> {
+                String htmlUrl = f.getHtmlUrl();
+                String initTableId = f.getInitTableId();
+                if(StringUtil.isNotBlank(htmlUrl) && StringUtils.isNotEmpty(initTableId)){
+                    //获取元素表数据
+                    List<WbsFormElement> wbsFormElements = wbsFormElementService.getBaseMapper().selectList(Wrappers.<WbsFormElement>lambdaQuery()
+                            .eq(WbsFormElement::getFId, initTableId)
+                            .eq(WbsFormElement::getIsDeleted, 0)
+                    );
+
+                    List<String> keys = wbsFormElements.stream().map(WbsFormElement::getEKey).collect(Collectors.toList());
+
+
+                    // 读取html页面信息
+                    String htmlString = "";
+                    //解析html
+                    try {
+                        R excelHtml = excelTabController.getExcelHtml(f.getPKeyId());
+                        htmlString = excelHtml.getData().toString();
+                    } catch (Exception e) {
+                    }
+                    if(StringUtil.isEmpty(htmlString)){
+                        return;
+                    }
+                    // 样式集合
+                    Document doc = Jsoup.parse(htmlString);
+                    //获取所有input标签
+                    //获取所有input标签
+                    String[] tagNames = {"el-input", "el-date-picker", "el-time-picker", "hc-form-select-search",
+                            "hc-table-form-upload", "hc-form-checkbox-group", "el-radio-group", "el-select"};
+                    Elements inputs = new Elements();
+                    for (String tagName : tagNames) {
+                        inputs.addAll(doc.select(tagName));
+                    }
+                    //判断标签是否存在id属性
+                    inputs.forEach(input -> {
+                        String id = input.attr("id");
+                        if(StringUtils.isEmpty(id)){
+                            f.setHtmlElementError(1);
+                            input.attr("htmlElementError", "1");
+                        } else {
+                            /**
+                             * 判断当前元素是否符合格式
+                             * 1、是否存在key_
+                             * 2、是否存在__
+                             * 3、key_后面是否为数字
+                             * 4、__后面是否为坐标
+                             * 5、key是否在元素库中存在
+                             */
+                            if(!id.contains("key_")
+                                    || !id.contains("__")
+                                    || !StringUtils.isNumber(id.split("__")[0].replace("key_",""))
+                                    || !id.split("__")[1].contains("_")
+                                    || !StringUtils.isNumber(id.split("__")[1].split("_")[0])
+                                    || !StringUtils.isNumber(id.split("__")[1].split("_")[1])
+                                    || !keys.contains(id.split("__")[0])
+                            ){
+                                f.setHtmlElementError(1);
+                                input.attr("htmlElementError", "1");
+                            }
+                        }
+                    });
                 }
-                return 3;
-            };
-            titles = new String[]{"报告表", "记录表", "其他"};
-        } else {
-            list.add(new WbsTreePrivateTableVO("", data));
-            return list;
-        }
-
-        // 分组(流式API简化)
-        Map<Integer, List<WbsNodeTableVO>> groupMap = data.stream()
-                .collect(Collectors.groupingBy(groupFunction));
+            });
 
-        // 构建返回列表
-        for (int i = 1; i <= 3; i++) {
-            List<WbsNodeTableVO> voList = groupMap.get(i);
-            if (CollectionUtil.isNotEmpty(voList)) {
-                list.add(new WbsTreePrivateTableVO(titles[i - 1], voList));
+            Integer wbsType = data.get(0).getWbsType();
+            Map<Integer, List<WbsNodeTableVO>> groupMap;
+            if (wbsType != null && wbsType == 1) {
+                groupMap = data.stream().collect(Collectors.groupingBy(vo -> {
+                    String tableOwner = vo.getTableOwner();
+                    if (StringUtil.isNumeric(tableOwner)) {
+                        int i = Integer.parseInt(tableOwner);
+                        if (i > 0 && i <= 3) {
+                            return 1;
+                        } else if (i > 3 && i <= 6) {
+                            return 2;
+                        }
+                    }
+                    return 3;
+                }));
+            } else if (wbsType != null && wbsType == 2) {
+                groupMap = data.stream().collect(Collectors.groupingBy(vo -> {
+                    String tableType = vo.getTableType();
+                    if (StringUtil.isNumeric(tableType)) {
+                        int i = Integer.parseInt(tableType);
+                        if (i == 1 ) {
+                            return 2;
+                        } else if (i == 2 ) {
+                            return 1;
+                        }
+                    }
+                    return 3;
+                }));
+            } else {
+                list.add(new WbsTreePrivateTableVO("", data));
+                return R.data(list);
+            }
+            String[][] titles = {{"施工方", "监理方", "其他"}, {"报告表", "记录表", "其他"}};
+            for (int i = 1; i <= 3; i++) {
+                List<WbsNodeTableVO> wbsNodeTableVOS = groupMap.get(i);
+                if (wbsNodeTableVOS != null && !wbsNodeTableVOS.isEmpty()) {
+                    list.add(new WbsTreePrivateTableVO(titles[wbsType - 1][i - 1], wbsNodeTableVOS));
+                }
             }
+            return R.data(list);
         }
-        return list;
+        return R.fail(200, "未查询到数据");
     }
 
     /**

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

@@ -192,4 +192,6 @@ public interface ArchiveTreeContractMapper extends BaseMapper<ArchiveTreeContrac
                                     @Param("parentId") Long parentId);
 
     List<ArchiveTreeContract> getArchiveTreeContractListByListOrderByTreeSort(@Param("nodeIds") List<Long> nodeIds);
+
+    void callGetChildIds(@Param("params") Map<String, Object> params);
 }

+ 8 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/ArchiveTreeContractMapper.xml

@@ -1043,4 +1043,12 @@
         </foreach>
         ORDER BY case when d.tree_sort regexp '^[a-zA-Z]' then 0 when d.tree_sort regexp '^[0-9]' then 1 else 2 end, d.tree_sort
     </select>
+    <select id="callGetChildIds" statementType="CALLABLE">
+        CALL get_archive_tree_child_ids(
+            #{params.parentId, mode=IN, jdbcType=BIGINT},
+            #{params.projectId, mode=IN, jdbcType=BIGINT},
+            #{params.tenantId, mode=IN, jdbcType=VARCHAR},
+            #{params.outIds, mode=OUT, jdbcType=VARCHAR}
+            )
+    </select>
 </mapper>

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

@@ -58,6 +58,7 @@
         dept.tab_type,
         dept.tab_id,
         info.table_owner as tableOwner,
+        info.tab_ch_name,
         (
         SELECT
         CASE WHEN count(1) > 0 THEN 1 ELSE 0 END

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

@@ -35,7 +35,7 @@ public interface WbsTreePrivateMapper extends EasyBaseMapper<WbsTreePrivate> {
 
     List<WbsTree> selectIsTable(Long tableId, String projectId);
 
-    List<WbsNodeTableVO> selectByNodeTable(@Param("parentId")String id, @Param("wbsId")String wbsId, @Param("projectId")String projectId);
+    List<WbsNodeTableVO> selectByNodeTable(String id, String wbsId, String projectId);
 
     void updateDeletedByCondition(String id, String wbsId, String projectId);
     void removeTableByPKeyIdCondition(String pKeyId, String wbsId, String projectId);

+ 32 - 39
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsTreePrivateMapper.xml

@@ -512,50 +512,43 @@
           AND project_id = #{projectId}
     </select>
     <select id="selectByNodeTable" resultType="org.springblade.manager.vo.WbsNodeTableVO">
-        SELECT
-            wt.p_key_id AS "pKeyId",
-            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
-                WHEN wt.table_type IN (2, 10) THEN 2
-                ELSE wt.table_type
-                END AS tableType,
-            wt.`status` AS isCreateTable,
-            wt.table_owner AS tableOwner,
-            wt.is_link_table,
-            wt.init_table_name,
-            -- 关联m_wbs_tree获取init_table_id,避免Java层二次查询
-            COALESCE(wt.init_table_id, wt2.init_table_id) AS initTableId,
-            wt.excel_id AS excelId,
-            wt.sort,
-            wt.status,
-            wt.node_type AS nodeType,
-            wt.wbs_type AS wbsType,
-            wt.default_conceal AS defaultConceal,
-            wt.fill_rate AS "fillRate",
-            wt.html_url AS htmlUrl,
-            -- 预统计元素数量,避免Java层重复查询
-            COALESCE(we.element_count, 0) AS elementTotal
+        SELECT wt.p_key_id                                                                          AS "pKeyId",
+               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
+                   when wt.table_type in (2, 10) then 2
+                   else wt.table_type
+                   end                                                                              as tableType,
+               wt.`status`                                                                          AS isCreateTable,
+               wt.table_owner                                                                       AS tableOwner,
+               wt.is_link_table,
+               wt.init_table_name,
+               wt.init_table_id                                                                     as initTableId,
+               wt.excel_id                                                                          AS excelId,
+               wt.sort,
+               wt.status,
+               wt.node_type                                                                         AS nodeType,
+               wt.wbs_type                                                                          AS wbsType,
+               wt.default_conceal                                                                   AS defaultConceal,
+               wt.fill_rate                                                                         AS "fillRate",
+               wt.html_url                                                                          AS htmlUrl,
+               (SELECT count(1)
+                FROM m_wbs_form_element
+                WHERE f_id = wt.init_table_id
+                  and is_deleted = 0)                                                               AS "elementTotal"
+                , (SELECT tab_ch_name from m_table_info where tab_en_name = wt.init_table_name)     As elementTableName
         FROM m_wbs_tree_private AS wt
-                 -- 左关联m_wbs_tree获取init_table_id(原Java层initTableIdMaps逻辑)
-                 LEFT JOIN m_wbs_tree AS wt2 ON wt.id = wt2.id AND wt2.is_deleted = 0
-            -- 预统计每个init_table_id的元素数量,消除行级子查询
-                 LEFT JOIN (
-            SELECT f_id, COUNT(1) AS element_count
-            FROM m_wbs_form_element
-            WHERE is_deleted = 0
-            GROUP BY f_id
-        ) AS we ON wt.init_table_id = we.f_id
         WHERE wt.type = 2
           AND wt.is_deleted = 0
-          AND wt.parent_id = #{parentId}  -- 原参数写错了!是parentId不是id
+          AND wt.parent_id = #{id}
           AND wt.wbs_id = #{wbsId}
           AND wt.project_id = #{projectId}
-          AND wt.trial_tab_contract_id IS NULL
+          AND wt.trial_tab_contract_id is null
+        -- AND (wt.wbs_type != 2 OR wt.table_type IN (1,2,9,10))
         ORDER BY wt.sort, fullName
     </select>
     <select id="getByCondition" resultType="org.springblade.manager.entity.WbsTreePrivate">

+ 49 - 9
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ArchiveTreeContractServiceImpl.java

@@ -18,6 +18,7 @@ package org.springblade.manager.service.impl;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.mixsmart.utils.StringUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.core.toolkit.StringPool;
@@ -752,26 +753,65 @@ public class ArchiveTreeContractServiceImpl extends BaseServiceImpl<ArchiveTreeC
 	 * @param id
 	 * @return
 	 */
-	public  boolean deleteTree(Long id) {
+//	public  boolean deleteTree(Long id) {
+//		ArchiveTreeContract dstNode = this.getById(id);
+//		if (dstNode == null ) {
+//			return false;
+//		}
+//
+//		List<ArchiveTreeContractVO2> dstTrees = this.tree2Root(AuthUtil.getTenantId(),null,null,dstNode.getProjectId(),null);
+//		if (dstTrees == null || dstTrees.size() == 0) {
+//			return false;
+//		}
+//
+//		ArchiveTreeContractVO2 subTree = ForestNodeMergerEx.getSubTree(dstTrees.get(0),id);
+//
+//		List<Long> ids = ForestNodeMergerEx.getChildrenIds(subTree);
+//
+//		ids.add(id);
+//		this.deleteLogic(ids);
+//		return true;
+//	}
+
+	public boolean deleteTree(Long id) {
 		ArchiveTreeContract dstNode = this.getById(id);
-		if (dstNode == null ) {
+		if (dstNode == null) {
 			return false;
 		}
+		String tenantId = AuthUtil.getTenantId();
+		Long projectId = dstNode.getProjectId();
 
-		List<ArchiveTreeContractVO2> dstTrees = this.tree2Root(AuthUtil.getTenantId(),null,null,dstNode.getProjectId(),null);
-		if (dstTrees == null || dstTrees.size() == 0) {
+		// 调用优化后的listAllChildIds(CTE/存储过程均可)
+		List<Long> ids = this.listAllChildIds(id, projectId, tenantId);
+		if (CollectionUtils.isEmpty(ids)) {
 			return false;
 		}
 
-		ArchiveTreeContractVO2 subTree = ForestNodeMergerEx.getSubTree(dstTrees.get(0),id);
-
-		List<Long> ids = ForestNodeMergerEx.getChildrenIds(subTree);
-
-		ids.add(id);
 		this.deleteLogic(ids);
 		return true;
 	}
 
+	public List<Long> listAllChildIds(Long parentId, Long projectId, String tenantId) {
+		// 1. 构建存储过程入参
+		Map<String, Object> params = new HashMap<>(4);
+		params.put("parentId", parentId);
+		params.put("projectId", projectId);
+		params.put("tenantId", tenantId);
+		params.put("outIds", "");  // 初始化出参
+
+		// 2. 调用存储过程
+		baseMapper.callGetChildIds(params);
+
+		// 3. 解析出参(逗号分隔的ID字符串转Long列表)
+		String outIds = (String) params.get("outIds");
+		if (StringUtils.isEmpty(outIds)) {
+			return Collections.emptyList();
+		}
+		return Arrays.stream(outIds.split(","))
+				.map(Long::valueOf)
+				.collect(Collectors.toList());
+	}
+
 	/**
 	 * 更轻量的删除节点树,同时删除节点下的案卷和文件
 	 * @param id

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

@@ -166,7 +166,7 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
                 List<Long> ids = records.stream().map(ExcelTabVO::getId).collect(Collectors.toList());
                 List<ExcelTabVO> excelTabs = this.baseMapper.getByIds(ids);
                 Map<Long, ExcelTabVO> map = excelTabs.stream().collect(toMap(ExcelTabVO::getId, v -> v));
-                List<ExcelTabVO> projectInfoList  = baseMapper.selectRootExcelTab(new Page<>(), null, ids);
+                List<ExcelTabVO> projectInfoList  = baseMapper.selectRootExcelTab(new Page<>(1,500), null, ids);
                 Map<Long, List<ExcelTabVO>> collect = projectInfoList.stream().collect(Collectors.groupingBy(ExcelTabVO::getId));
                 records.forEach(v -> {
                     ProjectInfoVO1 projectInfoVO1 = new ProjectInfoVO1();
@@ -194,7 +194,7 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
         List<ExcelTabVO> records = baseMapper.selectExcelTabPage(page, excelTab);
         if (!records.isEmpty() && (excelTab.getParentId() == null || excelTab.getParentId() == 0)) {
             Set<Long> set = records.stream().map(ExcelTabVO::getId).collect(Collectors.toSet());
-            List<ExcelTabVO> projectInfoList  = baseMapper.selectRootExcelTab(new Page<>(), null, set);
+            List<ExcelTabVO> projectInfoList  = baseMapper.selectRootExcelTab(new Page<>(1,500), null, set);
             Map<Long, List<ExcelTabVO>> collect = projectInfoList.stream().collect(Collectors.groupingBy(ExcelTabVO::getId));
             records.forEach(v -> {
                 List<ExcelTabVO> excelTabVOS = collect.get(v.getId());
@@ -234,7 +234,7 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
         } else {
             excelTabVO.setExcelUseNumber(Integer.parseInt(map.get("useNum").toString()));
         }
-        List<ExcelTabVO> projectInfoList  = baseMapper.selectRootExcelTab(new Page<>(), null, Collections.singleton(id));
+        List<ExcelTabVO> projectInfoList  = baseMapper.selectRootExcelTab(new Page<>(1,500), null, Collections.singleton(id));
         if (projectInfoList != null && !projectInfoList.isEmpty()) {
             List<ProjectInfoVO1> list = projectInfoList.stream().map(vo -> {
                 ProjectInfoVO1 projectInfoVO1 = new ProjectInfoVO1();

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

@@ -1132,8 +1132,9 @@ public class WbsFormElementServiceImpl extends BaseServiceImpl<WbsFormElementMap
         vo.setIsExistData(false);
         try {
             //获取实体表是否存储数据
-            vo.setIsExistData(jdbcTemplate.queryForObject("select count(0) > 0 from " + vo.getTabChName(), Boolean.class));
+            vo.setIsExistData(jdbcTemplate.queryForObject("select count(0) > 0 from " + vo.getTabEnName(), Boolean.class));
         } catch (Exception ignored) {
+            ignored.printStackTrace();
         }
         //获取项目列表
         List<String> list = baseMapper.selectProjectList(id);

+ 5 - 13
blade-service/blade-user/src/main/java/org/springblade/system/user/service/impl/UserServiceImpl.java

@@ -1932,19 +1932,11 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
 
         if (node != null) {
             if (!new Integer("6").equals(node.getNodeType()) && !Arrays.asList("1,2,3,4".split(",")).contains(node.getMajorDataType() + "")) {
-                if (node.getParentId() == 0) {
-                    throw new ServiceException("请从第三层级节点开始进行检索");
-                } else {
-                    WbsTreeContract wbsTreeContract = jdbcTemplate.query("select parent_id from m_wbs_tree_contract where is_deleted = 0 and status = 1 and type = 1 and id = " + node.getParentId() + " and contract_id = " + node.getContractId(), new BeanPropertyRowMapper<>(WbsTreeContract.class)).stream().findAny().orElse(null);
-                    if (wbsTreeContract != null && wbsTreeContract.getParentId().equals(0L)) {
-                        throw new ServiceException("请从第三层级节点开始进行检索");
-                    }
-                    WbsTreeContract oldSelectedNode = BeanUtil.copyProperties(node, WbsTreeContract.class);
-                    childNodesPkeyIds = this.getChildNodesPkeyIds(oldSelectedNode, lowestNodesPkeyIds);
-                    List<String> sj = this.getSJ(contract, vo, lowestNodesPkeyIds);
-                    if (sj != null && sj.size() > 0) {
-                        submitNodeKeyIds.addAll(sj);
-                    }
+                WbsTreeContract oldSelectedNode = BeanUtil.copyProperties(node, WbsTreeContract.class);
+                childNodesPkeyIds = this.getChildNodesPkeyIds(oldSelectedNode, lowestNodesPkeyIds);
+                List<String> sj = this.getSJ(contract, vo, lowestNodesPkeyIds);
+                if (sj != null && sj.size() > 0) {
+                    submitNodeKeyIds.addAll(sj);
                 }
             }
             vo.setWbsIds(submitNodeKeyIds);