el-table树形数据与懒加载

发布时间 2023-04-11 09:54:18作者: Aitaos
<template>
  <div class="page">
    <div class="page-box">
      <h3 style="margin-top: 0">类目 / 榜单管理</h3>
      <el-input placeholder="请输入关键字" v-model="keyWord" style="margin-bottom: 20px">
        <el-button slot="append" @click="treeFind" icon="el-icon-search"></el-button>
      </el-input>
      <el-table
        fit
        border
        :data="tableData"
        row-key="id"
        ref="multipleTable"
        resizable
        style="marign-bottom: 20px"
        default-expand-all
        :tree-props="{
          children: 'children',
          hasChildren: 'hasChildren',
        }"
        v-loading="loading"
      >
        <el-table-column width="300" label="类目">
          <template slot-scope="scope">
            <span v-if="scope.row.id > 0"> {{ scope.row.name }}</span>
            <el-input
              v-else
              ref="input"
              @blur="inputBlur(scope.row)"
              @change="inputChange(scope.row)"
              v-model="scope.row.name"
              size="mini"
            ></el-input>
          </template>
        </el-table-column>
        <el-table-column align="center" label="Best Sellers">
          <template slot-scope="scope">
            <upload-btn-list
              btnType="success"
              :btnDisabled="scope.row.id > 0 ? false : true"
            ></upload-btn-list>
          </template>
        </el-table-column>
        <el-table-column align="center" label="New Releaser">
          <template slot-scope="scope">
            <upload-btn-list :btnDisabled="scope.row.id > 0 ? false : true"></upload-btn-list>
          </template>
        </el-table-column>
        <el-table-column align="center" label="Movers & Shakers">
          <template slot-scope="scope">
            <upload-btn-list :btnDisabled="scope.row.id > 0 ? false : true"></upload-btn-list>
          </template>
        </el-table-column>
        <el-table-column align="center" label="Most Wished For">
          <template slot-scope="scope">
            <upload-btn-list :btnDisabled="scope.row.id > 0 ? false : true"></upload-btn-list>
          </template>
        </el-table-column>
        <el-table-column align="center" label="Gift Ideas">
          <template slot-scope="scope">
            <upload-btn-list :btnDisabled="scope.row.id > 0 ? false : true"></upload-btn-list>
          </template>
        </el-table-column>
        <el-table-column width="300" align="center" label="操作">
          <template slot-scope="scope">
            <div>
              <el-button
                :disabled="scope.row.id > 0 ? false : true"
                size="small"
                type="info"
                @click="append(scope.row)"
                >新增子级</el-button
              >
              <el-button
                :disabled="scope.row.id > 0 ? false : true"
                size="small"
                type="warning"
                @click="update(scope.row)"
                >编辑</el-button
              >
              <el-button size="small" type="danger" @click="del(scope.row)">删除</el-button>
            </div>
          </template>
        </el-table-column>
      </el-table>
    </div>
    <dialog-edit-add
      :Visible="dialogVisible"
      :data="dialogData"
      @close="dialogClose"
      @save="dialogSave"
    ></dialog-edit-add>
  </div>
</template>
<script>
import dialogEditAdd from '@/components/dialog/data/dialogEditAdd.vue';
import UploadBtnList from '@/components/common/upload-btn-list.vue';
export default {
  components: { dialogEditAdd, UploadBtnList },
  data() {
    return {
      rowId: 0,
      loading: false,
      dialogVisible: false,
      dialogData: {},
      keyWord: '',
      tableData: [],
      tableDataSource: [
        {
          id: 1,
          name: 'Any Department',
          parentId: 0,
          children: [
            {
              id: 2,
              name: 'Amazon Devices & Accessories',
              parentId: 1,
              children: [],
            },
          ],
        },
      ],
    };
  },
  created() {
    this.tableData = this.tableDataSource;
  },
  methods: {
    del(data) {
      this.$confirm(`此操作将永久删除类目${data.name}, 是否继续?`, '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      })
        .then(() => {
          this.removeChild(this.tableData, data.id);
          const a = this.$message({
            type: 'success',
            message: '删除成功!',
          });
        })
        .catch(() => {});
    },
    open(data, value) {
      if (value == 0) {
        this.dialogData = {
          id: 0,
          name: '',
          parentId: data.id,
          children: [],
        };
      } else if (value == 1) {
        this.dialogData = data;
      }
      this.dialogVisible = true;
    },
    append(data) {
      const newChild = {
        id: 0,
        name: '',
        parentId: data.id,
        children: [],
      };
      data.children.push(newChild);
      this.$nextTick(() => {
        this.$refs.input.focus();
      });
    },
    update(data) {
      this.rowId = data.id;
      data.id = 0;
      this.$nextTick(() => {
        this.$refs.input.focus();
      });
    },
    inputBlur(data) {
      this.inputChange(data);
    },
    inputChange(data) {
      if (data.name == '') {
        this.$message.error('类目名不能为空');
        return false;
      }
      this.loading = true;
      if (this.rowId == 0) {
        //新增
        data.id = 10;
      } else {
        //修改
        data.id = this.rowId;
      }
      setTimeout(() => {
        this.rowId = 0;
        this.loading = false;
      }, 1000);
    },
    treeFind() {
      let result = this.findChild(this.tableDataSource, (node) =>
        node.name.toLowerCase().includes(this.keyWord.toLowerCase())
      );
      if (!result) {
        this.tableData = [];
      } else {
        this.tableData = [];
        this.tableData.push(result);
      }
    },
    dialogClose() {
      this.dialogVisible = false;
    },
    dialogSave(data) {
      if (data.id == 0) {
        this.insertChild(this.tableData, data.parentId, data);
      } else {
        this.updateChild(this.tableData, data.id, data);
      }
      this.dialogVisible = false;
    },
    findChild(tree, func) {
      for (const data of tree) {
        if (func(data)) return data;
        if (data.children) {
          const res = this.findChild(data.children, func);
          if (res) return res;
        }
      }
      return null;
    },
    removeChild(list, id) {
      const parent = list;
      const index = parent.findIndex((child) => child.id == id);
      if (index !== -1) {
        parent.splice(index, 1);
        return list;
      }
      list = list.filter((item) => {
        let flag = item.id != id;
        if (flag) {
          if (item.children.length > 0) {
            item.children = this.removeChild(item.children, id);
          }
          return true;
        } else return flag;
      });
      return list;
    },
    insertChild(list, id, newChild) {
      list.forEach((item) => {
        let flag = item.id == id;
        if (flag) {
          item.children.push(newChild);
        } else {
          if (item.children.length > 0) {
            item.children = this.insertChild(item.children, id, newChild);
          }
        }
      });
      return list;
    },
    updateChild(list, id, newChild) {
      list.forEach((item, index) => {
        let flag = item.id == id;
        if (flag) {
          alert(1);
          this.$set(list, index, newChild);
        } else {
          if (item.children.length > 0) {
            item.children = this.updateChild(item.children, id, newChild);
          }
        }
      });
      return list;
    },
  },
};
</script>
<style lang="scss" scoped>
::v-deep .el-input-group {
  width: 300px;
}
::v-deep tr td:first-child .cell {
  display: flex !important;
  flex-wrap: nowrap !important;
}
</style>