Sfoglia il codice sorgente

复制节点弹窗增加

duy 3 giorni fa
parent
commit
204171b850

+ 337 - 0
src/views/manager/wbsinfo/TreeCopyModal.vue

@@ -0,0 +1,337 @@
+<template>
+  <el-dialog
+    :title="title"
+    :visible.sync="visible"
+    :width="dialogWidth"
+    :before-close="handleClose"
+    append-to-body
+
+    class="tree-copy-modal"
+  >
+    <!-- 提示信息 -->
+    <div class="alert-message">
+       <span>温馨提示:允许单对多、多对单、多对多的关联关系。关联后可在对应节点查看。【关联并继续】可以继续续进行关联。</span>
+     
+    </div>
+
+    <!-- 树形结构容器 -->
+    <div class="tree-container">
+      <!-- 左侧复制源树 -->
+      <div class="tree-wrapper left-tree">
+        <div class="tree-title">复制源</div>
+        <el-tree
+          ref="sourceTree"
+          :data="sourceTreeData"
+          :props="treeProps"
+          :load="loadSourceNode"
+          node-key="id"
+          show-checkbox
+          lazy
+          :expand-on-click-node="false"
+          @check="handleSourceCheck"
+        ></el-tree>
+      </div>
+
+      <!-- 中间箭头 -->
+      <div class="tree-arrow">
+        <i class="el-icon-arrow-right"></i>
+      </div>
+
+      <!-- 右侧复制到树 -->
+      <div class="tree-wrapper right-tree">
+        <div class="tree-title">复制到</div>
+        <el-tree
+          ref="targetTree"
+          :data="targetTreeData"
+          :props="treeProps"
+          :load="loadTargetNode"
+          node-key="id"
+          show-checkbox
+          lazy
+          :expand-on-click-node="false"
+          @check="handleTargetCheck"
+        ></el-tree>
+      </div>
+    </div>
+
+    <!-- 底部按钮 -->
+    <div slot="footer" class="dialog-footer">
+      <el-button @click="handleClose">取消</el-button>
+      <el-button type="primary" @click="handleLinkAndExit">关联并退出</el-button>
+      <el-button type="success" @click="handleLinkAndContinue">关联并继续</el-button>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+import {
+  getLazytree,
+
+} from "@/api/manager/wbstree";
+
+export default {
+  name: 'TreeCopyModal',
+  props: {
+    // 弹窗标题
+    title: {
+      type: String,
+      default: '复制节点'
+    },
+    // 弹窗宽度
+    dialogWidth: {
+      type: String,
+      default: '80%'
+    },
+    // 源树和目标树的ID参数
+    sourceId: {
+      type: [String, Number],
+      required: true
+    },
+    targetId: {
+      type: [String, Number],
+      required: true
+    },
+    // 用户信息,包含tenant_id
+    userInfo: {
+      type: Object,
+      required: true
+    }
+  },
+  data() {
+    return {
+      // 弹窗显示状态
+      visible: false,
+      // 源树数据
+      sourceTreeData: [],
+      // 目标树数据
+      targetTreeData: [],
+      // 树的配置项
+      treeProps: {
+              children: "children",
+        label: "title",
+        isLeaf: function (data) {
+          if (data.hasChildren && data.isExistForm != 1) {
+            return false;
+          } else if (data.hasChildren && data.isExistForm == 1) {
+            return true;
+          } else {
+            return true;
+          }
+        },
+      },
+      
+      // 选中的源节点
+      selectedSourceNodes: [],
+      // 选中的目标节点
+      selectedTargetNodes: []
+    };
+  },
+  methods: {
+    // 显示弹窗
+    show() {
+      this.visible = true;
+      // 重置选中状态
+      this.selectedSourceNodes = [];
+      this.selectedTargetNodes = [];
+      // 重置树
+      if (this.$refs.sourceTree) {
+        this.$refs.sourceTree.setCheckedKeys([]);
+      }
+      if (this.$refs.targetTree) {
+        this.$refs.targetTree.setCheckedKeys([]);
+      }
+    },
+
+    // 关闭弹窗
+    handleClose() {
+      this.visible = false;
+      this.$emit('close');
+    },
+
+    // 加载源树节点
+    loadSourceNode(node, resolve) {
+      let pid = 0;
+      if (node.level !== 0) {
+        pid = node.data.id;
+      }
+      getLazytree(this.sourceId, pid, this.userInfo.tenant_id)
+      
+        .then(res => {
+          let arr = [];
+          if (Array.isArray(res.data.data)) {
+            arr = res.data.data.map(item => ({
+              ...item,
+              // 如果后端没有返回isLeaf,这里可以根据实际业务逻辑判断
+              isLeaf: item.isLeaf !== undefined ? item.isLeaf : false
+            }));
+          }
+          resolve(arr);
+        })
+        .catch(err => {
+          console.error('加载源树节点失败:', err);
+          resolve([]);
+        });
+    },
+
+    // 加载目标树节点
+    loadTargetNode(node, resolve) {
+      let pid = 0;
+      if (node.level !== 0) {
+        pid = node.data.id;
+      }
+      getLazytree(this.sourceId, pid, this.userInfo.tenant_id)
+        .then(res => {
+          let arr = [];
+          if (Array.isArray(res.data.data)) {
+            arr = res.data.data.map(item => ({
+              ...item,
+              isLeaf: item.isLeaf !== undefined ? item.isLeaf : false
+            }));
+          }
+          resolve(arr);
+        })
+        .catch(err => {
+          console.error('加载目标树节点失败:', err);
+          resolve([]);
+        });
+    },
+
+    // 处理源树节点选择
+    handleSourceCheck(data, checked, indeterminate) {
+      this.selectedSourceNodes = this.$refs.sourceTree.getCheckedNodes(true, false);
+    },
+
+    // 处理目标树节点选择
+    handleTargetCheck(data, checked, indeterminate) {
+      this.selectedTargetNodes = this.$refs.targetTree.getCheckedNodes(true, false);
+    },
+
+    // 显示关联规则提示
+    showLinkTips() {
+      this.$alert('关联规则说明:\n1. 允许单对单、多对单、多对多的关联关系\n2. 关联后可在对应节点查看关联信息\n3. 复制操作不会影响原节点数据', '关联规则', {
+        confirmButtonText: '确定'
+      });
+    },
+
+    // 关联并退出
+    handleLinkAndExit() {
+      this.handleLink(true);
+    },
+
+    // 关联并继续
+    handleLinkAndContinue() {
+      this.handleLink(false);
+    },
+
+    // 处理关联操作
+    handleLink(exitAfterLink) {
+      if (this.selectedSourceNodes.length === 0 || this.selectedTargetNodes.length === 0) {
+        this.$message.warning('请至少选择一个源节点和一个目标节点');
+        return;
+      }
+
+      // 准备关联数据
+      const linkData = {
+        sourceNodes: this.selectedSourceNodes.map(node => node.id),
+        targetNodes: this.selectedTargetNodes.map(node => node.id)
+      };
+
+      // 触发父组件的关联事件
+      this.$emit('link', linkData, () => {
+        this.$message.success('关联成功');
+        if (exitAfterLink) {
+          this.handleClose();
+        } else {
+          // 清空选择但不关闭弹窗
+          this.$refs.sourceTree.setCheckedKeys([]);
+          this.$refs.targetTree.setCheckedKeys([]);
+          this.selectedSourceNodes = [];
+          this.selectedTargetNodes = [];
+        }
+      });
+    }
+  }
+};
+</script>
+
+<style scoped>
+.tree-copy-modal {
+  .alert-message {
+    padding: 10px 15px;
+    background-color: #f5f7fa;
+    border-left: 4px solid orange;
+    margin-bottom: 20px;
+    display: flex;
+    align-items: center;
+    font-size: 14px;
+    color: orange;
+
+    .el-icon-info-circle {
+      color: #409eff;
+      margin-right: 8px;
+    }
+
+    .el-button {
+      margin-left: auto;
+      color: #409eff;
+      padding: 0;
+    }
+  }
+
+  .tree-container {
+    display: flex;
+    justify-content: space-between;
+    height: 500px;
+    overflow: hidden;
+  }
+
+  .tree-wrapper {
+    flex: 1;
+    border: 1px solid #e4e7ed;
+    border-radius: 4px;
+    overflow: hidden;
+    display: flex;
+    flex-direction: column;
+
+    .tree-title {
+      padding: 10px 15px;
+      background-color: #f5f7fa;
+      border-bottom: 1px solid #e4e7ed;
+      font-weight: 500;
+    }
+
+    .el-tree {
+      flex: 1;
+      overflow: auto;
+      padding: 10px;
+    }
+  }
+
+  .left-tree {
+    margin-right: 15px;
+  }
+
+  .right-tree {
+    margin-left: 15px;
+  }
+
+  .tree-arrow {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    width: 40px;
+    color: #c0c4cc;
+
+    .el-icon-arrow-right {
+      font-size: 20px;
+    }
+  }
+
+  .dialog-footer {
+    display: flex;
+    justify-content: center;
+    padding-top: 15px;
+
+  }
+}
+</style>

+ 42 - 1
src/views/manager/wbsinfo/edit.vue

@@ -1489,6 +1489,15 @@
       >
       </FormulaEditone>
     </el-dialog>
+     <!-- 引入树形复制弹窗组件 -->
+    <tree-copy-modal
+      ref="treeCopyModal"
+      :source-id="id"
+     
+      :user-info="userInfo"
+      @close="handleModalClose"
+      @link="handleLinkNodes"
+    ></tree-copy-modal>
   </basic-container>
 </template>
 
@@ -1496,6 +1505,7 @@
 import ManualSorting from "@/components/WbsTree/ManualSorting";
 import FormulaEdit from "@/views/formula/edit.vue";
 import FormulaEditone from "@/views/formula/edit1.vue";
+import TreeCopyModal from './TreeCopyModal.vue';
 import {
   getLazytree,
   getDetail,
@@ -1537,6 +1547,9 @@ import { getDictionary, getChildList } from "@/api/system/dict";
 import { mapGetters } from "vuex";
 import { getStore, setStore } from "@/util/store";
 export default {
+    components: {
+    TreeCopyModal
+  },
   data() {
     var checkMajorDataType = (rule, value, callback) => {
       //console.log(this.nodeDetail.nodeType)
@@ -1706,6 +1719,8 @@ export default {
       dynamicDictList: [],
       standardTypeOptions: [], //标准分类
       unitOptions: [], //单位名称
+      copyDialogVisible: false, //复制节点弹框
+
     };
   },
   computed: {
@@ -3373,17 +3388,43 @@ export default {
         this.menuKey = "del";
         this.delNodeHandle();
       } else if (item.key === "copy") {
-        this.$message.info("暂无相关接口");
+      
+        this.$refs.treeCopyModal.show();
       } else if (item.key === "sort") {
         this.menuKey = "sort";
         this.paixuMD(data);
       }
     },
+     handleModalClose() {
+      console.log('树形复制弹窗已关闭');
+      // 可以在这里处理弹窗关闭后的逻辑
+    },
+
+    // 处理节点关联
+    handleLinkNodes(linkData, successCallback) {
+      console.log('准备关联的节点数据:', linkData);
+
+      // // 调用API进行节点关联
+      // linkNodesApi(linkData)
+      //   .then(res => {
+      //     if (res.data.success) {
+      //       // 关联成功,调用回调函数
+      //       successCallback();
+      //     } else {
+      //       this.$message.error('关联失败: ' + (res.data.message || '未知错误'));
+      //     }
+      //   })
+      //   .catch(err => {
+      //     console.error('关联节点出错:', err);
+      //     this.$message.error('关联失败,请重试');
+      //   });
+    }
   },
   components: {
     ManualSorting,
     FormulaEdit,
     FormulaEditone,
+     TreeCopyModal
   },
 };
 </script>