The World of Remnant

全动态的可拖拽el-table组件

<template>
  <div>
    <div v-show="Isshow">
      <el-collapse>
        <el-collapse-item name="1" title="表头">
          <el-checkbox-group v-model="checkboxVal">
            <el-checkbox
              v-for="(thead, index) in formTheadOptions"
              :key="`thead_${index}`"
              :label="thead.name"
            >{{ thead.name }}</el-checkbox>
          </el-checkbox-group>
        </el-collapse-item>
      </el-collapse>
    </div>

    <el-table
      id="applyTable"
      :key="key"
      :data="tableData"
      style="width: 100%"
      ref="multipleTable"
      row-key="RowsKeyId"
      size="mini"
      border
      :expand-row-keys="expands"
      :show-summary="IsshowSummary"
      :summary-method="Summary"
      :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
      @select="handleSelect"
      @select-all="handleSelect"
      @header-dragend="headChange"
      @row-dblclick="rowDBlclick"
      @sort-change="changeTableSort"
      @row-click="handleRowClick"
      @selection-change="handleSelectionChange"
    >
      <el-table-column type="selection" width="60" v-if="IsShowCheckbox"></el-table-column>
      <el-table-column width="29"></el-table-column>
      <el-table-column
        v-for="(fruit, index) in formThead"
        :key="`fruit_${index}`"
        :label="fruit.name"
        :prop="formThead[index].prop"
        align="center"
        show-overflow-tooltip
        :width="formThead[index].width"
        :resizable="true"
        class-name="canmove"
        :sortable="Issortable"
        :sort-method="sortMethod"
      >
        <template slot-scope="scope">{{ scope.row[formThead[index].prop] }}</template>
      </el-table-column>
      <el-table-column label="操作" align="center" width="200" v-if="IsShowInline">
        <el-button type="primary" size="mini" @click="handleDelete(scope.$index)">删除</el-button>
      </el-table-column>
    </el-table>
    <div class="tablepaging" style="margin-top:10px">
      <el-pagination
        background
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
        :current-page="pageNumber"
        :page-sizes="pageList"
        :page-size="pageSize"
        layout="total, sizes, prev, pager, next, jumper"
        :total="total"
      ></el-pagination>
    </div>
  </div>
</template>

<script>
import { getSummaries, Deduplicate } from "@/utils/validate";
import Common from "@/utils/common";
import Sortable from "sortablejs";
import { saveHead, getHead } from "@/api/getData";

export default {
  data() {
    return {
      tableData: [],
      key: 1, // table key
      checkboxVal: [],
      formThead: [], // 默认表头 Default header
      expands: [], //列表要展开的数据
      pageList: [20, 30, 40, 50], //每页显示个数选择器的选项设置
      pageSize: 20, //每页显示条目个数
      pageNumber: 1, //当前页数
      total: 0, //总条数
      saveListIn: [], //勾选的数据
      sortable: null,
      newtableData: [],
      saveList: [],
      Id: 0, //用于用户进入详情的ID
      originalTable: []
    };
  },
  props: {
    formTheadOptions: {
      //表头数据
      type: Array
    },
    requsetUrl: {
      //获取列表的URL
      type: String,
      default: ""
    },
    RequestData: {
      type: Object //获取列表请求数据
    },
    IsshowSummary: {
      type: Boolean //是否合计
    },
    SumType: {
      type: Array //合计字段
    },
    Isshow: {
      type: Boolean //是否可以自定义表头
    },
    IsShowInline: {
      type: Boolean //table行内删除按钮是否显示
    },
    Issortable: {
      type: Boolean //是否显示排序
    },
    IsShowCheckbox: {
      type: Boolean //是否显示表内复选框
    },
    HeaderType: {
      type: Number //列头类型,用来记录列头宽度和顺序 品目= 1, 部门= 3, 角色 = 4, 员工 = 5, 客户 = 6, 供应商 = 7, 客户订单 = 8, 采购单 = 9, 仓库 = 10, 入仓单 = 11, 在库 = 12, 出仓单 = 13, 送货 = 14
    }
  },
  watch: {
    checkboxVal(valArr) {
      this.formThead = this.formTheadOptions.filter(
        i => valArr.indexOf(i.name) >= 0
      );
      // this.key = this.key + 1; // 为了保证table 每次都会重渲
    },
    requsetUrl: {
      handler: function() {
        if (this.requsetUrl !== "") {
          this.getTableList();
        }
      },
      deep: true
    }
  },
  async mounted() {
    this.formTheadOptions.forEach(item => {
      this.checkboxVal.push(item.name);
    });

    await this.getTableList();
    if (Number(this.HeaderType) !== 0 && this.formTheadOptions) {
      this.rowDrop();
      this.columnDrop();
    }
  },
  methods: {
    //合计
    Summary(param) {
      let sums = [];
      if (this.tableData.length > 0 && this.SumType.length > 0) {
        sums = getSummaries(param, this.SumType, this.tableData);
      }
      return sums;
    },
    //行拖拽
    rowDrop() {
      const tbody = document.querySelector(".el-table__body-wrapper tbody");
      const _this = this;
      Sortable.create(tbody, {
        onEnd({ newIndex, oldIndex }) {
          const currRow = _this.tableData.splice(oldIndex, 1)[0];
          _this.tableData.splice(newIndex, 0, currRow);
        }
      });
    },
    //列拖拽
    columnDrop() {
      let self = this;
      const wrapperTr = document.querySelector(".el-table__header-wrapper tr");
      self.sortable = Sortable.create(wrapperTr, {
        animation: 180,
        delay: 0,
        handle: ".canmove",
        onEnd: evt => {
          if (evt.oldIndex < 2 || evt.newIndex < 2) {
            self.$message.error("此列不能拖动");
          } else {
            let oldindex = evt.oldIndex - 2;
            let newindex = evt.newIndex - 2;
            let oldItem = this.formTheadOptions[oldindex]; //找到要移动的数据
            this.formTheadOptions.splice(oldindex, 1); //把数据从就得数据中删除
            this.formTheadOptions.splice(newindex, 0, oldItem); //将旧的数组中将就得数据在新的位置上插入
            let Data = {
              ModuleEnum: this.HeaderType,
              ColList: []
            };

            if (this.formTheadOptions.length > 0) {
              this.formTheadOptions.forEach(formTheadOptionsItem => {
                let ColList = {
                  Name: formTheadOptionsItem.name,
                  Prop: formTheadOptionsItem.prop,
                  Width: formTheadOptionsItem.width
                };
                Data.ColList.push(ColList);
              });
            }

            this.saveHead(Data);
          }
        }
      });
    },

    //获得列表数据
    async getTableList() {
      this.tableData = [];
      this.RequestData.Data.PageNumber = this.pageNumber;
      this.RequestData.Data.PageSize = this.pageSize;
      let data = await Common(this.requsetUrl, this.RequestData);
      if (data.StatusCode !== 0) {
        this.$message.error(data.Message);
      } else {
        if (data.Message !== null) {
          this.$message.error(data.Message);
        } else {
          this.tableData = data.Data.Rows;
          this.total = data.Data.Total;
          if (this.tableData.length > 0) {
            this.tableData.forEach(tableDataItem => {
              for (let pro in tableDataItem) {
                //Id和RowsKeyId属性不在table上显示
                if (
                  tableDataItem[pro] !== "Id" ||
                  tableDataItem[pro] !== "RowsKeyId"
                ) {
                  //如果table上某一属性是用布尔值来返回的,则在前端转换成相应的"是"或者“否”
                  if (
                    typeof tableDataItem[pro] === "boolean" &&
                    pro !== "IsProduct"
                  ) {
                    let Item = "";
                    if (tableDataItem[pro]) {
                      Item = "可用";
                    } else {
                      Item = "停用";
                    }
                    tableDataItem[pro] = Item;
                  }
                }
              }
            });
          }
        }
      }
      this.$emit("dataLoaded", "");
    },

    //换页
    async handleSizeChange(val) {
      this.pageSize = val;
      await this.getTableList();
      this.toggleSelection();
    },
    async handleCurrentChange(val) {
      this.pageNumber = val;
      await this.getTableList();
      this.toggleSelection();
    },

    handleSelect(row, val) {
      let self = this;
      self.saveList = self.saveList.filter(item => {
        let judgement = true;
        self.tableData.forEach(items => {
          if (item.RowsKeyId === items.RowsKeyId || items != items) {
            judgement = false;
          } else {
            if (items.children) {
              if (items.children.length > 0) {
                items.children.forEach(childrenItem => {
                  if (
                    item.RowsKeyId == childrenItem.RowsKeyId ||
                    childrenItem != childrenItem
                  ) {
                    judgement = false;
                  }
                });
              } else {
                judgement = false;
              }
            }
          }
        });
        return judgement;
      });
      row.forEach(item => {
        self.saveList.push(item);
      });

      //当不勾选某条数据时,将该条数据从savelist中清除,Exit用来判断是去掉勾选数据还是勾上数据,如果Exit有值则说明是勾上数据,如果undefined则说明是无数据
      if (val) {
        let Exit = row.find(item => item.RowsKeyId === val.RowsKeyId);

        //全选和全不选
        if (val.Fid === 0) {
          //当带有子单的数据被勾选上或者不被勾选上,子单状态和主单状态保持一致
          if (val.children.length > 0) {
            //如果勾选带有子单的主单,则将主单下的子单全部勾选上
            if (Exit) {
              val.children.forEach(item => {
                self.$refs.multipleTable.toggleRowSelection(item, true);
                self.saveList.push(item);
              });
            } else {
              //如果去掉勾选状态的带有子单的主单,则将主单下的子单全部勾选状态清空
              val.children.forEach(item => {
                self.$refs.multipleTable.toggleRowSelection(item, false);
                self.saveList.push(item);
              });
            }
          } else {
            //如果勾选的主单不带有子单
            if (Exit) {
              self.saveList.push(val);
            } else {
              let list = self.saveList.find(
                items => items.RowsKeyId === val.RowsKeyId
              );
              if (list) {
                self.saveList.splice(items => val.RowsKeyId === list.RowsKeyId);
              }
            }
          }
        } //如果勾选的是子单
        else {
          if (Exit) {
            self.saveList.push(val);
          } else {
            let list = self.saveList.find(
              items => items.RowsKeyId === val.RowsKeyId
            );
            if (list) {
              self.saveList.splice(items => val.RowsKeyId === list.RowsKeyId);
            }
          }
        }
      }

      //去重
      self.saveList = Deduplicate(self.saveList);
      this.Id = 0;
      this.$emit("func", this.saveList, this.Id);
    },
    rowDBlclick(row) {
      this.Id = row.Id;
      this.ExchangeUnitId = row.ExchangeUnitId;
      this.saveList = [];
      if (this.Id) {
        this.$emit("func", this.saveList, this.Id);
      } else if (this.ExchangeUnitId) {
        this.$emit("func", this.saveList, this.ExchangeUnitId);
      }
      //   this.$emit("func", this.saveList, this.Id);
    },

    //勾选框状态保存
    toggleSelection() {
      let self = this;
      if (self.saveList) {
        self.saveList.forEach(item => {
          self.$nextTick(() => {
            let checkRow = self.tableData.find(
              tableRow => tableRow.RowsKeyId === item.RowsKeyId
            );
            if (self.tableData.length > 0) {
              self.tableData.forEach(tableItem => {
                if (tableItem.RowsKeyId === item.RowsKeyId) {
                  this.$refs.multipleTable.toggleRowSelection(tableItem, true);
                } else {
                  if (tableItem.children.length > 0) {
                    tableItem.children.forEach(childItem => {
                      if (childItem.RowsKeyId === item.RowsKeyId) {
                        this.$refs.multipleTable.toggleRowSelection(
                          childItem,
                          true
                        );
                      }
                    });
                  }
                }
              });
            }
          });
        });
      }
    },
    //删除
    handleDelete(index) {
      this.tableData.splice(index, 1);
    },
    //保存表头的宽度和顺序
    async saveHead(Data) {
      let res = await saveHead(Data);
      if (res.StatusCode !== 0) {
        this.$message.error(res.Message);
      }
    },

    //拖动表头改变列宽
    headChange(newWidth, oldWidth, column, event) {
      setTimeout(() => {
        let applyTable = document.getElementById("applyTable");
        let applyTableColgroup = applyTable.getElementsByTagName("colgroup")[0];
        let applyTableCol = applyTableColgroup.getElementsByTagName("col");

        for (let i = 0; i < applyTableCol.length; i++) {
          if (i < this.formTheadOptions.length) {
            this.formTheadOptions[i].width = applyTableCol[i + 2].width;
          }
        }

        let Data = {
          ModuleEnum: this.HeaderType,
          ColList: []
        };
        if (this.formTheadOptions.length > 0) {
          this.formTheadOptions.forEach(formTheadOptionsItem => {
            let ColList = {
              Name: formTheadOptionsItem.name,
              Prop: formTheadOptionsItem.prop,
              Width: formTheadOptionsItem.width
            };
            Data.ColList.push(ColList);
          });
        }
        this.saveHead(Data);
      }, 100);
    },
    changeTableSort(e) {
      if (this.originalTable.length === 0) {
        this.originalTable = JSON.parse(JSON.stringify(this.tableData));
      }

      if (e.order) {
        this.tableData = this.tableData.sort((a, b) => {
          let tempA = a[e.prop] || 0;
          let tempB = b[e.prop] || 0;
          return parseFloat(tempA) - parseFloat(tempB);
        });
      } else {
        this.tableData = JSON.parse(JSON.stringify(this.originalTable));
      }
    },
    sortMethod(a, b) {},
    handleSelectionChange(val) {
      this.saveList = val;
      this.saveList = Deduplicate(this.saveList);
      this.Id = 0;
      this.$emit("func", this.saveList, this.Id);
    },
    handleRowClick(row){
       let multipleTable = this.$refs.multipleTable;
       multipleTable.toggleRowSelection(row);
    }
  }
};
</script>