فهرست منبع

Revert "Revert "质检-同步合同段-上报记录表单html历史,重签先查询是否存在html历史有就使用历史,保存删除html历史""

This reverts commit b81ee4b6
LHB 1 ماه پیش
والد
کامیت
8746be0a37
15فایلهای تغییر یافته به همراه910 افزوده شده و 3 حذف شده
  1. 56 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/WbsTreeContractOldHtml.java
  2. 6 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/feign/WbsTreeContractClient.java
  3. 23 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/feign/WbsTreeContractOldHtmlClient.java
  4. 27 0
      blade-service/blade-business/src/main/java/org/springblade/business/controller/InformationWriteQueryController.java
  5. 79 3
      blade-service/blade-business/src/main/java/org/springblade/business/utils/FileUtils.java
  6. 593 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ExcelTabController.java
  7. 8 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/feign/WbsTreeContractClientImpl.java
  8. 24 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/feign/WbsTreeContractOldHtmlClientImpl.java
  9. 18 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsTreeContractOldHtmlMapper.java
  10. 22 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsTreeContractOldHtmlMapper.xml
  11. 2 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/IWbsTreeContractService.java
  12. 13 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/WbsTreeContractOldHtmlService.java
  13. 11 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ExcelTabServiceImpl.java
  14. 22 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreeContractOldHtmlServiceImpl.java
  15. 6 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreeContractServiceImpl.java

+ 56 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/WbsTreeContractOldHtml.java

@@ -0,0 +1,56 @@
+package org.springblade.manager.entity;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.util.Date;
+import lombok.Data;
+
+/**
+ * 合同段表单上报之前的html记录
+ * @author LHB
+ * @TableName m_wbs_tree_contract_old_html
+ */
+@TableName(value ="m_wbs_tree_contract_old_html")
+@Data
+public class WbsTreeContractOldHtml {
+    /**
+     * 
+     */
+    @TableId
+    private Long id;
+
+    /**
+     * 合同WBS的p_key_id
+     */
+    private Long contractFormId;
+
+    /**
+     * 上报之前的html表单
+     */
+    private String oldHtmlUrl;
+
+    /**
+     *  是否删除(0-正常,1-已删除)
+     */
+    private Integer isDeleted;
+
+    /**
+     *  创建时间
+     */
+    private Date createTime;
+
+    /**
+     *  创建人
+     */
+    private Long createUser;
+
+    /**
+     *  修改时间
+     */
+    private Date updateTime;
+
+    /**
+     *  修改人
+     */
+    private Long updateUser;
+}

+ 6 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/feign/WbsTreeContractClient.java

@@ -205,4 +205,10 @@ public interface WbsTreeContractClient {
 
     @GetMapping(API_PREFIX + "/saveNameRuleByPkeyId")
     void saveNameRuleByPkeyId(@RequestParam Long  pKeyId, @RequestParam String s,  @RequestParam Long projectId);
+
+    @GetMapping(API_PREFIX + "/findIsExistTreeNode")
+    Integer findIsExistTreeNode(List<String> processNodeList);
+
+    @GetMapping(API_PREFIX + "/queryListByPIds")
+    List<WbsTreeContract> queryListByPIds(List<Long> pIds);
 }

+ 23 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/feign/WbsTreeContractOldHtmlClient.java

@@ -0,0 +1,23 @@
+package org.springblade.manager.feign;
+
+import org.springblade.manager.entity.WbsTreeContract;
+import org.springblade.manager.entity.WbsTreeContractOldHtml;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+
+import java.util.List;
+
+import static org.springblade.core.launch.constant.AppConstant.APPLICATION_NAME_PREFIX;
+
+@FeignClient(value = APPLICATION_NAME_PREFIX + "manager")
+public interface WbsTreeContractOldHtmlClient {
+    /**
+     * 接口前缀
+     */
+    String API_PREFIX = "/api/manager/WbsTreeContractOldHtml";
+
+    @PostMapping(API_PREFIX + "/save")
+    Boolean save(@RequestBody List<WbsTreeContractOldHtml> data);
+
+}

+ 27 - 0
blade-service/blade-business/src/main/java/org/springblade/business/controller/InformationWriteQueryController.java

@@ -7,6 +7,7 @@ import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.conditions.query.QueryChainWrapper;
@@ -112,6 +113,7 @@ public class InformationWriteQueryController extends BladeController {
     private final ContractClient contractClient;
 
     private final WbsTreeContractClient wbsTreeContractClient;
+    private final WbsTreeContractOldHtmlClient wbsTreeContractOldHtmlClient;
 
     private final WbsTreePrivateClient wbsTreePrivateClient;
 
@@ -1213,8 +1215,33 @@ public class InformationWriteQueryController extends BladeController {
                 return R.data(300, false, "未查询到填报信息,上报失败");
             }
         } else { //质检
+            //记录选中节点的所有表单旧html
+            List<Long> list = Arrays.stream(startTaskVO.getIds().split(",")).map(Long::parseLong).collect(Collectors.toList());
+            List<WbsTreeContract> wbsTreeContracts =  wbsTreeContractClient.queryListByPIds(list);
+
+
             businessData = this.informationQueryService.getOne(Wrappers.<InformationQuery>lambdaQuery().eq(InformationQuery::getWbsId, startTaskVO.getIds().replaceAll(",", "")).eq(InformationQuery::getClassify, startTaskVO.getClassify().toString()).eq(InformationQuery::getType, 1).last("order by id desc limit 1"));
             if (businessData != null) {
+
+                //处理html 复制之后记录在新表中w
+                if (CollectionUtils.isNotEmpty(wbsTreeContracts)) {
+                    List<WbsTreeContractOldHtml> data = new ArrayList<>();
+                    try {
+                        for (WbsTreeContract wbsTreeContract : wbsTreeContracts) {
+                            WbsTreeContractOldHtml oldHtml = new WbsTreeContractOldHtml();
+                            oldHtml.setId(SnowFlakeUtil.getId());
+                            oldHtml.setCreateUser(getUser().getUserId());
+                            String htmlUrl = wbsTreeContract.getHtmlUrl();
+                            String s = FileUtils.copyFileWithAbsolutePath(htmlUrl);
+                            oldHtml.setOldHtmlUrl(FileUtils.copyFileWithAbsolutePath(htmlUrl));
+                            data.add(oldHtml);
+                        }
+                        wbsTreeContractOldHtmlClient.save(data);
+                    } catch (Exception e) {
+                        throw new ServiceException(e.getMessage());
+                    }
+                }
+
                 //设置业务数据ID
                 startTaskVO.setIds(businessData.getId().toString());
                 return this.batchTask(startTaskVO);

+ 79 - 3
blade-service/blade-business/src/main/java/org/springblade/business/utils/FileUtils.java

@@ -18,6 +18,7 @@ import org.springblade.common.constant.CommonConstant;
 import org.springblade.common.utils.CommonUtil;
 import org.springblade.common.utils.SystemUtils;
 import org.springblade.common.vo.DataVO;
+import org.springblade.core.log.exception.ServiceException;
 import org.springblade.core.tool.utils.IoUtil;
 import org.springblade.system.cache.ParamCache;
 
@@ -33,9 +34,7 @@ import java.awt.image.AffineTransformOp;
 import java.awt.image.BufferedImage;
 import java.io.*;
 import java.net.URLEncoder;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
+import java.nio.file.*;
 import java.util.Arrays;
 import java.util.Iterator;
 import java.util.List;
@@ -658,4 +657,81 @@ public class FileUtils {
             System.err.println("删除本地文件失败: " + localFilePath + ", 错误: " + e.getMessage());
         }
     }
+
+    /**
+     * 获取文件绝对路径并复制文件
+     * @param sourcePath 源文件路径(相对或绝对)
+     */
+    public static String copyFileWithAbsolutePath(String sourcePath) {
+        try {
+            // 1. 获取源文件的绝对路径
+            File sourceFile = new File(sourcePath);
+            String absolutePath = sourceFile.getAbsolutePath();
+            System.out.println("源文件绝对路径: " + absolutePath);
+
+            // 2. 验证文件存在且可读
+            if (!sourceFile.exists()) {
+                System.err.println("错误: 源文件不存在");
+                throw new ServiceException("错误: 源文件不存在");
+            }
+            if (!sourceFile.canRead()) {
+                System.err.println("错误: 无法读取源文件");
+
+                throw new ServiceException("错误: 源文件不存在");
+            }
+
+            // 3. 创建目标文件路径(在相同目录,文件名添加 _copy)
+            String parentDir = sourceFile.getParent();
+            String fileName = sourceFile.getName();
+
+            // 提取文件名和扩展名
+            String baseName;
+            String extension = "";
+            int dotIndex = fileName.lastIndexOf('.');
+            if (dotIndex > 0) {
+                baseName = fileName.substring(0, dotIndex);
+                extension = fileName.substring(dotIndex);
+            } else {
+                baseName = fileName;
+            }
+
+            // 生成唯一的目标文件名(避免覆盖)
+            File destFile;
+            int copyCounter = 1;
+            do {
+                String newFileName = baseName + "_copy" +
+                        (copyCounter > 1 ? "_" + copyCounter : "") +
+                        extension;
+                destFile = new File(parentDir, newFileName);
+                copyCounter++;
+            } while (destFile.exists());
+
+            System.out.println("目标文件路径: " + destFile.getAbsolutePath());
+
+            // 4. 执行文件复制(使用NIO方法)
+            Path source = sourceFile.toPath();
+            Path destination = destFile.toPath();
+
+            // 复制文件并保留属性
+            Files.copy(source, destination,
+                    StandardCopyOption.COPY_ATTRIBUTES,
+                    StandardCopyOption.REPLACE_EXISTING);
+
+            System.out.println("文件复制成功!");
+            return destFile.getAbsolutePath();
+        } catch (InvalidPathException e) {
+            System.err.println("路径无效: " + e.getMessage());
+            throw new ServiceException("路径无效");
+        } catch (FileAlreadyExistsException e) {
+            System.err.println("文件已存在: " + e.getMessage());
+            throw new ServiceException("文件已存在");
+        } catch (AccessDeniedException e) {
+            System.err.println("访问被拒绝: " + e.getMessage());
+            throw new ServiceException("访问被拒绝");
+        } catch (IOException e) {
+            System.err.println("IO错误: " + e.getMessage());
+            e.printStackTrace();
+            throw new ServiceException("IO错误");
+        }
+    }
 }

+ 593 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ExcelTabController.java

@@ -169,6 +169,7 @@ public class ExcelTabController extends BladeController {
 
     private final WbsTreeContractStatisticsClient wbsTreeContractStatisticsClient;
 
+    private final WbsTreeContractOldHtmlService wbsTreeContractOldHtmlService;
 
     @Autowired
     StringRedisTemplate RedisTemplate;
@@ -1002,6 +1003,598 @@ public class ExcelTabController extends BladeController {
         return doc.select("table").first() + "";
     }
 
+    // 上传解析 html
+    public void expailHtmlInfo(String thmlUrl, Long excelId, String tabType) throws Exception {
+
+        // 读取
+        File file1 = ResourceUtil.getFile(thmlUrl);
+        String htmlString = IoUtil.readToString(new FileInputStream(file1));
+
+        /*
+           解析
+           1 解析样式
+           2 计算坐标
+           3 计算区域位置
+         */
+        // 样式集合
+        Document doc = Jsoup.parse(htmlString);
+        // 解析 style
+        Map<String, String> styleMap = getHtmlStyle(doc);
+        //解析
+        Element table = doc.select("table").first();
+
+        Elements trs = table.select("tr");
+        Element tableinfo = trs.get(0).parent().parent().attr("style", "border-collapse: collapse;");
+
+        // 获取图片信息
+        Elements imgs = doc.select("img");
+
+
+        // 获取总行列数
+        int maxCol = doc.select("Col").size();
+        String[] rowData = new String[trs.size() + 5]; //本来加一的 害怕出现特殊情况 故意 加 5
+
+        // 行的状态
+        boolean index_state = false;
+        // 区域划分表示
+        int xy_type = 1;
+
+        // 解析 excel元素集合
+        List<ExctabCell> colTitle = new ArrayList<>();
+
+//      标题集合信息
+        List<Map<String, String>> zikey = new ArrayList<>();
+        for (int i = 0; i <= trs.size() - 1; i++) {
+            Element tr = trs.get(i);
+            Elements tds = tr.select("td");
+
+            String xyInof = getTrInfo(tds, styleMap, index_state, xy_type, maxCol, i, zikey);
+
+            xy_type = Integer.parseInt(xyInof.split(",")[0]);
+            tr.attr("xy_type", xyInof);
+            index_state = Boolean.parseBoolean(xyInof.split(",")[1]);
+            boolean isMaxCol = Integer.parseInt(xyInof.split(",")[2]) == maxCol;
+
+            boolean istrue = Boolean.parseBoolean(xyInof.split(",")[3]);
+
+
+            // 计算单元格坐标
+            int x = 0;
+
+            for (int j = 0; j < tds.size(); j++) {
+                {
+                    Element data = tds.get(j);
+                    Boolean isText = false;
+                    //判断高度
+                    String style = data.attr("style");
+                    if (StringUtils.isNotBlank(style)) {
+                        int index = style.lastIndexOf(":");
+                        String substring = style.substring(index + 1);
+                        String height = substring.substring(0, substring.length() - 3);
+                        int i1 = 0;
+                        try {
+                            i1 = Integer.parseInt(height);
+                        } catch (NumberFormatException e) {
+                            substring = style.substring(style.lastIndexOf(":", index - 1) + 1);
+                            height = substring.substring(0, substring.indexOf("px;"));
+                            i1 = Integer.parseInt(height);
+                        }
+                        if (i1 > 90) {
+                            isText = true;
+                        }
+                    }
+                    String trHtml = data.html();
+                    int colspan = data.attr("COLSPAN").equals("") ? 0 : Integer.parseInt(data.attr("COLSPAN"));
+                    int rowspan = data.attr("ROWSPAN").equals("") ? 0 : Integer.parseInt(data.attr("ROWSPAN"));
+                    String keyId = data.attr("class");
+                    if (StringUtils.isNotEmpty(keyId)) {
+                        String classInfo = styleMap.get(keyId);
+                        data.removeAttr("class");
+                    }
+
+                    Map<String, String> textObject = new HashMap<>();
+                    // 计算
+                    int x1 = 0;
+                    int x2 = 0;
+                    int y1 = 0;
+                    int y2 = 0;
+
+                    String textInfo = data.text().trim().replaceAll(" ", "");
+
+                    y1 = i + 1;
+                    //x 移位 算法
+                    String getRowInfo = rowData[y1];
+
+                    if (getRowInfo != null) {
+                        String[] dataInfo2 = getRowInfo.split(",");
+
+                        // 排序
+                        int lastMax = 0;
+                        List<String> datax = Arrays.stream(dataInfo2).sorted((a, b) -> Integer.parseInt(a.split(":")[1]) - Integer.parseInt(b.split(":")[1])).collect(Collectors.toList());
+                        List<String> lastdata = new ArrayList<>();
+                        //组合
+                        for (int h = 0; h < datax.size(); h++) {
+                            int mx1 = Integer.parseInt(datax.get(h).split(":")[0]);
+                            int mx2 = Integer.parseInt(datax.get(h).split(":")[1]);
+                            if (lastdata.size() == 0) {
+                                lastdata.add(datax.get(0));
+                            } else {
+                                if (lastMax + 1 == mx1) {
+                                    int minVal = Integer.parseInt(lastdata.get(lastdata.size() - 1).split(":")[0]);
+                                    lastdata.remove(lastdata.size() - 1);
+                                    lastdata.add(minVal + ":" + mx2);
+                                } else {
+                                    lastdata.add(datax.get(h));
+                                }
+                            }
+                            lastMax = mx2;
+                        }
+                        dataInfo2 = lastdata.stream().toArray(String[]::new);
+
+                        // 先逻辑处理 连续时,归一
+                        if ((dataInfo2[0].split(":")[0]).equals("1") && j == 0) {
+                            x = Integer.parseInt(dataInfo2[0].split(":")[1]);
+                        } else {
+                            for (int m = 0; m < dataInfo2.length; m++) {
+                                int mx1 = Integer.parseInt(dataInfo2[m].split(":")[0]);
+                                int mx2 = Integer.parseInt(dataInfo2[m].split(":")[1]);
+                                if ((mx1 - x) == 1 && mx1 > x) {
+                                    x = mx2;
+                                }
+                            }
+                        }
+                    }
+
+                    // X 坐标
+
+
+                    if (tds.size() == 1) {
+                        if (colspan == 0) {
+                            x1 = x + 1;
+                            x2 = x + 1;
+                        } else {
+                            if (x == 0) {
+                                x1 = 1;
+                                x2 = colspan;
+                            } else {
+                                x1 = x + 1;
+                                x2 = x + colspan;
+                            }
+                        }
+                    } else {
+                        if (colspan == 0) {
+                            x1 = x + 1;
+                            x2 = x + 1;
+                            x = x2;
+                        } else {
+                            x1 = x + 1;
+                            x2 = x + colspan;
+                            x = x2;
+                        }
+                    }
+
+
+                    //x y 坐标
+                    if (rowspan == 0) {
+                        y2 = i + 1;
+                    } else {
+                        y2 = i + rowspan;
+                        for (int k = 0; k < rowspan - 1; k++) {
+                            String dataInfo = rowData[k + 2 + i];
+                            if (dataInfo == null) {
+                                dataInfo = x1 + ":" + x2;
+                            } else {
+                                dataInfo = dataInfo + "," + x1 + ":" + x2;
+                                String[] arr = dataInfo.split(",");
+                                //排序
+                                for (int r = 0; r < arr.length - 1; r++) {
+                                    for (int q = arr.length - 2; q >= r; q--) {
+                                        Integer jval = Integer.parseInt(arr[q + 1].split(":")[0]);
+                                        Integer jval1 = Integer.parseInt(arr[q].split(":")[0]);
+                                        if (jval < jval1) {
+                                            String temp = arr[q + 1];
+                                            arr[q + 1] = arr[q];
+                                            arr[q] = temp;
+                                        }
+                                    }
+                                }
+
+                                //组合
+                                String newDataInfo = "";
+                                for (int r = 0; r < arr.length; r++) {
+                                    if (r == 0) {
+                                        newDataInfo = arr[0];
+                                    } else {
+                                        int StrMax = Integer.parseInt(newDataInfo.substring(newDataInfo.lastIndexOf(":") + 1, newDataInfo.length()));
+                                        Integer nowMin = Integer.parseInt(arr[r].split(":")[0]);
+                                        Integer nowMax = Integer.parseInt(arr[r].split(":")[1]);
+                                        if ((StrMax + 1) == nowMin) {
+                                            String lastStr = "";
+                                            if (newDataInfo.indexOf(",") >= 0) {
+                                                lastStr = newDataInfo.substring(newDataInfo.lastIndexOf(",") + 1, newDataInfo.length());
+                                                newDataInfo = newDataInfo.substring(0, newDataInfo.lastIndexOf(","));
+                                            } else {
+                                                lastStr = newDataInfo;
+                                                newDataInfo = "";
+                                            }
+                                            int lastmin = Integer.parseInt(lastStr.split(":")[0]);
+                                            if (StringUtils.isNotEmpty(newDataInfo)) {
+                                                newDataInfo = newDataInfo + "," + lastmin + ":" + nowMax;
+                                            } else {
+                                                newDataInfo = lastmin + ":" + nowMax;
+                                            }
+                                        } else {
+                                            newDataInfo = newDataInfo + "," + nowMin + ":" + nowMax;
+                                        }
+                                    }
+                                }
+                                dataInfo = newDataInfo;
+                            }
+                            rowData[k + 2 + i] = dataInfo;
+                        }
+                    }
+
+                    data.text(textInfo.replaceAll(" ", ""));
+                    if (textInfo.indexOf("□") < 0 && !textInfo.isEmpty() && !(textInfo.equals("/") && textInfo.length() < 2) && !(textInfo.indexOf("年") >= 0 && textInfo.indexOf("月") >= 0 && textInfo.indexOf("日") >= 0) && !textInfo.equals("—") && !textInfo.equals("-")) {  // 标题区域
+                        Map<String, String> dataInfo = new HashMap<String, String>();
+                        dataInfo.put("name", textInfo);
+                        dataInfo.put("x1", x1 + "");
+                        dataInfo.put("x2", x2 + "");
+                        dataInfo.put("y1", y1 + "");
+                        dataInfo.put("y2", y2 + "");
+                        dataInfo.put("xytype", xy_type + "");
+                        if (textInfo.indexOf("/") < 0 || (textInfo.indexOf("/") >= 0 && textInfo.length() > 1)) { // 带/为分割数据
+                            zikey.add(dataInfo);
+                        }
+                    } else { //空行
+                        List<Map<String, String>> left = new ArrayList<>();
+                        List<Map<String, String>> top = new ArrayList<>();
+                        for (int k = 0; k < zikey.size(); k++) {
+                            String name = zikey.get(k).get("name");
+                            int xx1 = Integer.parseInt(zikey.get(k).get("x1"));
+                            int xx2 = Integer.parseInt(zikey.get(k).get("x2"));
+                            int yy1 = Integer.parseInt(zikey.get(k).get("y1"));
+                            int yy2 = Integer.parseInt(zikey.get(k).get("y2"));
+                            int xytype2 = Integer.parseInt(zikey.get(k).get("xytype"));
+
+                            // 左匹配
+                            if (yy1 <= y1 && yy2 >= y2 && xx2 < x1 && xytype2 == xy_type) {
+                                left.add(zikey.get(k));
+                            }
+
+                            //向 上 匹配
+                            if (index_state) {
+                                if (xx1 <= x1 && xx2 >= x2 && yy2 < y1 && xytype2 == xy_type) {
+                                    top.add(zikey.get(k));
+                                }
+                            }
+                        }
+
+                        String inputText = "";
+                        // 特征值赛选 规则
+                        for (int k = 0; k < left.size(); k++) { // 左计算
+                            String name = left.get(k).get("name");
+                            int xx1 = Integer.parseInt(left.get(k).get("x1"));
+                            int xx2 = Integer.parseInt(left.get(k).get("x2"));
+                            int yy1 = Integer.parseInt(left.get(k).get("y1"));
+                            int yy2 = Integer.parseInt(left.get(k).get("y2"));
+
+                            if (!StringUtil.isNumeric(name) && name.length() <= 20) { // 数字不匹配
+                                if (index_state) { // 正向规则匹配
+                                    if (istrue) { // 是否空格等于值
+                                        if (x1 - xx2 <= 1 && y1 == yy2) {
+                                            inputText = name;
+                                        } else {
+                                            inputText += name + "_";
+                                        }
+                                    } else {
+                                        inputText += name + "_";
+                                    }
+                                } else {
+                                    if (x1 - xx2 <= 1 && y1 == yy2) {
+                                        inputText = name;
+                                    }
+                                }
+                            }
+                        }
+
+                        // 特征值赛选 规则
+                        if (top != null && top.size() >= 1) {
+                            for (int k = 0; k < top.size(); k++) { // 向上计算
+                                String name = top.get(k).get("name");
+                                int xx1 = Integer.parseInt(top.get(k).get("x1"));
+                                int xx2 = Integer.parseInt(top.get(k).get("x2"));
+                                int yy1 = Integer.parseInt(top.get(k).get("y1"));
+                                int yy2 = Integer.parseInt(top.get(k).get("y2"));
+                                if (!StringUtil.isNumeric(name) && name.length() <= 20) {
+                                    inputText += name + "_";
+                                }
+                            }
+                        }
+
+                        if (inputText != null && inputText != "" && inputText.indexOf("_") >= 0) {
+                            inputText = inputText.substring(0, inputText.lastIndexOf("_"));
+                        }
+
+                        // 质检表特殊处理匹配
+
+                        String parm = i + "," + j + "," + x1 + "," + x2 + "," + y1 + "," + y2 + ",$event";
+                        // 设置文本信息
+                        ExctabCell exctabCell = new ExctabCell();
+                        if ((textInfo.indexOf("年") >= 0 && textInfo.indexOf("月") >= 0 && textInfo.indexOf("日") >= 0) || inputText.indexOf("日期") >= 0) {
+                            if (inputText.indexOf("日期") >= 0) {
+                                data.empty().append("<el-date-picker type='date' @keyDowns='dateKeydown()' format='YYYY年MM月DD日' value-format='YYYY年MM月DD日' @contextmenu.prevent.native='contextmenuClick(" + parm + ")'  @mouseup.right='RightClick(" + parm + ")' trIndex=" + i + " tdIndex=" + j + "  x1=" + x1 + " x2=" + x2 + " y1=" + y1 + " y2=" + y2 + " style='width:100%;height:100%;' placeholder='" + inputText + "'> </el-date-picker>");
+                            } else if (textInfo.indexOf("年") >= 0 && textInfo.indexOf("月") >= 0 && textInfo.indexOf("日") >= 0) {
+                                if (inputText.indexOf("专业监理工程师") >= 0) {
+                                    inputText = "专业监理工程师_年月日";
+                                } else if (inputText.indexOf("质检工程师") >= 0) {
+                                    inputText = "质检工程师_年月日";
+                                } else {
+                                    inputText = "年月日";
+                                }
+                            }
+                            data.empty().append("<el-date-picker @keyDowns='dateKeydown()'  type='date' format='YYYY年MM月DD日' value-format='YYYY年MM月DD日' @contextmenu.prevent.native='contextmenuClick(" + parm + ")'  @mouseup.right='RightClick(" + parm + ")' trIndex=" + i + " tdIndex=" + j + "  x1=" + x1 + " x2=" + x2 + " y1=" + y1 + " y2=" + y2 + " style='width:100%;height:100%;' placeholder='年月日'> </el-date-picker>");
+                            exctabCell.setTextInfo(inputText);
+                            exctabCell.setExctabId(excelId);
+                            exctabCell.setIsDeleted(0);
+                            exctabCell.setXys(i + "_" + j);
+                            colTitle.add(exctabCell);
+                            data.attr("title", inputText);
+
+                        } else if (textInfo.indexOf("□") >= 0) { //多选框
+                            exctabCell.setTextInfo(inputText);
+                            exctabCell.setExctabId(excelId);
+                            exctabCell.setIsDeleted(0);
+                            exctabCell.setXys(i + "_" + j);
+                            colTitle.add(exctabCell);
+                            data.attr("title", inputText);
+                            // 添加多选框
+
+                            String[] cheText = textInfo.split("□");
+                            JSONArray objs = new JSONArray();
+                            if (cheText != null && cheText.length >= 1) {
+                                int key = 1;
+                                for (String keyval : cheText) {
+                                    JSONObject jsonObject = new JSONObject();
+                                    if (StringUtils.isNotEmpty(keyval)) {
+                                        jsonObject.put("key", key);
+                                        jsonObject.put("name", keyval);
+                                        objs.add(jsonObject);
+                                        keyId += 1;
+                                    }
+                                }
+                            } else {
+                                JSONObject jsonObject = new JSONObject();
+                                jsonObject.put("key", "1");
+                                jsonObject.put("name", "");
+                                objs.add(jsonObject);
+                            }
+
+                            String checkbox = "<hc-form-checkbox-group @keydown.shift.up='keyupShiftUp' @keydown.shift.down='keyupShiftDown' @keydown.shift.left='keyupShiftLeft' @keydown.shift.right='keyupShiftRight' :objs='" + objs + "'  @change='checkboxGroupChange' @contextmenu.prevent.native='contextmenuClick(" + parm + ")'  @mouseup.right='RightClick(" + parm + ")' trIndex=" + i + " tdIndex=" + j + "  x1=" + x1 + " x2=" + x2 + " y1=" + y1 + " y2=" + y2 + " placeholder=''> </hc-form-checkbox-group>";
+                            data.empty().append(checkbox);
+
+                        } else {
+
+                            if (index_state) { // 区域内
+                                if (rowspan >= 1 || isText) {
+                                    data.empty().append("<el-input type='textarea' @keydown.shift.up='keyupShiftUp' @keydown.shift.down='keyupShiftDown' @keydown.shift.left='keyupShiftLeft'  @keydown.shift.right='keyupShiftRight'  @contextmenu.prevent.native='contextmenuClick(" + parm + ")'  @mouseup.right='RightClick(" + parm + ")' trIndex=" + i + " tdIndex=" + j + "  x1=" + x1 + " x2=" + x2 + " y1=" + y1 + " y2=" + y2 + " style='width:100%;height:100%;'   :rows=" + rowspan * 2 + " placeholder=''> </el-input>");
+                                } else {
+                                    data.empty().append("<el-input type='text' @keydown.shift.up='keyupShiftUp' @keydown.shift.down='keyupShiftDown' @keydown.shift.left='keyupShiftLeft'  @keydown.shift.right='keyupShiftRight'  @contextmenu.prevent.native='contextmenuClick(" + parm + ")'  @mouseup.right='RightClick(" + parm + ")' trIndex=" + i + " tdIndex=" + j + "  x1=" + x1 + " x2=" + x2 + " y1=" + y1 + " y2=" + y2 + " style='width:100%;height:100%;' placeholder=''> </el-input>");
+                                }
+                            } else if (tabType.equals("100") && i < 2) { //计量特殊添加
+                                data.empty().append("<el-input type='text' @keydown.shift.up='keyupShiftUp' @keydown.shift.down='keyupShiftDown' @keydown.shift.left='keyupShiftLeft'  @keydown.shift.right='keyupShiftRight'  @contextmenu.prevent.native='contextmenuClick(" + parm + ")'  @mouseup.right='RightClick(" + parm + ")' trIndex=" + i + " tdIndex=" + j + "  x1=" + x1 + " x2=" + x2 + " y1=" + y1 + " y2=" + y2 + " style='width:100%;height:100%;' placeholder=''> </el-input>");
+                            } else { // 区域外
+                                if (j == 0) {
+                                    if (colspan == maxCol && i >= 1) {
+                                        if (rowspan >= 1 || isText) {
+                                            data.empty().append("<el-input @keydown.shift.up='keyupShiftUp' @keydown.shift.down='keyupShiftDown' @keydown.shift.left='keyupShiftLeft' @keydown.shift.right='keyupShiftRight' type='textarea'  @contextmenu.prevent.native='contextmenuClick(" + parm + ")'  @mouseup.right='RightClick(" + parm + ")' trIndex=" + i + " tdIndex=" + j + "  x1=" + x1 + " x2=" + x2 + " y1=" + y1 + " y2=" + y2 + " style='width:100%;height:100%;'   :rows=" + rowspan * 2 + " placeholder=''> </el-input>");
+                                        } else {
+                                            data.empty().append("<el-input @keydown.shift.up='keyupShiftUp' @keydown.shift.down='keyupShiftDown' @keydown.shift.left='keyupShiftLeft' @keydown.shift.right='keyupShiftRight' type='text' @contextmenu.prevent.native='contextmenuClick(" + parm + ")'  @mouseup.right='RightClick(" + parm + ")' trIndex=" + i + " tdIndex=" + j + "  x1=" + x1 + " x2=" + x2 + " y1=" + y1 + " y2=" + y2 + " style='width:100%;height:100%;' placeholder=''> </el-input>");
+                                        }
+                                    }
+                                } else {
+                                    Element bforData = tds.get(j - 1);
+                                    if (!bforData.text().isEmpty() || bforData.html().indexOf("hc-form-checkbox-group") >= 0) {
+                                        if (rowspan >= 1 || isText) {
+                                            data.empty().append("<el-input @keydown.shift.up='keyupShiftUp' @keydown.shift.down='keyupShiftDown' @keydown.shift.left='keyupShiftLeft' @keydown.shift.right='keyupShiftRight' type='textarea' @contextmenu.prevent.native='contextmenuClick(" + parm + ")'  @mouseup.right='RightClick(" + parm + ")' trIndex=" + i + " tdIndex=" + j + "  x1=" + x1 + " x2=" + x2 + " y1=" + y1 + " y2=" + y2 + " style='width:100%;height:100%;'   :rows=" + rowspan * 2 + " placeholder=''> </el-input>");
+                                        } else {
+                                            data.empty().append("<el-input @keydown.shift.up='keyupShiftUp' @keydown.shift.down='keyupShiftDown' @keydown.shift.left='keyupShiftLeft'  @keydown.shift.right='keyupShiftRight' type='text' @contextmenu.prevent.native='contextmenuClick(" + parm + ")'  @mouseup.right='RightClick(" + parm + ")' trIndex=" + i + " tdIndex=" + j + "  x1=" + x1 + " x2=" + x2 + " y1=" + y1 + " y2=" + y2 + " style='width:100%;height:100%;' placeholder=''> </el-input>");
+                                        }
+                                    }
+                                }
+                            }
+
+                            if (!inputText.equals("")) {
+                                exctabCell.setExctabId(excelId);
+                                exctabCell.setTextInfo(inputText);
+                                if (inputText.contains("日期") || inputText.contains("年") || inputText.contains("月") || inputText.contains("日")) {
+                                    //日期
+                                    exctabCell.setTextElementType(4);
+                                } else if (inputText.indexOf("签字") >= 0) {
+                                    exctabCell.setTextElementType(6);
+                                } else {
+                                    //字符串
+                                    exctabCell.setTextElementType(1);
+                                }
+
+                                exctabCell.setIsDeleted(0);
+                                exctabCell.setXys(i + "_" + j);
+                                colTitle.add(exctabCell);
+                            }
+                            data.attr("title", inputText);
+                        }
+                    }
+                }
+            }
+        }
+        //System.out.println(zikey);
+        // 去掉重复的数
+        Map<String, String> groupMap2 = colTitle.stream()
+                .collect(Collectors.groupingBy(ExctabCell::getTextInfo, Collectors.mapping(ExctabCell::getXys, Collectors.joining(","))));
+
+        exctabCellService.DeletExcelByTableId(excelId + "");
+
+        List<ExctabCell> colTitle2 = new ArrayList<>();
+        for (String title : groupMap2.keySet()) {
+            ExctabCell exctabCell = new ExctabCell();
+            exctabCell.setExctabId(excelId);
+            exctabCell.setIsDeleted(0);
+            exctabCell.setTextInfo(title);
+            exctabCell.setCreateTime(new Date());
+
+            if (title.contains("日期") || title.contains("年") || title.contains("月") || title.contains("日")) {
+                //日期
+                exctabCell.setTextElementType(4);
+            } else {
+                //字符串
+                exctabCell.setTextElementType(1);
+            }
+
+            exctabCell.setXys(groupMap2.get(title));
+            colTitle2.add(exctabCell);
+        }
+        exctabCellService.saveBatch(colTitle2);
+
+
+        //对excel 的图片进行操作
+        ExcelTab exceltab = excelTabService.getById(excelId);
+        if (exceltab != null) {
+            // 获取excle 的数据
+            String fileUrl = exceltab.getFileUrl();
+            InputStream ossInputStream = CommonUtil.getOSSInputStream(fileUrl);
+            Workbook wb = new Workbook();
+            wb.loadFromMHtml(ossInputStream);
+            Worksheet sheet = wb.getWorksheets().get(0);
+            PicturesCollection pictures = sheet.getPictures();
+            if (pictures != null && pictures.size() >= 1) {
+                for (int i = 0; i < pictures.size(); i++) {
+                    ExcelPicture pic = pictures.get(i);
+                    int x = pic.getLeftColumn();
+                    int y = pic.getBottomRow();
+                    Elements select = doc.select("el-input[x1=" + x + "][y1=" + y + "]");
+                    System.out.println("xx=--" + x);
+                    System.out.println("yy=--" + y);
+                    if (select != null && select.size() >= 1) {
+                        Element element = select.get(0);
+                        Element elementP = element.parent();
+                        element.remove();
+                        Element imgele = imgs.get(i);
+                        imgele.removeAttr("class");
+                        elementP.append(imgele.toString());
+                    }
+                }
+            }
+
+            ossInputStream.close();
+        }
+        // 移除图片
+        imgs.remove();
+        // 保存
+        exceltab.setIsDeleted(8);
+        excelTabService.saveOrUpdate(exceltab);
+        File writefile = new File(thmlUrl);
+        FileUtil.writeToFile(writefile, doc.html(), Boolean.parseBoolean("UTF-8"));
+    }
+
+    //计算区域坐标
+    public static String getTrInfo(Elements tds, Map<String, String> styleMap, boolean index_state, Integer xy_type, int maxCol, int y, List<Map<String, String>> zikey) {
+
+        int x_width = 0;
+        int y_width = 0;
+        int text_width = 0;
+        int width = 0;
+
+        int null_count = 0;
+        int val_count = 0;
+
+        boolean istrue = true;
+
+        // 上 tr 长度
+
+        List<Map<String, String>> maxList = zikey.stream().filter(map -> Integer.parseInt(map.get("y1")) <= y && y <= Integer.parseInt(map.get("y2"))).collect(Collectors.toList());
+
+        int top1_max = 0;
+        if (maxList != null && maxList.size() >= 1) {
+            top1_max = maxList.stream().mapToInt(m -> Integer.parseInt(m.get("x2"))).max().getAsInt();
+        }
+
+
+        //区域计算
+        for (int j = 0; j < tds.size(); j++) {
+            Element data = tds.get(j);
+            String keyId = data.attr("class");
+            int colspan = data.attr("COLSPAN").equals("") ? 1 : Integer.parseInt(data.attr("COLSPAN"));
+            if (colspan == 0) {
+                colspan = data.attr("colspan").equals("") ? 1 : Integer.parseInt(data.attr("colspan"));
+            }
+            String classInfo = styleMap.get(keyId);
+            String textInfo = data.text().trim().replaceAll(" ", "");
+
+            if (classInfo == null) {
+                classInfo = data.attr("style");
+            } else {
+                data.removeAttr("class");
+                data.attr("style", styleMap.get(keyId).replaceAll("break-word", "inherit"));
+            }
+
+            // 计算线开始
+            if (classInfo.indexOf("border-left-style") >= 0 && classInfo.indexOf("border-top-style") >= 0 && classInfo.indexOf("border-right-style") >= 0) {
+                x_width += colspan;
+            }
+
+            // 计算结束
+            if (classInfo.indexOf("border-left-style") < 0 && (classInfo.indexOf("border-top-style") < 0 || classInfo.indexOf("border-top-style") >= 0) && classInfo.indexOf("border-bottom-style") < 0 && classInfo.indexOf("border-right-style") < 0) {
+                y_width += colspan;
+            }
+
+            String name = data.text();
+            if (!name.isEmpty()) {
+                text_width += colspan;
+            }
+            width += colspan;
+
+            if (!textInfo.isEmpty() && !(textInfo.equals("/") && textInfo.length() <= 2) && !(textInfo.indexOf("年") >= 0 && textInfo.indexOf("月") >= 0 && textInfo.indexOf("日") >= 0) && !textInfo.equals("—") && !textInfo.equals("-")) {  // 标题区域
+                val_count++;
+            } else {
+                null_count++;
+            }
+        }
+
+        // 在区域内
+        //  System.out.println(index_state+"——"+y+"__"+x_width);
+
+        if (index_state) {
+            //是否需要改变
+            if (maxCol == y_width) { // 是否结束区域值
+                index_state = false;
+                xy_type += 1;
+            }
+            if (maxCol == text_width && top1_max != text_width) { // 是否区域开始时
+                xy_type += 1;
+            }
+        } else { // 区域外
+            if (maxCol == x_width) {
+                index_state = true;
+                xy_type += 1;
+            }
+        }
+
+        // 空是否等于值的个数
+        istrue = null_count == val_count && width == maxCol;
+        return xy_type + "," + index_state + "," + width + "," + istrue;
+    }
+
+    // 获取解析样式
+    public static Map<String, String> getHtmlStyle(Document doc) {
+        Map<String, String> styleMap = new HashMap<>();
+        Element style = doc.select("style").first();
+        Matcher cssMatcher = Pattern.compile("(\\w+)\\s*[{]([^}]+)[}]").matcher(style.html());
+        while (cssMatcher.find()) {
+            styleMap.put(cssMatcher.group(1), cssMatcher.group(2));
+        }
+        return styleMap;
+    }
+
     /**
      * 清表生成html
      */

+ 8 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/feign/WbsTreeContractClientImpl.java

@@ -499,5 +499,13 @@ public class WbsTreeContractClientImpl implements WbsTreeContractClient {
         wbsTreeContractController.saveContractNameRule(s,pKeyId,projectId);
     }
 
+    @Override
+    public Integer findIsExistTreeNode(List<String> ids) {
+        return wbsTreeContractService.findIsExistTreeNode(ids);
+    }
 
+    @Override
+    public List<WbsTreeContract> queryListByPIds(List<Long> pIds) {
+        return wbsTreeContractService.queryListByPIds(pIds);
+    }
 }

+ 24 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/feign/WbsTreeContractOldHtmlClientImpl.java

@@ -0,0 +1,24 @@
+package org.springblade.manager.feign;
+
+import lombok.AllArgsConstructor;
+import org.springblade.manager.entity.WbsTreeContractOldHtml;
+import org.springblade.manager.service.WbsTreeContractOldHtmlService;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+/**
+ * @author LHB
+ */
+@RestController
+@AllArgsConstructor
+public class WbsTreeContractOldHtmlClientImpl implements WbsTreeContractOldHtmlClient {
+    @Resource
+    private WbsTreeContractOldHtmlService wbsTreeContractOldHtmlService;
+
+    @Override
+    public Boolean save(List<WbsTreeContractOldHtml> data) {
+        return wbsTreeContractOldHtmlService.saveBatch(data);
+    }
+}

+ 18 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsTreeContractOldHtmlMapper.java

@@ -0,0 +1,18 @@
+package org.springblade.manager.mapper;
+
+import org.springblade.manager.entity.WbsTreeContractOldHtml;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+* @author LHB
+* @description 针对表【m_wbs_tree_contract_old_html(合同段表单上报之前的html记录)】的数据库操作Mapper
+* @createDate 2025-07-01 17:37:36
+* @Entity generator.domain.MWbsTreeContractOldHtml
+*/
+public interface WbsTreeContractOldHtmlMapper extends BaseMapper<WbsTreeContractOldHtml> {
+
+}
+
+
+
+

+ 22 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsTreeContractOldHtmlMapper.xml

@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="org.springblade.manager.mapper.WbsTreeContractOldHtmlMapper">
+
+    <resultMap id="BaseResultMap" type="org.springblade.manager.entity.WbsTreeContractOldHtml">
+            <id property="id" column="id" />
+            <result property="contractFormId" column="contract_form_id" />
+            <result property="oldHtmlUrl" column="old_html_url" />
+            <result property="isDeleted" column="is_deleted" />
+            <result property="createTime" column="create_time" />
+            <result property="createUser" column="create_user" />
+            <result property="updateTime" column="update_time" />
+            <result property="updateUser" column="update_user" />
+    </resultMap>
+
+    <sql id="Base_Column_List">
+        id,contract_form_id,old_html_url,is_deleted,create_time,create_user,
+        update_time,update_user
+    </sql>
+</mapper>

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

@@ -92,4 +92,6 @@ public interface IWbsTreeContractService extends BaseService<WbsTreeContract> {
     boolean checkNodeAllDate(WbsTreeContract contract);
 
     List<APIWbsContractSubdivisionVo> getWbsContractSubdivision(String contractId);
+
+    List<WbsTreeContract> queryListByPIds(List<Long> pIds);
 }

+ 13 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/service/WbsTreeContractOldHtmlService.java

@@ -0,0 +1,13 @@
+package org.springblade.manager.service;
+
+import org.springblade.manager.entity.WbsTreeContractOldHtml;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+* @author LHB
+* @description 针对表【m_wbs_tree_contract_old_html(合同段表单上报之前的html记录)】的数据库操作Service
+* @createDate 2025-07-01 17:37:36
+*/
+public interface WbsTreeContractOldHtmlService extends IService<WbsTreeContractOldHtml> {
+
+}

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

@@ -137,6 +137,8 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
     private final TrialSelfInspectionRecordClient trialSelfInspectionRecordClient;
     // excel 解析结构
     private final IExctabCellService exctabCellService;
+    private final WbsTreeContractOldHtmlService wbsTreeContractOldHtmlService;
+
 
     @Autowired
     StringRedisTemplate RedisTemplate;
@@ -1509,6 +1511,15 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
         String keyNameList="";
         // 匹配关联
         try {
+            // 这里先从旧html表中获取  如果有用旧的html m_wbs_tree_contract_old_html
+            WbsTreeContractOldHtml oldHtml = wbsTreeContractOldHtmlService.getOne(Wrappers.<WbsTreeContractOldHtml>lambdaQuery()
+                    .eq(WbsTreeContractOldHtml::getContractFormId, pkeyId)
+                    .eq(WbsTreeContractOldHtml::getIsDeleted, 0)
+                    .last("limit 1"));
+            if(oldHtml != null){
+                wbsTreeContract.setHtmlUrl(oldHtml.getOldHtmlUrl());
+            }
+
             InputStream inputStreamByUrl = FileUtils.getInputStreamByUrl(wbsTreeContract.getHtmlUrl());
             String htmlString = IoUtil.readToString(inputStreamByUrl);
             Document doc = Jsoup.parse(htmlString);

+ 22 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreeContractOldHtmlServiceImpl.java

@@ -0,0 +1,22 @@
+package org.springblade.manager.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springblade.manager.entity.WbsTreeContractOldHtml;
+import org.springblade.manager.service.WbsTreeContractOldHtmlService;
+import org.springblade.manager.mapper.WbsTreeContractOldHtmlMapper;
+import org.springframework.stereotype.Service;
+
+/**
+* @author LHB
+* @description 针对表【m_wbs_tree_contract_old_html(合同段表单上报之前的html记录)】的数据库操作Service实现
+* @createDate 2025-07-01 17:37:36
+*/
+@Service
+public class WbsTreeContractOldHtmlServiceImpl extends ServiceImpl<WbsTreeContractOldHtmlMapper, WbsTreeContractOldHtml>
+    implements WbsTreeContractOldHtmlService {
+
+}
+
+
+
+

+ 6 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreeContractServiceImpl.java

@@ -4468,4 +4468,10 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
             }
         }
     }
+    @Override
+    public List<WbsTreeContract> queryListByPIds(List<Long> pIds) {
+        return baseMapper.selectList(Wrappers.<WbsTreeContract>lambdaQuery()
+                .in(WbsTreeContract::getPId, pIds)
+                .eq(WbsTreeContract::getIsDeleted, 0));
+    }
 }