回显需要保存两个数据 table封装

128 阅读1分钟
<!--
@Description: 封装element table select组件
@Last-edit-date: 2023.1.10
@Easy o.o <<<<<<<
<ElTableSelect
  :columns="tableColumns"
  :data="tableData"
  :operation="['check']"
  :is-selection="true"
  :page-size="5"
  :total="total"
  :judgeValue="'index'"
  @handleCurrentChange="handleCurrentChange"
  @handleConfirm="handleConfirm"
  @handleCancel="handleCancel"

   /* 备注: */
  size="small" small是比较好看的
  stripe是否为斑马纹 table
  highlight-current-row 是否要高亮当前行
  select	当用户手动勾选数据行的 Checkbox 时触发的事件
  select-all	当用户手动勾选全选 Checkbox 时触发的事件
  selection-change	当选择项发生变化时会触发该事件
  row-click	当某一行被点击时会触发该事件 点击行可以勾选中  
  :header-cell-class-name="cellClass"  只选中一个的时候 隐藏表头多选框 不隐藏默认勾选一个(第一个)
/>
-->
<template>
  <section class="el-table-container">
    <el-table
      ref="tableGroup"
      :data="data"
      :highlight-current-row="true"
      :row-key="getRowKeys"
      border
      stripe
      size="small"
      style="width: 100%"
      :header-cell-class-name="cellClass"
      @selection-change="handleSelectionChange"
      @select="handleSelect"
      @select-all="handleSelectAll"
      @row-click="handleRowClick"
    >
      <!--多选列-->
      <el-table-column
        v-if="isSelection"
        type="selection"
        align="center"
        width="55"
        :selectable="selected"
      />

      <!-- 展示列 -->
      <template v-for="(column, index) in columns">
        <!-- 看不懂 -->
        <!-- <slot v-if="column.slotName" :name="column.slotName" />
        <component
          :is="column.component"
          v-if="column.component"
          :key="index"
          :params="column.params"
        /> -->
        <!-- 处理自定义内容 -->
        <el-table-column
          v-if="column.slotName"
          :key="index"
          :prop="column.prop"
          :label="column.label"
          :width="column.width"
          align="center"
        >
          <template slot-scope="scope">
            <slot :name="column.slotName" :data="scope.row"></slot>
          </template>
        </el-table-column>
        <!-- 默认展示 -->
        <el-table-column
          v-if="!column.slotName && column.prop"
          :key="index"
          :label="column.label"
          :prop="column.prop"
          :width="column.width"
          :class-name="column.className"
          align="center"
        />
      </template>

      <!-- 操作列  fixed="right" 固定列-->
      <el-table-column
        :width="fixedWidth"
        label="操作"
        fixed="right"
        align="center"
      >
        <template slot-scope="scope">
          <el-button
            v-if="operationGroup('edit')"
            icon="el-icon-edit"
            type="success"
            size="mini"
            @click="handleEdit(scope.$index, scope.row)"
          >
            编辑
          </el-button>
          <el-button
            v-if="operationGroup('insert')"
            icon="el-icon-plus"
            size="mini"
            @click="handleInsert(scope.$index, scope.row)"
          >
            增加
          </el-button>
          <el-button
            v-if="operationGroup('delete')"
            icon="el-icon-close"
            type="danger"
            size="mini"
            @click="handleDelete(scope.$index, scope.row)"
          >
            删除
          </el-button>
          <el-button
            v-if="operationGroup('check')"
            icon="el-icon-info"
            type="info"
            size="mini"
            @click="handleCheck(scope.$index, scope.row)"
          >
            查看
          </el-button>
          <!-- 自定义按钮 -->
          <span v-if="operationGroup('custom')" style="display: inline-block">
            <!--eslint-disable-->
            <el-button
              v-for="(i, index) in customList"
              v-if="
                !i.condition ||
                i.condition.value.indexOf(scope.row[i.condition.key]) >= 0
              "
              :key="index"
              :icon="i.icon"
              :type="i.btnType"
              size="mini"
              @click="handleCustom(scope.$index, scope.row, i.handler)"
            >
              {{ i.buttonName }}
            </el-button>
          </span>
        </template>
      </el-table-column>
    </el-table>

    <div class="el-pagination-total"><span>{{ total }}</span
      >条
    </div>
    <el-pagination
      v-if="isPagination"
      background
      :current-page="currentPage"
      :page-sizes="pageSizes"
      :page-size="pageSize"
      :layout="layout"
      :total="total"
      class="el-pagination-c"
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
    />

    <el-row class="el-row-select">
      <div class="box">
        <el-button
          style="margin-right: 8px"
          type="primary"
          size="small"
          @click="handleConfirm"
          >确定</el-button
        >
        <el-button size="small" @click="handleCancel">取消</el-button>
      </div>
    </el-row>
  </section>
</template>

<script>
export default {
  name: "ElTableSelect",
  props: {
    /*
     * 表格
     * */
    checkData: {
      type: [Array, String],
      default: () => [],
    },
    // 表格展示列
    columns: {
      type: Array,
      required: true,
    },
    // 表格数据
    data: {
      type: Array,
      required: true,
    },
    // 是否显示多选列
    isSelection: {
      type: Boolean,
      default: false,
    },
    // 操作组
    // 自定义按钮{icon: '图标', btnType: '按钮类型', handler: '执行的方法', buttonName: '按钮名字',condition: {} 显示判别值}
    operation: {
      type: Array,
      default: () => [],
    },
    // 传入自定义按钮时,需要延展宽度的最大值
    operationCustomLength: {
      type: Number,
      default: 0,
    },
    // 回显判别值的name
    judgeValue: {
      required: true,
      type: String,
    },
    // 只能勾选一个
    isSelectOne: {
      type: Boolean,
      default: false,
    },
    /*
     * 分页
     * */
    // 是否显示
    isPagination: {
      type: Boolean,
      default: true,
    },
    total: {
      type: Number,
      default: 0,
    },
    // 当前页面
    currentPage: {
      type: Number,
      default: 1,
    },
    // 自定义每页面数量组
    pageSizes: {
      type: Array,
      default: () => [10, 20, 50, 100],
    },
    // 每页面数量
    pageSize: {
      type: Number,
      default: 10,
    },
    // total 数据总量, sizes 每页面数量组, prev 上一页, pager, next 下一页, jumper 页面跳转
    layout: {
      type: String,
      default: "sizes,prev, pager, next, jumper",
    },
  },
  data() {
    return {
      getRowKeys(row) {
        return row.index;
      },
      cacheCurrentPage: 1,
      cacheSelectData: [],
    };
  },
  computed: {
    // 操作按钮的宽度自适应
    fixedWidth() {
      return this.operationCustomLength
        ? this.operationCustomLength * 110 - 5
        : this.operation.length * 110 - 5;
    },
  },
  mounted() {
    this.cacheCurrentPage = this.currentPage;
  },
  // watch: {
  //   checkData: {
  //     handler(val) {
  //        console.log("checkData", val);
  //       if (val && val.length > 0) {
  //         this.cacheSelectData = val;
  //         this.echoSelection(this.cacheSelectData[this.cacheCurrentPage]);
  //         console.log("youzhi", val);
  //       }
  //     },
  //     immediate: true,
  //     deep: true,
  //   },
  // },
  methods: {
    againShow(data) {
      this.cacheSelectData = data;
      console.log("this.cacheSelectData", data);
      this.echoSelection(this.cacheSelectData[this.cacheCurrentPage]);
    },
    //全选按钮隐藏
    cellClass(row) {
      // console.log(row)
      if (this.isSelectOne) {
        if (row.columnIndex === 0) {
          return "DisableSelection";
        }
      }
    },
    //是否禁用多选框
    selected(row, index) {
      // if (this.isSelectOne) {
      // 	return false //不可勾选
      // } else {
      // 	return true; //可勾选
      // }
      return true; //可勾选
    },
    //点击行触发,选中或不选中复选框
    handleRowClick(row) {
      /* 选中的再次点击取消勾选 this.rows.length && 第一次cacheCurrentPage都没值 */
      let _selectData;
      let selected =
        this.cacheSelectData[this.cacheCurrentPage] &&
        this.cacheSelectData[this.cacheCurrentPage].some(
          (item) => item.id === row.id
        );
      // console.log('是否选中',selected)
      // 用row判断需要点击两次
      // console.log('是否选中',this.cacheSelectData[this.cacheCurrentPage] && this.cacheSelectData[this.cacheCurrentPage].indexOf(row) !== -1)
      if (selected === true) {
        //当前行被选中
        this.cacheSelectData[this.cacheCurrentPage] = this.cacheSelectData[
          this.cacheCurrentPage
        ].filter((item) => {
          return item.id !== row.id;
        });
        this.$refs.tableGroup.toggleRowSelection(row, false);
      } else {
        //当前行未被选中
        /* 传入row行就会被选中 */
        this.$refs.tableGroup.toggleRowSelection(row);
        if (this.isSelectOne) {
          this.$refs.tableGroup.clearSelection();
          this.$refs.tableGroup.toggleRowSelection(row, true);
          // 获取当前选中的数据
          _selectData = this.$refs.tableGroup.selection;
          this.cacheSelectData[this.cacheCurrentPage] = _selectData;
          this.cacheSelectData.forEach((item, index) => {
            if (index !== this.cacheCurrentPage) {
              this.cacheSelectData[index] = null;
            }
          });
        } else {
          // 获取当前选中的数据
          _selectData = this.$refs.tableGroup.selection;
          this.cacheSelectData[this.cacheCurrentPage] = _selectData;
        }
      }

      // console.log("当前选中的数据", _selectData);
      this.handleSelectionChange(_selectData);
    },
    /*
     * 表格
     * */
    // 筛选行的操作
    operationGroup(affix) {
      if (affix === "custom") {
        // 自定义列表
        this.customList = this.operation.filter((n) => {
          return typeof n === "object";
        });
        return this.customList;
      } else {
        // 固定
        return this.operation.indexOf(affix) >= 0;
      }
    },
    // 自定义事件触发
    handleCustom(index, row, handler) {
      this.$emit(handler, index, row);
    },
    // 编辑事件
    handleEdit(index, row) {
      this.$emit("handleEdit", index, row);
    },
    // 插入事件
    handleInsert(index, row) {
      this.$emit("handleInsert", index, row);
    },
    // 删除事件
    handleDelete(index, row) {
      this.$confirm("确认删除?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      }).then(() => {
        this.$emit("handleDelete", index, row);
      });
    },
    // 查看事件
    handleCheck(index, row) {
      event.stopPropagation(); //禁止选中行
      this.$emit("handleCheck", index, row);
    },
    // 选中改变事件
    handleSelectionChange(val) {
      this.$emit("handleSelectionChange", val);
    },
    // 单个选中事件
    handleSelect(list, row) {
      if (this.isSelectOne) {
        if (list.length > 1) {
          let del_row = list.shift(); //改变原来数组(留下来的是最新的) 把数组的第一个元素从其中删除,并返回第一个元素的值  后面打钩的值(新增的)是push在数组后面的  so前面的值就是旧值
          this.$refs.tableGroup.toggleRowSelection(del_row, false);
          // console.log("留下来的是最新的", list);
          this.cacheSelectData[this.cacheCurrentPage] = list;
          console.log("cacheSelectData", this.cacheSelectData);
        } else {
          this.cacheSelectData[this.cacheCurrentPage] = list;
          /* 把其他页的选中数据清空 */
          //  this.cacheSelectData.forEach((item,index)=>{
          //    console.log('index',index);
          //    if(index !== this.cacheCurrentPage){
          //      item = []
          //    }
          //  })
          //使用arr[index]的形式赋值改变
          this.cacheSelectData.forEach((item, index) => {
            if (index !== this.cacheCurrentPage) {
              this.cacheSelectData[index] = null;
            }
          });
          console.log("this.cacheSelectData", this.cacheSelectData);
        }
        /* 方法二: */
        // 清除 所有勾选项
        // 当表格数据都没有被勾选的时候 就返回
        // 主要用于将当前勾选的表格状态清除
        // this.$refs.tableGroup.clearSelection();
        // if (list.length == 0) return;
        // this.$refs.tableGroup.toggleRowSelection(row, true);
      } else {
        this.cacheSelectData[this.cacheCurrentPage] = list;
      }
      this.$emit("handleSelect", list);
    },
    // 全选事件
    handleSelectAll(list) {
      if (this.isSelectOne) {
        if (list.length > 1) {
          list.length = 1;
        }
      } else {
        // 防止指针错乱
        this.cacheSelectData[this.cacheCurrentPage] = list.length ? list : null;
      }

      this.$emit("handleSelect", list);
    },
    // 单行选中
    setSelection(row, bool) {
      this.$refs.tableGroup.toggleRowSelection(row, bool);
    },
    // 清空选中
    clearSelection() {
      this.$refs.tableGroup.clearSelection();
    },
    // 分页选择回显
    echoSelection(currentPageSelectList) {
      if (currentPageSelectList) {
        const _list = this.data.filter((row) => {
          return currentPageSelectList.some((item) => {
            return item[this.judgeValue] === row[this.judgeValue];
          });
        });
        _list.forEach((row) => {
          this.setSelection(row);
          // or
          // this.$refs.tableGroup.toggleRowSelection(row)
        });
      }
    },

    /*
     * 分页
     * */
    handleSizeChange(num) {
      this.$emit("handleSizeChange", num);
    },
    handleCurrentChange(page) {
      this.$emit("handleCurrentChange", page);
      this.cacheCurrentPage = page;
      // 等待表格数据回显
      setTimeout(() => {
        this.echoSelection(this.cacheSelectData[page]);
      }, 500);
    },

    /*
     * 按钮
     * */
    // 确定
    handleConfirm() {
      // 所有选中的数据  cacheSelectData 第一个数据是 undefined
      const _AllSelectData = []
        .concat(...this.cacheSelectData)
        .filter((item) => {
          return item !== null && typeof item === "object";
        });
      //this.cacheSelectData 回显用到
      this.$emit("handleConfirm", _AllSelectData, this.cacheSelectData);
      this.cacheSelectData = [];
      this.clearSelection();
    },
    // 取消
    handleCancel() {
      this.cacheSelectData = [];
      this.$emit("handleCancel");
      this.clearSelection();
    },
  },
};
</script>

<style scoped lang="scss" ref="stylesheet/scss">
.el-table-container {
  .el-pagination-c {
    float: right;
    margin-top: 1.5em;
  }
  .el-pagination-total {
    float: left;
    margin-top: 1.5em;
    span {
      margin: 0 4px;
      color: #409eff;
    }
  }
  .el-row-select {
    margin-top: 6em;
    text-align: right;
    .box {
      display: inline-block;
    }
  }
}
// 全选按钮的隐藏样式:
::v-deep .el-table .DisableSelection .cell .el-checkbox__inner {
  display: none;
  position: relative;
}
::v-deep .el-table .DisableSelection .cell:before {
  content: "";
  position: absolute;
}
</style>