瀏覽代碼

绑定特性

laibulaizheli 3 天之前
父節點
當前提交
b249029813

+ 55 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/WbsDivide.java

@@ -0,0 +1,55 @@
+package org.springblade.manager.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.springblade.core.mp.base.BaseEntity;
+
+/**
+ * WBS划分实体类
+ */
+@Data
+@TableName("m_wbs_divide")
+@EqualsAndHashCode(callSuper = true)
+public class WbsDivide extends BaseEntity {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 关联键ID
+     */
+    private Long pKeyId;
+
+    /**
+     * 划分ID
+     */
+    private String divideId;
+
+    /**
+     * 名称
+     */
+    private String name;
+
+    /**
+     * 父级ID
+     */
+    private String parentId;
+
+    /**
+     * 合同段ID
+     */
+    private String contractId;
+
+    /**
+     * 划分编号
+     */
+    private String divideNum;
+
+    /**
+     * 项目ID
+     */
+    private String projectId;
+
+}
+
+

+ 29 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/DivideClientReq.java

@@ -0,0 +1,29 @@
+package org.springblade.manager.vo;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * WBS划分客户端请求对象
+ */
+@Data
+public class DivideClientReq implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 合同段ID
+     */
+    private String contractId;
+
+    /**
+     * 树节点列表
+     */
+    private List<DivideClientVo> trees = new ArrayList<>();
+
+}
+
+

+ 47 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/DivideClientVo.java

@@ -0,0 +1,47 @@
+package org.springblade.manager.vo;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * WBS划分客户端视图对象
+ */
+@Data
+public class DivideClientVo implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * ID
+     */
+    private String id;
+
+    /**
+     * 名称
+     */
+    private String name;
+
+    /**
+     * 父级ID
+     */
+    private String parentId;
+
+    /**
+     * 合同段ID
+     */
+    private String contractId;
+
+    /**
+     * 划分编号
+     */
+    private String divideNum;
+
+    /**
+     * 是否已绑定(前端展示用)
+     */
+    private Boolean binded;
+
+}
+
+

+ 188 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/WbsDivideController.java

@@ -0,0 +1,188 @@
+package org.springblade.manager.controller;
+
+import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springblade.core.boot.ctrl.BladeController;
+import org.springblade.core.tool.api.R;
+import org.springblade.manager.entity.WbsDivide;
+import org.springblade.manager.service.IWbsDivideService;
+import org.springblade.manager.vo.DivideClientReq;
+import org.springblade.manager.vo.DivideClientVo;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * WBS划分 控制器
+ *
+ * @author BladeX
+ */
+@Slf4j
+@RestController
+@AllArgsConstructor
+@RequestMapping("/wbsDivide")
+@Api(value = "WBS划分管理", tags = "WBS划分管理接口")
+public class WbsDivideController extends BladeController {
+
+    private final IWbsDivideService wbsDivideService;
+
+    /**
+     * 获取第三方树节点(带已关联状态标识)
+     */
+    @GetMapping("/getChildNodes")
+    @ApiOperationSupport(order = 1)
+    @ApiOperation(value = "获取第三方树节点", notes = "传入pKeyId、contractId、parentId")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "pKeyId", value = "WBS节点ID", required = true, dataType = "Long"),
+            @ApiImplicitParam(name = "contractId", value = "合同段ID", required = true, dataType = "String"),
+            @ApiImplicitParam(name = "parentId", value = "父节点ID(根节点传0)", required = true, dataType = "String")
+    })
+    public R<List<DivideClientVo>> getChildNodes(@RequestParam Long pKeyId,
+                                                   @RequestParam String contractId,
+                                                   @RequestParam String parentId) {
+        try {
+            // 调用第三方接口获取子节点
+            DivideClientReq divideClientReq = wbsDivideService.getChildNodes(contractId, parentId);
+            
+            if (divideClientReq == null || divideClientReq.getTrees() == null) {
+                return R.data(null);
+            }
+
+            List<DivideClientVo> trees = divideClientReq.getTrees();
+            
+            // 查询当前pKeyId已关联的divideId列表
+            List<String> bindedDivideIds = wbsDivideService.getBindedDivideIds(pKeyId);
+            
+            // 标记哪些节点已关联
+            for (DivideClientVo vo : trees) {
+                if (bindedDivideIds.contains(vo.getId())) {
+                    vo.setBinded(true);
+                    log.debug("节点 {} 已关联", vo.getId());
+                } else {
+                    vo.setBinded(false);
+                }
+            }
+            
+            return R.data(trees);
+        } catch (Exception e) {
+            log.error("获取第三方树节点失败,pKeyId={}, contractId={}, parentId={}, error={}", 
+                    pKeyId, contractId, parentId, e.getMessage(), e);
+            return R.fail("获取第三方树节点失败:" + e.getMessage());
+        }
+    }
+
+    /**
+     * 批量绑定节点
+     */
+    @PostMapping("/batchBind")
+    @ApiOperationSupport(order = 2)
+    @ApiOperation(value = "批量绑定节点", notes = "传入pKeyId、projectId、contractId和节点列表")
+    public R<Integer> batchBind(@RequestParam Long pKeyId,
+                                 @RequestParam String projectId,
+                                 @RequestParam String contractId,
+                                 @RequestBody List<DivideClientVo> divideClientVos) {
+        try {
+            int successCount = wbsDivideService.batchBind(pKeyId, divideClientVos, projectId, contractId);
+            return R.data(successCount, "成功绑定 " + successCount + " 个节点");
+        } catch (Exception e) {
+            log.error("批量绑定节点失败,pKeyId={}, error={}", pKeyId, e.getMessage(), e);
+            return R.fail("批量绑定节点失败:" + e.getMessage());
+        }
+    }
+
+    /**
+     * 解绑定节点
+     */
+    @PostMapping("/unbind")
+    @ApiOperationSupport(order = 3)
+    @ApiOperation(value = "解绑定节点", notes = "传入pKeyId和divideId")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "pKeyId", value = "WBS节点ID", required = true, dataType = "Long"),
+            @ApiImplicitParam(name = "divideId", value = "划分ID", required = true, dataType = "String")
+    })
+    public R<Boolean> unbind(@RequestParam Long pKeyId, @RequestParam String divideId) {
+        try {
+            boolean result = wbsDivideService.unbind(divideId, pKeyId);
+            return R.status(result);
+        } catch (Exception e) {
+            log.error("解绑定节点失败,pKeyId={}, divideId={}, error={}", 
+                    pKeyId, divideId, e.getMessage(), e);
+            return R.fail("解绑定节点失败:" + e.getMessage());
+        }
+    }
+
+    /**
+     * 查询已绑定的节点列表
+     */
+    @GetMapping("/getBindedNodes")
+    @ApiOperationSupport(order = 4)
+    @ApiOperation(value = "查询已绑定的节点列表", notes = "传入pKeyId")
+    @ApiImplicitParam(name = "pKeyId", value = "WBS节点ID", required = true, dataType = "Long")
+    public R<List<WbsDivide>> getBindedNodes(@RequestParam Long pKeyId) {
+        try {
+            List<WbsDivide> list = wbsDivideService.getByPKeyId(pKeyId);
+            return R.data(list);
+        } catch (Exception e) {
+            log.error("查询已绑定节点失败,pKeyId={}, error={}", pKeyId, e.getMessage(), e);
+            return R.fail("查询已绑定节点失败:" + e.getMessage());
+        }
+    }
+
+    /**
+     * 查询已绑定的divideId列表
+     */
+    @GetMapping("/getBindedDivideIds")
+    @ApiOperationSupport(order = 5)
+    @ApiOperation(value = "查询已绑定的divideId列表", notes = "传入pKeyId")
+    @ApiImplicitParam(name = "pKeyId", value = "WBS节点ID", required = true, dataType = "Long")
+    public R<List<String>> getBindedDivideIds(@RequestParam Long pKeyId) {
+        try {
+            List<String> divideIds = wbsDivideService.getBindedDivideIds(pKeyId);
+            return R.data(divideIds);
+        } catch (Exception e) {
+            log.error("查询已绑定divideId列表失败,pKeyId={}, error={}", pKeyId, e.getMessage(), e);
+            return R.fail("查询已绑定divideId列表失败:" + e.getMessage());
+        }
+    }
+
+    /**
+     * 根据划分编号查询
+     */
+    @GetMapping("/getByDivideNum")
+    @ApiOperationSupport(order = 6)
+    @ApiOperation(value = "根据划分编号查询", notes = "传入divideNum")
+    @ApiImplicitParam(name = "divideNum", value = "划分编号", required = true, dataType = "String")
+    public R<List<WbsDivide>> getByDivideNum(@RequestParam String divideNum) {
+        try {
+            List<WbsDivide> list = wbsDivideService.getByDivideNum(divideNum);
+            return R.data(list);
+        } catch (Exception e) {
+            log.error("根据划分编号查询失败,divideNum={}, error={}", divideNum, e.getMessage(), e);
+            return R.fail("查询失败:" + e.getMessage());
+        }
+    }
+
+    /**
+     * 根据划分编号获取PDF URL列表
+     */
+    @GetMapping("/getPdfUrlsByDivideNum")
+    @ApiOperationSupport(order = 7)
+    @ApiOperation(value = "根据划分编号获取PDF URL列表", notes = "传入divideNum,返回对应的PDF URL列表")
+    @ApiImplicitParam(name = "divideNum", value = "划分编号", required = true, dataType = "String")
+    public R<List<String>> getPdfUrlsByDivideNum(@RequestParam String divideNum) {
+        try {
+            List<String> pdfUrls = wbsDivideService.getPdfUrlsByDivideNum(divideNum);
+            return R.data(pdfUrls, "成功获取 " + pdfUrls.size() + " 个PDF URL");
+        } catch (Exception e) {
+            log.error("根据划分编号获取PDF URL列表失败,divideNum={}, error={}", divideNum, e.getMessage(), e);
+            return R.fail("获取PDF URL列表失败:" + e.getMessage());
+        }
+    }
+
+}
+

+ 50 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsDivideMapper.java

@@ -0,0 +1,50 @@
+package org.springblade.manager.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Param;
+import org.springblade.manager.entity.WbsDivide;
+
+import java.util.List;
+
+/**
+ * WBS划分 Mapper 接口
+ */
+public interface WbsDivideMapper extends BaseMapper<WbsDivide> {
+
+    /**
+     * 根据pKeyId查询所有记录
+     *
+     * @param pKeyId 关联键ID
+     * @return 记录列表
+     */
+    List<WbsDivide> selectByPKeyId(@Param("pKeyId") Long pKeyId);
+
+    /**
+     * 根据divideNum查询所有记录
+     *
+     * @param divideNum 划分编号
+     * @return 记录列表
+     */
+    List<WbsDivide> selectByDivideNum(@Param("divideNum") String divideNum);
+
+    /**
+     * 检查是否存在相同的pKeyId和divideId的记录
+     *
+     * @param pKeyId   关联键ID
+     * @param divideId 划分ID
+     * @return 记录数
+     */
+    Integer checkExists(@Param("pKeyId") Long pKeyId, @Param("divideId") String divideId);
+
+    /**
+     * 解绑定,设置isDeleted为1
+     *
+     * @param divideId 划分ID
+     * @param pKeyId   关联键ID
+     * @return 影响行数
+     */
+    Integer unbind(@Param("divideId") String divideId, @Param("pKeyId") Long pKeyId);
+
+}
+
+

+ 59 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsDivideMapper.xml

@@ -0,0 +1,59 @@
+<?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.WbsDivideMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="wbsDivideResultMap" type="org.springblade.manager.entity.WbsDivide">
+        <id column="id" property="id"/>
+        <result column="create_time" property="createTime"/>
+        <result column="create_user" property="createUser"/>
+        <result column="create_dept" property="createDept"/>
+        <result column="update_user" property="updateUser"/>
+        <result column="update_time" property="updateTime"/>
+        <result column="status" property="status"/>
+        <result column="is_deleted" property="isDeleted"/>
+        <result column="p_key_id" property="pKeyId"/>
+        <result column="divide_id" property="divideId"/>
+        <result column="name" property="name"/>
+        <result column="parent_id" property="parentId"/>
+        <result column="contract_id" property="contractId"/>
+        <result column="divide_num" property="divideNum"/>
+        <result column="project_id" property="projectId"/>
+    </resultMap>
+
+    <!-- 根据pKeyId查询所有记录 -->
+    <select id="selectByPKeyId" resultMap="wbsDivideResultMap">
+        SELECT *
+        FROM m_wbs_divide
+        WHERE p_key_id = #{pKeyId}
+          AND is_deleted = 0
+    </select>
+
+    <!-- 根据divideNum查询所有记录 -->
+    <select id="selectByDivideNum" resultMap="wbsDivideResultMap">
+        SELECT *
+        FROM m_wbs_divide
+        WHERE divide_num = #{divideNum}
+          AND is_deleted = 0
+    </select>
+
+    <!-- 检查是否存在相同的pKeyId和divideId的记录 -->
+    <select id="checkExists" resultType="java.lang.Integer">
+        SELECT COUNT(1)
+        FROM m_wbs_divide
+        WHERE p_key_id = #{pKeyId}
+          AND divide_id = #{divideId}
+          AND is_deleted = 0
+    </select>
+
+    <!-- 解绑定,设置isDeleted为1 -->
+    <update id="unbind">
+        UPDATE m_wbs_divide
+        SET is_deleted = 1
+        WHERE divide_id = #{divideId}
+          AND p_key_id = #{pKeyId}
+    </update>
+
+</mapper>
+
+

+ 92 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/service/IWbsDivideService.java

@@ -0,0 +1,92 @@
+package org.springblade.manager.service;
+
+import org.springblade.core.mp.base.BaseService;
+import org.springblade.manager.entity.WbsDivide;
+import org.springblade.manager.vo.DivideClientReq;
+import org.springblade.manager.vo.DivideClientVo;
+
+import java.util.List;
+
+/**
+ * WBS划分 Service 接口
+ */
+public interface IWbsDivideService extends BaseService<WbsDivide> {
+
+    /**
+     * 根据pKeyId查询所有记录
+     *
+     * @param pKeyId 关联键ID
+     * @return 记录列表
+     */
+    List<WbsDivide> getByPKeyId(Long pKeyId);
+
+    /**
+     * 绑定,生成一条记录
+     * 如果有pKeyId和divideId完全相同的记录则不生成
+     *
+     * @param pKeyId         关联键ID
+     * @param divideClientVo 划分客户端VO
+     * @param projectId      项目ID
+     * @param contractId     合同段ID
+     * @return 是否成功
+     */
+    boolean bind(Long pKeyId, DivideClientVo divideClientVo, String projectId, String contractId);
+
+    /**
+     * 解绑定,将对应的记录isDeleted设置成1
+     *
+     * @param divideId 划分ID
+     * @param pKeyId   关联键ID
+     * @return 是否成功
+     */
+    boolean unbind(String divideId, Long pKeyId);
+
+    /**
+     * 根据divideNum查询所有记录
+     *
+     * @param divideNum 划分编号
+     * @return 记录列表
+     */
+    List<WbsDivide> getByDivideNum(String divideNum);
+
+    /**
+     * 根据contractId和parentId获取子节点
+     * 通过HTTP接口调用 http://127.0.0.1/fengjian/getChildNodes
+     *
+     * @param contractId 合同段ID
+     * @param parentId   父节点ID
+     * @return 子节点数据
+     */
+    DivideClientReq getChildNodes(String contractId, String parentId);
+
+    /**
+     * 批量绑定节点
+     *
+     * @param pKeyId          关联键ID
+     * @param divideClientVos 划分客户端VO列表
+     * @param projectId       项目ID
+     * @param contractId      合同段ID
+     * @return 成功绑定的数量
+     */
+    int batchBind(Long pKeyId, List<DivideClientVo> divideClientVos, String projectId, String contractId);
+
+    /**
+     * 查询指定pKeyId已关联的所有divideId列表
+     *
+     * @param pKeyId 关联键ID
+     * @return divideId列表
+     */
+    List<String> getBindedDivideIds(Long pKeyId);
+
+    /**
+     * 根据divideNum查询所有记录的pKeyId,并获取对应的PDF URL列表
+     *
+     * @param divideNum 划分编号
+     * @return PDF URL列表
+     */
+    List<String> getPdfUrlsByDivideNum(String divideNum);
+
+    void testCompleteFlow();
+
+}
+

+ 293 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsDivideServiceImpl.java

@@ -0,0 +1,293 @@
+package org.springblade.manager.service.impl;
+
+import com.alibaba.fastjson.JSON;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.http.HttpEntity;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.util.EntityUtils;
+import org.springblade.business.feign.InformationQueryClient;
+import org.springblade.core.mp.base.BaseServiceImpl;
+import org.springblade.manager.entity.WbsDivide;
+import org.springblade.manager.mapper.WbsDivideMapper;
+import org.springblade.manager.service.IWbsDivideService;
+import org.springblade.manager.vo.DivideClientReq;
+import org.springblade.manager.vo.DivideClientVo;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * WBS划分 Service 实现类
+ */
+@Slf4j
+@Service
+@AllArgsConstructor
+public class WbsDivideServiceImpl extends BaseServiceImpl<WbsDivideMapper, WbsDivide> implements IWbsDivideService {
+
+    private final InformationQueryClient informationQueryClient;
+
+    @Override
+    public List<WbsDivide> getByPKeyId(Long pKeyId) {
+        return baseMapper.selectByPKeyId(pKeyId);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public boolean bind(Long pKeyId, DivideClientVo divideClientVo, String projectId, String contractId) {
+        // 检查是否已存在相同的pKeyId和divideId的记录
+        Integer count = baseMapper.checkExists(pKeyId, divideClientVo.getId());
+        if (count != null && count > 0) {
+            // 已存在,不生成新记录
+            return false;
+        }
+
+        // 创建新记录
+        WbsDivide wbsDivide = new WbsDivide();
+        wbsDivide.setPKeyId(pKeyId);
+        wbsDivide.setDivideId(divideClientVo.getId());
+        wbsDivide.setName(divideClientVo.getName());
+        wbsDivide.setParentId(divideClientVo.getParentId());
+        wbsDivide.setContractId(contractId);
+        wbsDivide.setDivideNum(divideClientVo.getDivideNum());
+        wbsDivide.setProjectId(projectId);
+
+        return save(wbsDivide);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public boolean unbind(String divideId, Long pKeyId) {
+        Integer rows = baseMapper.unbind(divideId, pKeyId);
+        return rows != null && rows > 0;
+    }
+
+    @Override
+    public List<WbsDivide> getByDivideNum(String divideNum) {
+        return baseMapper.selectByDivideNum(divideNum);
+    }
+
+    @Override
+    public DivideClientReq getChildNodes(String contractId, String parentId) {
+        CloseableHttpClient httpClient = null;
+        CloseableHttpResponse response = null;
+        
+        try {
+            // 构建请求URL
+            String url = String.format("https://hccq.cqfjgs.com/fengjian/getChildNodes?contractId=%s&parentId=%s",
+                    contractId, parentId);
+            
+            // 创建HttpClient
+            httpClient = HttpClients.createDefault();
+            
+            // 创建HttpGet请求
+            HttpGet httpGet = new HttpGet(url);
+            
+            // 执行请求
+            response = httpClient.execute(httpGet);
+            
+            // 获取响应实体
+            HttpEntity entity = response.getEntity();
+            
+            if (entity != null) {
+                // 读取响应内容
+                String responseBody = EntityUtils.toString(entity, StandardCharsets.UTF_8);
+                
+                // 将JSON字符串转换为对象
+                DivideClientReq divideClientReq = JSON.parseObject(responseBody, DivideClientReq.class);
+                
+                return divideClientReq;
+            }
+            
+        } catch (Exception e) {
+            log.error("调用getChildNodes接口失败,contractId={}, parentId={}, error={}", 
+                    contractId, parentId, e.getMessage(), e);
+        } finally {
+            // 关闭资源
+            try {
+                if (response != null) {
+                    response.close();
+                }
+                if (httpClient != null) {
+                    httpClient.close();
+                }
+            } catch (IOException e) {
+                log.error("关闭HTTP连接失败", e);
+            }
+        }
+        
+        // 返回空对象
+        return new DivideClientReq();
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public int batchBind(Long pKeyId, List<DivideClientVo> divideClientVos, String projectId, String contractId) {
+        if (divideClientVos == null || divideClientVos.isEmpty()) {
+            return 0;
+        }
+
+        int successCount = 0;
+        for (DivideClientVo divideClientVo : divideClientVos) {
+            boolean result = bind(pKeyId, divideClientVo, projectId, contractId);
+            if (result) {
+                successCount++;
+            }
+        }
+        
+        log.info("批量绑定节点,pKeyId={}, 总数={}, 成功={}", pKeyId, divideClientVos.size(), successCount);
+        return successCount;
+    }
+
+    @Override
+    public List<String> getBindedDivideIds(Long pKeyId) {
+        List<WbsDivide> list = baseMapper.selectByPKeyId(pKeyId);
+        List<String> divideIds = new ArrayList<>();
+        if (list != null && !list.isEmpty()) {
+            for (WbsDivide wbsDivide : list) {
+                divideIds.add(wbsDivide.getDivideId());
+            }
+        }
+        return divideIds;
+    }
+
+    @Override
+    public List<String> getPdfUrlsByDivideNum(String divideNum) {
+        List<String> pdfUrls = new ArrayList<>();
+        
+        try {
+            // 1. 根据divideNum查询所有记录
+            List<WbsDivide> wbsDivideList = baseMapper.selectByDivideNum(divideNum);
+            
+            if (wbsDivideList == null || wbsDivideList.isEmpty()) {
+                log.warn("根据divideNum={}未查询到任何记录", divideNum);
+                return pdfUrls;
+            }
+            
+            log.info("根据divideNum={}查询到{}条记录", divideNum, wbsDivideList.size());
+            
+            // 2. 遍历所有记录,取出pKeyId
+            for (WbsDivide wbsDivide : wbsDivideList) {
+                Long pKeyId = wbsDivide.getPKeyId();
+                
+                if (pKeyId == null) {
+                    log.warn("记录id={}的pKeyId为空,跳过", wbsDivide.getId());
+                    continue;
+                }
+                
+                try {
+                    // 3. 使用informationQueryClient.getInfoByWbsId获取InformationQuery对象
+                    // 第二个参数classify传0
+                    org.springblade.business.entity.InformationQuery informationQuery = 
+                            informationQueryClient.getInfoByWbsId(pKeyId, 0);
+                    
+                    if (informationQuery != null && informationQuery.getPdfUrl() != null 
+                            && !informationQuery.getPdfUrl().trim().isEmpty()) {
+                        // 4. 取出pdfUrl添加到列表
+                        pdfUrls.add(informationQuery.getPdfUrl());
+                        log.debug("pKeyId={}对应的pdfUrl={}", pKeyId, informationQuery.getPdfUrl());
+                    } else {
+                        log.debug("pKeyId={}未查询到有效的pdfUrl", pKeyId);
+                    }
+                } catch (Exception e) {
+                    log.error("查询pKeyId={}的InformationQuery信息失败, error={}", pKeyId, e.getMessage(), e);
+                }
+            }
+            
+            log.info("根据divideNum={}最终获取到{}个pdfUrl", divideNum, pdfUrls.size());
+            
+        } catch (Exception e) {
+            log.error("根据divideNum={}获取PDF URL列表失败, error={}", divideNum, e.getMessage(), e);
+        }
+        
+        return pdfUrls;
+    }
+
+    public void testCompleteFlow() {
+        log.info("========== 开始测试完整流程 ==========");
+
+        // 1. 模拟WBS树节点的pKeyId
+        Long pKeyId = 1001L;
+        String projectId = "project_001";
+        String contractId = "54e8a314de8a493d9f08a9d3cf7c";
+
+        log.info("步骤1: 用户点击WBS树节点,pKeyId={}", pKeyId);
+
+        // 2. 获取第三方树的根节点(parentId为0)
+        log.info("步骤2: 获取第三方树根节点,contractId={}, parentId=0", contractId);
+        DivideClientReq rootNodes = this.getChildNodes(contractId, "0");
+
+        if (rootNodes != null && rootNodes.getTrees() != null && !rootNodes.getTrees().isEmpty()) {
+            log.info("获取到 {} 个根节点", rootNodes.getTrees().size());
+            log.info("根节点数据: {}", JSON.toJSONString(rootNodes.getTrees()));
+
+            // 3. 模拟用户展开第一个根节点,获取子节点
+            DivideClientVo firstRoot = rootNodes.getTrees().get(0);
+            log.info("步骤3: 用户展开根节点: {}, 获取子节点", firstRoot.getName());
+
+            DivideClientReq childNodes = this.getChildNodes(contractId, firstRoot.getId());
+            if (childNodes != null && childNodes.getTrees() != null) {
+                log.info("获取到 {} 个子节点", childNodes.getTrees().size());
+            }
+
+            // 4. 模拟用户勾选部分节点进行绑定
+            log.info("步骤4: 用户勾选节点并保存");
+            List<DivideClientVo> selectedNodes = new ArrayList<>();
+
+            // 假设用户勾选了前2个节点
+            int selectCount = Math.min(2, childNodes.getTrees().size());
+            for (int i = 0; i < selectCount; i++) {
+                selectedNodes.add(childNodes.getTrees().get(i));
+            }
+
+            log.info("用户勾选了 {} 个节点", selectedNodes.size());
+
+            // 5. 执行批量绑定
+            int successCount = this.batchBind(pKeyId, selectedNodes, projectId, contractId);
+            log.info("步骤5: 批量绑定完成,成功绑定 {} 个节点", successCount);
+
+            // 6. 查询已绑定的节点
+            log.info("步骤6: 查询已绑定的节点");
+            List<WbsDivide> bindedNodes = this.getByPKeyId(pKeyId);
+            log.info("查询到 {} 个已绑定节点", bindedNodes.size());
+            for (WbsDivide node : bindedNodes) {
+                log.info("已绑定节点: divideId={}, name={}, divideNum={}",
+                        node.getDivideId(), node.getName(), node.getDivideNum());
+            }
+
+            // 7. 查询已绑定的divideId列表(用于前端标记已关联状态)
+            log.info("步骤7: 查询已绑定的divideId列表");
+            List<String> bindedDivideIds = this.getBindedDivideIds(pKeyId);
+            log.info("已绑定的divideId列表: {}", bindedDivideIds);
+
+            // 8. 模拟用户解绑第一个节点
+            if (!bindedNodes.isEmpty()) {
+                log.info("步骤8: 用户解绑第一个节点");
+                WbsDivide firstNode = bindedNodes.get(0);
+                boolean unbindResult = this.unbind(firstNode.getDivideId(), pKeyId);
+                log.info("解绑结果: {}, divideId={}", unbindResult, firstNode.getDivideId());
+
+                // 9. 再次查询已绑定节点,验证解绑结果
+                log.info("步骤9: 再次查询已绑定节点");
+                List<WbsDivide> remainingNodes = this.getByPKeyId(pKeyId);
+                log.info("剩余已绑定节点数: {}", remainingNodes.size());
+            }
+
+        } else {
+            log.warn("未能从第三方接口获取到树节点数据");
+            log.info("模拟数据进行测试...");
+
+        }
+
+        log.info("========== 测试完整流程结束 ==========");
+    }
+
+}
+