|  | @@ -28,12 +28,12 @@
 | 
	
		
			
				|  |  |                                  :data="treeData"
 | 
	
		
			
				|  |  |                                  :props="treeProps"
 | 
	
		
			
				|  |  |                                  :default-expand-all="false"
 | 
	
		
			
				|  |  | -                        
 | 
	
		
			
				|  |  |                                  :filter-node-method="filterNode"
 | 
	
		
			
				|  |  |                                  :load="loadNode"  
 | 
	
		
			
				|  |  |                                  lazy  
 | 
	
		
			
				|  |  |                                  node-key="id"
 | 
	
		
			
				|  |  |                                  check-strictly
 | 
	
		
			
				|  |  | +                                :default-checked-keys="defaultCheckedKeys" 
 | 
	
		
			
				|  |  |                                  @node-click="handleNodeClick"
 | 
	
		
			
				|  |  |                              >
 | 
	
		
			
				|  |  |                                  <!-- 自定义节点内容,使用单选框 -->
 | 
	
	
		
			
				|  | @@ -65,6 +65,7 @@
 | 
	
		
			
				|  |  |  import { ref, watch } from 'vue'
 | 
	
		
			
				|  |  |  import wbsApi from '~api/data-fill/wbs'
 | 
	
		
			
				|  |  |  import { getArrValue, getObjValue } from 'js-fast-way'
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  // 接收父组件传入的属性
 | 
	
		
			
				|  |  |  const props = defineProps({
 | 
	
		
			
				|  |  |      pKeyId:{
 | 
	
	
		
			
				|  | @@ -77,6 +78,7 @@ const pKeyId = ref(props.pKeyId)
 | 
	
		
			
				|  |  |  watch(() => props.pKeyId, (val) => {
 | 
	
		
			
				|  |  |      pKeyId.value = val
 | 
	
		
			
				|  |  |  })
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  // 对话框显示状态
 | 
	
		
			
				|  |  |  const linkModal = defineModel('modelValue', {
 | 
	
		
			
				|  |  |      default: false,
 | 
	
	
		
			
				|  | @@ -92,12 +94,21 @@ const sourceData = ref([
 | 
	
		
			
				|  |  |      { id: '119739d00e974214acd85b3ad661', name: '六工区' },
 | 
	
		
			
				|  |  |      { id: 'cc10f104ddb64320ab59ac7abec9', name: '二期工程' },
 | 
	
		
			
				|  |  |  ])
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// 新增:默认选中的节点ID数组
 | 
	
		
			
				|  |  | +const defaultCheckedKeys = ref([])
 | 
	
		
			
				|  |  | +// 新增:用于存储所有已加载的节点数据,方便查找binded状态
 | 
	
		
			
				|  |  | +const allLoadedNodes = ref({})
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  // 监听左侧工区变化,重新加载根节点数据
 | 
	
		
			
				|  |  |  watch(leftRadio, (newVal) => {
 | 
	
		
			
				|  |  | +    defaultCheckedKeys.value = [] // 清空默认选中
 | 
	
		
			
				|  |  | +    allLoadedNodes.value = {} // 清空已加载节点缓存
 | 
	
		
			
				|  |  |      loadRootNodes(newVal)
 | 
	
		
			
				|  |  |      selectedNodeId.value = ''
 | 
	
		
			
				|  |  |      selectedNodeData.value = null
 | 
	
		
			
				|  |  |  })
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  // 搜索关键词
 | 
	
		
			
				|  |  |  const queryValue = ref('')
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -111,7 +122,7 @@ const selectedNodeId = ref(null)
 | 
	
		
			
				|  |  |  const treeProps = {
 | 
	
		
			
				|  |  |      label: 'name',
 | 
	
		
			
				|  |  |      children: 'children',
 | 
	
		
			
				|  |  | -    isLeaf: 'isLeaf', // 新增isLeaf字段判断是否为叶子节点
 | 
	
		
			
				|  |  | +    isLeaf: 'isLeaf',
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  // 树形数据 - 初始只存放根节点
 | 
	
	
		
			
				|  | @@ -120,73 +131,96 @@ const treeData = ref([])
 | 
	
		
			
				|  |  |  // 监听对话框显示状态
 | 
	
		
			
				|  |  |  watch(() => linkModal.value, (val) => {
 | 
	
		
			
				|  |  |      if (val) {
 | 
	
		
			
				|  |  | -        // 对话框打开时的初始化操作
 | 
	
		
			
				|  |  |          selectedNodeId.value = ''
 | 
	
		
			
				|  |  |          queryValue.value = ''
 | 
	
		
			
				|  |  | -      
 | 
	
		
			
				|  |  | +        defaultCheckedKeys.value = []
 | 
	
		
			
				|  |  | +        allLoadedNodes.value = {}
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  })
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  // 加载根节点数据
 | 
	
		
			
				|  |  |  const loadRootNodes = async (workArea) => {
 | 
	
		
			
				|  |  | -  // 清空现有树形数据
 | 
	
		
			
				|  |  |    treeData.value = []
 | 
	
		
			
				|  |  | -  // 重置选中节点ID
 | 
	
		
			
				|  |  |    selectedNodeId.value = ''
 | 
	
		
			
				|  |  |    
 | 
	
		
			
				|  |  | -  if (!workArea) return // 如果没有选中工区则不加载
 | 
	
		
			
				|  |  | +  if (!workArea) return
 | 
	
		
			
				|  |  |    
 | 
	
		
			
				|  |  |    try {
 | 
	
		
			
				|  |  | -    // 加载根节点(parentId设为0表示根节点)
 | 
	
		
			
				|  |  |      const { data } = await wbsApi.getChildNodes({
 | 
	
		
			
				|  |  |        contractId: workArea,
 | 
	
		
			
				|  |  |        pKeyId: pKeyId.value || '',
 | 
	
		
			
				|  |  | -      parentId: 0, // 明确请求根节点数据
 | 
	
		
			
				|  |  | +      parentId: 0,
 | 
	
		
			
				|  |  |      })
 | 
	
		
			
				|  |  |      
 | 
	
		
			
				|  |  | -    // 设置根节点数据
 | 
	
		
			
				|  |  | -    treeData.value = getArrValue(data)
 | 
	
		
			
				|  |  | -    // 重置树形组件状态
 | 
	
		
			
				|  |  | +    const nodes = getArrValue(data)
 | 
	
		
			
				|  |  | +    treeData.value = nodes
 | 
	
		
			
				|  |  | +    // 处理根节点中的binded状态
 | 
	
		
			
				|  |  | +    handleBindedNodes(nodes)
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  |      if (treeRef.value) {
 | 
	
		
			
				|  |  | -        console.log(treeRef.value, 'treeRef.value.')
 | 
	
		
			
				|  |  | - 
 | 
	
		
			
				|  |  | -      treeRef.value.setCheckedKeys([])
 | 
	
		
			
				|  |  | +      treeRef.value.setCheckedKeys(defaultCheckedKeys.value)
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |    } catch (error) {
 | 
	
		
			
				|  |  |      console.error('加载根节点失败:', error)
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  | -// 懒加载节点方法
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +// 新增:处理节点数据中的binded状态
 | 
	
		
			
				|  |  | +const handleBindedNodes = (nodes) => {
 | 
	
		
			
				|  |  | +    nodes.forEach(node => {
 | 
	
		
			
				|  |  | +        // 缓存所有节点数据
 | 
	
		
			
				|  |  | +        allLoadedNodes.value[node.id] = node
 | 
	
		
			
				|  |  | +        
 | 
	
		
			
				|  |  | +        // 如果节点binded为true,添加到默认选中
 | 
	
		
			
				|  |  | +        if (node.binded) {
 | 
	
		
			
				|  |  | +            defaultCheckedKeys.value.push(node.id)
 | 
	
		
			
				|  |  | +            // 如果是单选场景,直接选中最后一个binded为true的节点
 | 
	
		
			
				|  |  | +            selectedNodeId.value = node.id
 | 
	
		
			
				|  |  | +            selectedNodeData.value = node
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        
 | 
	
		
			
				|  |  | +        // 递归处理子节点(如果有的话)
 | 
	
		
			
				|  |  | +        if (node.children && node.children.length) {
 | 
	
		
			
				|  |  | +            handleBindedNodes(node.children)
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    })
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// 懒加载节点方法
 | 
	
		
			
				|  |  |  const loadNode = async (node, resolve) => {
 | 
	
		
			
				|  |  |      const { level, data: item } = node
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    if (level === 0) {
 | 
	
		
			
				|  |  | +        return resolve([])
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |      
 | 
	
		
			
				|  |  | -  // 根节点(level:0)已通过loadRootNodes加载,直接返回空数组阻止重复请求
 | 
	
		
			
				|  |  | -  if (level === 0) {
 | 
	
		
			
				|  |  | -    return resolve([])
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  |      let parentId = 0
 | 
	
		
			
				|  |  |      if (level !== 0) {
 | 
	
		
			
				|  |  |          const nodeData = getObjValue(item)
 | 
	
		
			
				|  |  |          parentId = nodeData?.id
 | 
	
		
			
				|  |  | -        
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      
 | 
	
		
			
				|  |  | -    // 获取数据
 | 
	
		
			
				|  |  | -    const { data } = await wbsApi.getChildNodes({
 | 
	
		
			
				|  |  | -        contractId: leftRadio.value || '',
 | 
	
		
			
				|  |  | -      
 | 
	
		
			
				|  |  | -        pKeyId: pKeyId.value || '',
 | 
	
		
			
				|  |  | -        parentId,
 | 
	
		
			
				|  |  | -      
 | 
	
		
			
				|  |  | -       
 | 
	
		
			
				|  |  | -       
 | 
	
		
			
				|  |  | -    })
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    resolve(getArrValue(data))
 | 
	
		
			
				|  |  | +    try {
 | 
	
		
			
				|  |  | +        const { data } = await wbsApi.getChildNodes({
 | 
	
		
			
				|  |  | +            contractId: leftRadio.value || '',
 | 
	
		
			
				|  |  | +            pKeyId: pKeyId.value || '',
 | 
	
		
			
				|  |  | +            parentId,
 | 
	
		
			
				|  |  | +        })
 | 
	
		
			
				|  |  | +        
 | 
	
		
			
				|  |  | +        const childNodes = getArrValue(data)
 | 
	
		
			
				|  |  | +        // 处理子节点中的binded状态
 | 
	
		
			
				|  |  | +        handleBindedNodes(childNodes)
 | 
	
		
			
				|  |  | +        // 同步更新树形组件的选中状态
 | 
	
		
			
				|  |  | +        if (treeRef.value) {
 | 
	
		
			
				|  |  | +            treeRef.value.setCheckedKeys(defaultCheckedKeys.value)
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        
 | 
	
		
			
				|  |  | +        resolve(childNodes)
 | 
	
		
			
				|  |  | +    } catch (error) {
 | 
	
		
			
				|  |  | +        console.error('加载子节点失败:', error)
 | 
	
		
			
				|  |  | +        resolve([])
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  | -// 修改加载根节点数据方法
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  // 关闭对话框
 | 
	
		
			
				|  |  |  const closeModal = () => {
 | 
	
	
		
			
				|  | @@ -194,6 +228,8 @@ const closeModal = () => {
 | 
	
		
			
				|  |  |      selectedNodeData.value = null
 | 
	
		
			
				|  |  |      selectedNodeId.value = null
 | 
	
		
			
				|  |  |      leftRadio.value = null
 | 
	
		
			
				|  |  | +    defaultCheckedKeys.value = []
 | 
	
		
			
				|  |  | +    allLoadedNodes.value = {}
 | 
	
		
			
				|  |  |      emit('close')
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -211,17 +247,14 @@ const filterNode = (value, data) => {
 | 
	
		
			
				|  |  |  // 处理节点点击事件
 | 
	
		
			
				|  |  |  const selectedNodeData = ref(null)
 | 
	
		
			
				|  |  |  const handleNodeClick = (data) => {
 | 
	
		
			
				|  |  | -    // 如果是叶子节点才允许选中
 | 
	
		
			
				|  |  | -        selectedNodeId.value = data.id
 | 
	
		
			
				|  |  | -        selectedNodeData.value = data
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | +    selectedNodeId.value = data.id
 | 
	
		
			
				|  |  | +    selectedNodeData.value = data
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  // 确认关联
 | 
	
		
			
				|  |  |  const confirmLoad = ref(false)
 | 
	
		
			
				|  |  |  const confirmLink = async () => {
 | 
	
		
			
				|  |  |      if (!selectedNodeId.value) {
 | 
	
		
			
				|  |  | -        // 提示用户未选择节点
 | 
	
		
			
				|  |  |          window?.$message?.warning('请选择节点')
 | 
	
		
			
				|  |  |          return
 | 
	
		
			
				|  |  |      }
 | 
	
	
		
			
				|  | @@ -235,14 +268,10 @@ const confirmLink = async () => {
 | 
	
		
			
				|  |  |          window.$message?.success(msg ?? '操作成功')
 | 
	
		
			
				|  |  |          closeModal()
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  </script>
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  <style lang="scss" scoped>
 | 
	
		
			
				|  |  | -// 调整单选框与文字的对齐方式
 | 
	
		
			
				|  |  |  :deep(.el-radio) {
 | 
	
		
			
				|  |  |    vertical-align: middle;
 | 
	
		
			
				|  |  |  }
 |