ソースを参照

跨节点移动修改

duy 1 ヶ月 前
コミット
915f25e807
1 ファイル変更141 行追加101 行削除
  1. 141 101
      src/views/data-fill/components/jumpTreeDialog.vue

+ 141 - 101
src/views/data-fill/components/jumpTreeDialog.vue

@@ -1,6 +1,7 @@
 <template>
     <hc-new-dialog v-model="moveModal" is-table title="跨节点移动" widths="72rem" @close="closeModal">
         <hc-page-split class="m-4" :options="{ sizes: [50, 50] }">
+            <!-- 左侧内容保持不变 -->
             <template #left>
                 <hc-card scrollbar>
                     <div v-loading="cityLoading" class="checkbox-container">
@@ -29,6 +30,7 @@
                     </div>
                 </hc-card>
             </template>
+            
             <hc-card class="tree-card">
                 <template #search>
                     <div class="flex-1">
@@ -44,30 +46,37 @@
                         </el-button>
                     </div>
                 </template>
-                <!-- 添加懒加载树 -->
+                
+                <!-- 修改树的渲染方式 -->
                 <el-scrollbar class="tree-scrollbar mt-3" style="height: 100%;">
+                    <!-- 普通树 -->
                     <el-tree
                         v-if="!isShowSearch"
                         ref="treeRef"
-                        node-key="id"
-                       
+                        :key="treeKey"
+                        node-key="id" 
                         :props="treeProps"
                         :load="treeLoadNode"
                         lazy
-                        :show-checkbox="true"
                         :check-strictly="true"
-                        :check-on-click-node="true"
-                       
                         highlight-current
-                        @check="handleCheckChange"
+                        @node-click="handleNodeClick"
                     >
                         <template #default="{ node, data }">
                             <span class="custom-tree-node">
+                                <!-- 使用单选框替代复选框 -->
+                                <el-radio 
+                                    v-model="selectedNodeId" 
+                                    :value="data.id"
+                                    :disabled="data.nodeType === 6"
+                                    class="mr-2"
+                                />
                                 <span>{{ node.label }}</span>
-                               
                             </span>
                         </template>
                     </el-tree>
+                    
+                    <!-- 搜索结果树 -->
                     <el-tree
                         v-else
                         v-loading="treeLoading"
@@ -75,18 +84,20 @@
                         default-expand-all
                         :props="treeProps"
                         :data="treeData"
-                       
-                        :show-checkbox="true"
                         :check-strictly="true"
-                        :check-on-click-node="true"
-                       
                         highlight-current
-                        @check="handleCheckChange"
+                        @node-click="handleNodeClick"
                     >
                         <template #default="{ node, data }">
                             <span class="custom-tree-node">
+                                <!-- 使用单选框替代复选框 -->
+                                <el-radio 
+                                    v-model="selectedNodeId" 
+                                    :value="data.id"
+                                    :disabled="data.nodeType === 6"
+                                    class="mr-2"
+                                />
                                 <span>{{ node.label }}</span>
-                               
                             </span>
                         </template>
                     </el-tree>
@@ -104,6 +115,7 @@
 import { nextTick, ref, watch } from 'vue'
 import { getArrValue, getObjValue } from 'js-fast-way'
 import queryApi from '~api/data-fill/query'
+
 // 接收父组件传入的属性
 const props = defineProps({
   contractId: {
@@ -123,15 +135,16 @@ const props = defineProps({
     default: '',
   },
 })
-//事件
+
+// 事件
 const emit = defineEmits(['close', 'save'])
 const contractId = ref(props.contractId)
 const classType = ref(props.classType) 
 const authBtnTabKey = ref(props.authBtnTabKey)
 const primaryKeyId = ref(props.primaryKeyId)
-//监听
-watch(() => [
 
+// 监听
+watch(() => [
     props.contractId,
     props.classType,
     props.authBtnTabKey,
@@ -141,21 +154,27 @@ watch(() => [
     classType.value = clas
     authBtnTabKey.value = tab
     primaryKeyId.value = pkid
-    getSameLevelsTreeData()
+  
 })
+
 const moveModal = defineModel('modelValue', {
     default: false,
 })
+watch(() => moveModal.value, (val) => {
+    if (val && primaryKeyId.value) {
+        getSameLevelsTreeData()
+    }
+})
 const closeModal = ()=>{
     moveModal.value = false
-     checkAll.value = false
-
-      checkedCities.value = []
-      cities.value = []
-      treeRef.value.setCheckedKeys([])
+    checkAll.value = false
+    checkedCities.value = []
+    cities.value = []
+    selectedNodeId.value = null // 重置选中状态
     emit('close')
 }
 
+// 左侧复选框相关
 const checkAll = ref(false)
 const isIndeterminate = ref(false)
 const checkedCities = ref([])
@@ -165,34 +184,32 @@ const handleCheckAllChange = (val) => {
   checkedCities.value = val ? cities.value.map(city => city.pkeyId) : []
   isIndeterminate.value = false
 }
+
 const handleCheckedCitiesChange = (value) => {
   const checkedCount = value.length
   checkAll.value = checkedCount === cities.value.length
   isIndeterminate.value = checkedCount > 0 && checkedCount < cities.value.length
 }
+
+// 搜索相关
 const searchInput = ref('')
 
-// 树相关
+// 树相关 - 修改为单选
 const treeRef = ref(null)
 const treeData = ref([])
 const isShowSearch = ref(false)
-const currentNode = ref(null)
+const selectedNodeId = ref(null) // 存储当前选中的节点ID
+const currentNode = ref(null) // 存储当前选中的节点数据
 
-// 树配置
+// 树配置 - 移除disabled配置,在单选框中处理
 const treeProps = {
   label: 'title',
   children: 'children',
   isLeaf: 'notExsitChild',
-    disabled: (data) => {
-        // 当节点类型为6时不能能选择
-        return data.nodeType === 6
-    },
 }
-
+const treeKey = ref(0) // 用于强制刷新树组件
 // 加载节点数据
-
 const treeLoadNode = async (node, resolve) => {
- 
     const { level, data: item } = node
     
     let contractIdRelation = '',
@@ -204,112 +221,127 @@ const treeLoadNode = async (node, resolve) => {
         parentId = contractIdRelation ? nodeData?.primaryKeyId : nodeData?.id
         primaryKeyId = nodeData?.id || ''
     }
-    //获取数据
+    
+    // 获取数据
     const { data } = await queryApi.queryWbsTreeData({
         contractId: contractId.value || '',
         contractIdRelation,
         primaryKeyId,
         parentId,
-        // classifyType: authBtnTabKey.value,
         classifyType: classType.value,
         tableOwner: authBtnTabKey.value,
-        dataTime:new Date(),
+        dataTime: new Date(),
     })
 
-
     resolve(getArrValue(data))
 }
-// 节点点击事件
-const handleCheckChange = (data, checked) => {
-  // 确保只能选中一个节点
-  const checkedNodes = treeRef.value.getCheckedNodes()
-  if (checkedNodes.length > 1) {
-    // 取消之前选中的节点
-    checkedNodes.forEach(node => {
-      if (node.id !== data.id) {
-        treeRef.value.setChecked(node, false)
-      }
-    })
-  }
-  currentNode.value = checked ? data : null
-  
+
+// 处理节点点击和单选逻辑
+const handleNodeClick = (data) => {
+    // 如果节点被禁用则不处理
+    if (data.nodeType === 6) return
+    
+    // 设置选中状态
+    selectedNodeId.value = data.id
+    currentNode.value = data
 }
 
+// 搜索功能
+
 // 搜索功能
 const searchClick = () => {
   if (!searchInput.value) {
      isShowSearch.value = false
-    
+     // 重新加载原始树
+     if (treeRef.value) {
+       refreshTree()
+     }
   } else {
     isShowSearch.value = true
     getSearchTreeData()
   }
-  // TODO: 实现搜索逻辑
-  console.log('搜索关键词:', searchInput.value)
 }
-const treeLoading = ref(false)
+// 刷新树的方法 - 替代reload
+const refreshTree = () => {
+  // 通过修改key值强制树组件重新渲染
+  treeKey.value += 1
+  // 重置选中状态
+  selectedNodeId.value = null
+  currentNode.value = null
+}
 
+
+const treeLoading = ref(false)
 const getSearchTreeData = async () => {
     treeLoading.value = true
-    const { error, code, data }
-        = await queryApi.getTreeNodeByQueryValueAndContractId({
-            contractId: contractId.value,
-            queryValue: searchInput.value,
-            tableOwner: authBtnTabKey.value,
-        })
-    //判断状态
+    const { error, code, data } = await queryApi.getTreeNodeByQueryValueAndContractId({
+        contractId: contractId.value,
+        queryValue: searchInput.value,
+        tableOwner: authBtnTabKey.value,
+    })
+    
     if (!error && code === 200) {
-      
         treeData.value = getArrValue(data)
-        treeLoading.value = false
     } else {
-        treeLoading.value = false
-
         treeData.value = []
     }
+    treeLoading.value = false
 }
+
+// 获取左侧数据
 const cityLoading = ref(false)
 const getSameLevelsTreeData = async () => { 
-      cityLoading.value = true
-    const { error, code, data }
-        = await queryApi.getSiblingWbsContract({
-            pKeyId: primaryKeyId.value,
-           
-        })
-    //判断状态
+    cityLoading.value = true
+    const { error, code, data } = await queryApi.getSiblingWbsContract({
+        pKeyId: primaryKeyId.value,
+    })
+    
     if (!error && code === 200) {
-      
         cities.value = getArrValue(data)
-        cityLoading.value = false
     } else {
-        cityLoading.value = false
-
         cities.value = []
     }
+    cityLoading.value = false
 }
+
+// 提交移动
 const moveLoading = ref(false)
 const submitMove = async (type)=>{
-  moveLoading.value = true
-  const { error, code, data, msg } = await queryApi.moveNode({
-            leftPkeyIds: checkedCities.value,
-            rightPkeyId:currentNode.value.pKeyId,
-        })
-        moveLoading.value = false
-        if (!error && code === 200) {
-         window.$message?.success(msg ?? '操作成功')
-    } 
-    if (type === 1) {
-        emit('save')
-    } else {
-      checkAll.value = false
-
-      checkedCities.value = []
-      cities.value = []
-      treeRef.value.setCheckedKeys([])
-       getSameLevelsTreeData()
-       searchClick()
+    // 验证是否选择了目标节点
+    if (!selectedNodeId.value) {
+        window.$message?.warning('请选择目标节点')
+        return
+    }
+    
+    moveLoading.value = true
+    const { error, code, data, msg } = await queryApi.moveNode({
+        leftPkeyIds: checkedCities.value,
+        rightPkeyId: currentNode.value.pKeyId,
+    })
+    moveLoading.value = false
+    
+    if (!error && code === 200) {
+        window.$message?.success(msg ?? '操作成功')
+        
+        if (type === 1) {
+            emit('save')
+            closeModal()
+        } else {
+            // 重置表单但保持弹窗打开
+            checkAll.value = false
+            checkedCities.value = []
+            selectedNodeId.value = null
+            currentNode.value = null
+            getSameLevelsTreeData()
+             // 刷新树数据
+            if (isShowSearch.value && searchInput.value) {
+                getSearchTreeData() // 搜索状态下重新搜索
+            } else {
+                refreshTree() // 普通状态下刷新树
+            }
+    
+        }
     }
-  
 }
 </script>
 
@@ -332,8 +364,7 @@ const submitMove = async (type)=>{
     }
 }
 
-
-// 添加树卡片样式
+// 树卡片样式
 .tree-card {
   height: 100%;
   display: flex;
@@ -348,7 +379,7 @@ const submitMove = async (type)=>{
   }
 }
 
-// 修改滚动容器样式
+// 滚动容器样式
 .tree-scrollbar {
   flex: 1;
   height: 0;
@@ -358,5 +389,14 @@ const submitMove = async (type)=>{
     height: 100%;
   }
 }
-</style>
 
+// 调整单选框与文字的对齐方式
+:deep(.el-radio) {
+  vertical-align: middle;
+}
+
+.custom-tree-node {
+  display: flex;
+  align-items: center;
+}
+</style>