基于antd-vue二次封装成自己想要的业务——加强篇

之前写过这个,有地址
https://blog.csdn.net/weixin_44191425/article/details/119740500?spm=1001.2014.3001.5501

现在只是为了更优化丰富一下,然后修复了一些bug

结合之前的和现在的看,会更明白。

基于之前封装的组件,优化了一些bug,比如说编辑和新增的时候做了其他操作,新增的输入框和编辑框要恢复到之前的状态。

<template>
  <div>
    <a-tree
      v-if="treeData.length > 0"
      :tree-data="treeData"
      block-node
      default-expand-all
      style="margin-top:65px;"
    >
      <icon slot="switcherIcon" name="down"></icon>
      <template slot="custom" slot-scope="item">
        <!-- 如果是新增-->
        <span v-if="item.isNewItem">
          <input
            type="text"
            class="editInput"
            :maxlength="30"
            v-model="item.name"
            placeholder="请输入部门名称"
          />
          <span
            class="tree-save_icon edit-require_icon"
            @click="submitAddFun(item)"
          >
            <a-icon type="check-circle" />
          </span>
          <span
            class="tree-cancle_icon edit-require_icon"
            @click="cancelAddFun(item)"
          >
            <a-icon type="close-circle" />
          </span>
          
        </span>
        <!-- 不是新增 -->
        <div v-else>
          <!-- 编辑时展示输入框 -->
          <div v-if="item.isEdit">
            <input
              type="text"
              v-model="item.title"
              :maxlength="30"
              class="editInput"
            />
            <span
              class="tree-save_icon edit-require_icon"
              @click="submitEdit(item)"
            >
              <a-icon type="check-circle" />
            </span>
            <span
              class="tree-cancle_icon edit-require_icon"
              @click="cancelEdit(item.id, false)"
            >
              <a-icon type="close-circle" />
            </span>
            
          </div>
          <!-- 否则展示原来的节点信息 -->
          <div v-else>
            <!-- <a-popover placement="topLeft"> -->
              <!-- <template slot="content">
                <p>{{ item.title }}</p>
              </template> -->
            <span class="node-title" @click="selectNode(item)" >{{
              item.title
            }}</span>
          <!-- </a-popover> -->
            <!-- 删除按钮 -->
            <a-popconfirm
              class="delete-box"
              placement="topRight"
              ok-text="确定"
              cancel-text="取消"
              overlayClassName="staff-delete-pop"
              @confirm="deleteNode(item)"
              v-show="item.isShowDelete"
            >
              <template slot="title">
                删除{{
                  item.title
                }}后,该部门下的所有员工将被删除,且已存在的演练数据也将去除,确定删除
                ?

              </template>
              <a-tooltip placement="top">
                <template slot="title">
                  <span>删除</span>
                </template>
                  <span class="icon-wrap" @click="cancelBubble($event)" style="margin-left:8px">
                    <icon name="delete-opt" />
                  </span>
              </a-tooltip>
            </a-popconfirm>
            <!-- 编辑按钮 -->
            <template v-if="item.isShowEdit">
              <a-tooltip placement="top">
                <template slot="title">
                  <span>编辑</span>
                </template>
                  <span class="icon-wrap" @click="editNode(item.id)">
                  <icon name="edit-opt" />
                  </span>
              </a-tooltip>
            </template>
            <!-- 新增按钮 -->
            <a-tooltip v-if="item.isShowAdd" placement="top">
              <template slot="title">
                <span>新增</span>
              </template>
              <span class="icon-wrap" @click="addNewNode(item)">
                <icon name="plus" />
              </span>
            </a-tooltip>
          </div>
        </div>
      </template>
    </a-tree>
  </div>
</template>

<script>
import {
  addOrganization,
  deleteOrganization,
  editOrganization,
} from "@/api/staff.js";
export default {
  props: {
    treeData: {
      type: Array,
      default: () => [],
    },
  },
  data() {
    return {
      tempTable: [],
    };
  },
  mounted() {
    this.visible = false;
  },
  methods: {
    // 选择单条查询
    selectNode(node) {
      this.deleteEditInput()
      this.deleteAddInput()
      this.$emit("getParams", node);
    },
    // 删除取消气泡
    cancelBubble(e) {
      e.stopPropagation();
    },
    // 新增节点
    addNewNode(node) {
      this.deleteEditInput()
      const newNode = {
        addNode: true,
        id: Math.ceil(Math.random() * 10000),
        key: Math.ceil(Math.random() * 10000),
        isEdit: false,
        name: "",
        isNewItem: true,
        title: "",
        status: node.status,
        depth: node.depth + 1,
        parent_id: node.id,
        parent_name: node.title,
        scopedSlots: { title: "custom" },
      };
      this.$nextTick(() => {
        for (let i = 0; i < this.treeData.length; i++) {
          if (this.treeData[i].id === node.id) {
            this.deleteAddInput();
            this.treeData[i].children.unshift(newNode);
          }
        }
      });
    },
    // 删除新增的input框
    deleteAddInput() {
      for (let i = 0; i < this.treeData.length; i++) {
        // 父级
        if (this.treeData[i].addNode) {
          this.treeData.splice(i, 1);
          // 子集
        } else {
          this.deleteChildren(this.treeData[i].children);
        }
      }
    },
    // 删除子集
    deleteChildren(data) {
      if (!data.length) return;
      for (let j = 0; j < data.length; j++) {
        // 删除已有的输入框
        if (data[j].addNode) {
          data.splice(j, 1);
        }
      }
    },
    // 提交新增
    submitAddFun(node) {
      if (!node.name) {
        this.$message.error("部门名称不能为空!");
        return;
      }
      let params = {
        name: node.name,
        parentId: node.parent_id,
      };
      addOrganization(params).then((res) => {
        if (res.errorCode === "00000") {
          this.deleteAddInput();
          this.$message.success("部门新增成功");
          this.$emit('refrshAdd');
        }
      });
    },
    // 取消新增
    cancelAddFun() {
      this.deleteAddInput();
    },
    // 删除节点内容
    deleteNode(item) {
      deleteOrganization({ id: item.id }).then((res) => {
        if (res.errorCode === "00000") {
          this.$message.success("部门删除成功");
          // 接口请求成功之后做本地删除
          this.treeData[0].children = this.treeData[0].children.filter(ele => ele.id != item.id)
          // 删除一条补一条最新的
          this.$emit("deleteAfterAdd");
          // 刷新列表
          this.$emit("resetList");
        } else {
          this.$message.error(res.message);
        }
      });
    },
    // 编辑
    editNode(id) {
      this.deleteAddInput()
      const copyData = this.treeData;
      copyData.forEach((ele) => {
        // 父级编辑
        if (ele.id == id) {
          this.$set(ele, "isEdit", true);
        } else {
          ele.children.forEach((ite) => {
            if (ite.id == id) {
              this.$set(ite, "isEdit", true);
            } else {
              this.$set(ite, "isEdit", false);
            }
          });
        }
      });
    },
    // 撤销编辑框
    deleteEditInput() {
      this.treeData.forEach( item => {
        item.children.forEach( ite => {
          this.$set(ite, "isEdit", false);
        })
      })
    },
    // 取消编辑
    cancelEdit(id, isEdit) {
      const copyData = this.treeData[0].children;
      copyData.forEach((ele) => {
        // 父级编辑
        if (ele.id == id) {
          this.$set(ele, "isEdit", isEdit);
          return;
        }
      });
    },
    // 提交编辑
    submitEdit(data) {
      if (!data.title) {
        this.$message.error("部门名称不能为空!");
        return;
      }
      let params = {
        id: data.id,
        name: data.title,
        parentId: data.parent_id,
      };
      editOrganization(params).then((res) => {
        if (res.errorCode === "00000") {
          this.$message.success("部门修改成功");
          // 接口请求成功之后做本地修改
          const copyData = this.treeData[0].children;
          copyData.forEach((ele) => {
            // 父级编辑
            if (ele.id == data.id) {
              this.$set(ele, "isEdit", false);
              this.$set(ele, "title", data.title);
              return;
            }
          });
          // 修改部门成功之后刷新员工列表
          this.$parent.pagination({page:1,page_size:10})
        } else {
          this.$message.error(res.message);
        }
      });
    },
  },
  watch: {},
};
</script>

<style lang="less" scoped>
.icon-wrap {
  float: right;
  color: #999999;
}
/deep/ .ant-tree>li>.ant-tree-node-content-wrapper{
  background: #FAFAFA;
}
/deep/.ant-tree>li>span.ant-tree-switcher, .ant-tree li span.ant-tree-iconEle{
  line-height: 32px !important;
}
/deep/ .ant-tree-child-tree {
  padding-left: 23px;
  margin-top: 10px;
  li {
    list-style: none;
    .ant-tree-node-content-wrapper {
      height: 32px !important;
      .icon-wrap{
        visibility: hidden;
      }
      &:hover {
        background: #f6f9ff;
        .icon-wrap{
          visibility: inherit;
        }
      }
    }
    .node-title{
      padding-left:30px ;
    }
  }
  .ant-tree-treenode-switcher-open {
    vertical-align: middle;
    line-height: 35px;
    height: 40px;
    .ant-tree-node-content-wrapper {
      margin-top: 3px;
      width: 100% !important;
      line-height: 32px;
      height: 32px;
      &:hover {
        background: #f6f9ff;
      }
    }
   
  }
  .ant-tree-treenode-switcher-close{
    position: relative;
    &::before{
      position: absolute;
      top: 18px;
      left: 18px;
      vertical-align: middle;
      width: 4px;
      height: 4px;
      border-radius: 50%;
      background: #333333;
      content: '';
    }
    &:first-child::before{
      top: 22px;
    }
  }

  .ant-tree-switcher-noop {
    width: 0;
  }
}
/deep/.ant-tree-node-content-wrapper.ant-tree-node-content-wrapper-normal {
  width: 100% !important;
  line-height: 32px;
  height: 32px;
}
/deep/.ant-tree-node-selected {
  height: 32px;
  background: #f6f9ff;
}
/deep/ .edit-require_icon {
  margin-left: 5px;
}
.editInput {
  width: 70%;
  height: 30px;
  margin-left: 25px;
  line-height: 30px;
  outline: none;
  border: 1px solid @line-gray;
  background: transparent;
  font-size: 12px;
}
/deep/ .ant-tree-title div {
  line-height: 32px;
  height: 32px;
  &:hover {
    background: #f6f9ff;
  }
}
.node-title{
  width: 70%;
  padding-left: 10px;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  display: inline-block;
}
</style>

部门树增加滑动加载、搜索查询

在这里插入图片描述

// 左侧关键词查询
    handelLeftSearch(e) {
      this.leftTreeSearch.keyword = e.target.value ? e.target.value : null;
      this.leftTreeSearch.page = 1;
      this.getOrganizationList(this.treeData);
    },
    // 左侧部门树滑动加载
    scroll() {
      this.$nextTick(() => {
        const el = this.$refs.leftTreeList;
        const offsetHeight = el.offsetHeight;
        const scrollTop = el.scrollTop;
        const scrollHeight = el.scrollHeight;
        if (offsetHeight + scrollTop - scrollHeight >= 0) {
          // 查询聚合数据
          this.getOrganizationList(this.treeData);
        }
      });
    },
getOrganizationList(dataArr) {
      if (this.treeLoading) {
        return;
      }
      this.treeLoading = true;
      organizationList(this.leftTreeSearch).then((res) => {
        if (res.errorCode == "00000") {
          let handelData = res.data.records;
          if (handelData.length == 0) {
            this.treeLoading = false;
            return;
          }
          // 如果是搜索渲染数据
          if (this.leftTreeSearch.page == 1) {
            dataArr[0].children = [];
          }
          handelData.forEach((item) => {
            item.parentId = dataArr[0].id;
            item.key = item.id;
            item.title = item.name;
            item.depth = 2;
            item.isEdit = false;
            item.isNewItem = false;
            item.isDelete = false;
            item.isShowDelete = true;
            item.isShowEdit = true;
            item.isShowAdd = false;
            item.scopedSlots = { title: "custom" };
            dataArr[0].children.push(item);
          });
          this.leftTreeSearch.page += 1;
          this.treeLoading = false;
        }
      });
      this.treeData = dataArr;
    },

版权声明:本文为weixin_44191425原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。