Newer
Older
operation_web / src / components / common / PageTable / index.vue
<template>
  <!-- 显示表格 -->
  <div
    class="h-100 page-table"
    ref="tableBox"
    v-loading="listInfo.loading"
    element-loading-text="加载中"
    element-loading-spinner="el-icon-loading"
    element-loading-background="rgba(255,255,255,0.3)"
  >
    <el-table
      class="h-100"
      :data="data"
      row-key="id"
      default-expand-all
      :class="className"
      :max-height="listInfo.tableHeight"
      :header-cell-style="{ textAlign: 'center' }"
      :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
      @select-all="handleSelectionChange"
      @selection-change="handleSelectionChange"
    >
      <el-table-column
        v-if="checkBox"
        type="selection"
        width="55"
        align="center"
        :selectable="checkboxInit"
      />
      <el-table-column
        v-if="tabIndex"
        label="序号"
        align="center"
        :width="fieldList.length === 0 ? '' : 60"
      >
        <template slot-scope="scope">
          <span>{{
            scope.$index +
              1 +
              (listInfo.query.current - 1) * listInfo.query.size
          }}</span>
        </template>
      </el-table-column>
      <el-table-column
        v-for="(item, index) in fieldList"
        :key="index"
        :prop="item.value"
        :label="item.label"
        :fixed="item.fixed"
        :align="item.align ? item.align : 'center'"
        :width="item.width"
        :min-width="`${item.minWidth}`"
        :show-overflow-tooltip="item.tooltip"
      >
        <template slot-scope="scope">
          <!-- solt自定义列-->
          <template v-if="item.type === 'slot'">
            <slot :name="'col-' + item.value" :row="scope.row" />
          </template>
          <!-- 嵌套表格 -->
          <template v-else-if="item.children">
            <el-table-column
              v-for="(childItem, childIndex) in item.children"
              :key="childIndex"
              :prop="childItem.value"
              :label="childItem.label"
              align="center"
              :width="item.width"
              :min-width="item.minWidth"
            />
          </template>
          <!-- 图片 -->
          <el-image
            v-else-if="item.type === 'image' && scope.row[item.value]"
            :src="scope.row[item.value]"
            fit="fill"
          ></el-image>
          <!-- 其他 -->
          <span v-else>
            {{
              getDataName({
                dataList: listTypeInfo[item.list],
                value: "value",
                label: "key",
                data: scope.row[item.value]
              }) || "-"
            }}
          </span>
        </template>
      </el-table-column>
      <el-table-column
        v-if="handle"
        :key="'handle'"
        :fixed="handle.fixed"
        align="center"
        :label="handle.label"
        :width="handle.width"
      >
        <template v-slot="scope">
          <template v-for="(item, index) in handle.btList">
            <!-- 自定义操作类型 -->
            <slot
              v-if="item.slot"
              :name="`bt-${item.event}`"
              :data="{ item, row: scope.row }"
            />
            <!-- 操作按钮 -->
            <el-button
              v-if="
                !item.slot &&
                  item.show &&
                  (!item.ifRender || item.ifRender(scope.row))
              "
              :key="index"
              :size="item.size || 'small'"
              :type="item.type"
              :icon="item.icon"
              v-has="item.has ? item.has : ''"
              :disabled="item.disabled"
              :loading="scope.row[item.loading]"
              @click="handleClick(item.event, scope.row, scope.$index)"
            >
              {{ item.label }}
            </el-button>
          </template>
        </template>
      </el-table-column>
    </el-table>
    <!-- 分页组件 -->
    <template v-if="pagination">
      <el-pagination
        background
        layout="total, sizes, prev, pager, next, jumper"
        :total="listInfo.total"
        :pager-count="5"
        :page-sizes="[10, 20, 30, 40]"
        :page-size="listInfo.query.size"
        :current-page.sync="listInfo.query.current"
        @current-change="handleCurrentChange"
        @size-change="handleSizeChange"
      />
    </template>
  </div>
</template>

<script>
export default {
  props: {
    //自定义样式名
    className: {
      type: String
    },
    //获取数据的接口
    apiUrl: {
      type: String
    },
    //是否显示序号
    tabIndex: {
      type: Boolean,
      default: false
    },
    //表格字段配置
    fieldList: {
      type: Array,
      default: () => {
        return [];
      }
    },
    //刷新
    refresh: {
      type: Number
    },
    //重置当前页
    initCurpage: {
      type: Number
    },
    //表格数据
    data: {
      type: Array
    },
    //是否有选中框
    checkBox: {
      type: Boolean,
      default: false
    },
    //操作栏配置
    handle: {
      type: Object
    },
    //监听高度
    listenHeight: {
      type: Boolean,
      default: true
    },
    //类型列表
    listTypeInfo: {
      type: Object,
      default: () => {
        return {};
      }
    },
    //是否分页
    pagination: {
      type: Boolean,
      default: false
    },
    //查询条件
    query: {
      type: Object,
      default: () => {
        return {};
      }
    },
    //表格最大高度
    tableHeight: {
      type: Number
    },
    //表格数据展示类型
    tableType: {
      type: String
    },
    loading: {
      type: Boolean,
      default: true
    },
    //用于区分多个表格选中的结果
    type: {
      type: String,
      default: "all"
    }
  },
  data() {
    return {
      //列表相关
      listInfo: {
        tableHeight: null, //表格最大高度
        total: 0, //总条数
        loading: false, //加载动画
        query: {
          //查询条件
          current: 1, //当前页
          size: 10 //每页条数
        }
      }
    };
  },
  watch: {
    initCurpage() {
      this.listInfo.query.current = 1;
    },
    refresh: {
      handler(newVal, oldVal) {
        if (this.apiUrl === "") return;
        this.getList(this.apiUrl);
      },
      deep: true
    }
  },
  mounted() {
    setTimeout(() => {
      this.listInfo.tableHeight = this.getTableHeight();
    }, 0);
    window.addEventListener("resize", () => {
      this.listInfo.tableHeight = this.getTableHeight();
    });
  },
  methods: {
    // 处理参数
    handleParams() {
      const obj = {};
      for (const key in this.query) {
        // if (this.query[key] || this.query[key] === 0) {
        obj[key] = this.query[key];
        // }
      }
      // 如果不需要分页,则无分页相关参数
      const dataObj = this.pagination ? { data: obj } : { data: {} };
      return this.pagination ? { ...this.listInfo.query, ...dataObj } : dataObj;
    },
    //选中数据
    handleSelectionChange(rows) {
      this.$emit("handleEvent", this.type, rows);
    },
    //派发按钮点击事件
    handleClick(event, data, index) {
      this.$emit("handleClick", event, data, index);
    },
    /**
     * 通过key找到在列表中对应的显示
     * @param {Object} obj
     * @param obj.dataList 数据列表
     * @param obj.value    数据的值对应的字段名称   例如 'value'
     * @param obj.label    数据的说明对应的字段名称 例如 'label'
     * @param obj.data     当前传入的数据值
     * @return name        返回当前传入值在数组中对应的名字
     */
    getDataName(obj) {
      let name = obj.data;
      if (Array.isArray(obj.dataList) && obj.dataList.length > 0) {
        for (let i = 0; i < obj.dataList.length; i++) {
          if (obj.dataList[i][obj.value] === obj.data) {
            name = obj.dataList[i][obj.label];
          }
        }
      }
      return name;
    },
    handleCurrentChange(val) {
      this.listInfo.query.current = val; //当前页
      this.$emit("currentPage", val);
      this.getList(this.apiUrl);
    },
    handleSizeChange(val) {
      this.listInfo.query.size = val; //当前一页多少条
      this.getList(this.apiUrl);
    },
    //获取数据
    getList(url) {
      // return new Promise((resolve, reject)=>{
      //每次调用接口自动绑定最新数据
      this.listInfo.loading = true;
      this.$http
        .post(url, this.handleParams())
        .then(res => {
          this.listInfo.loading = false;
          if (res.data.code === 200 || res.data.code === 1) {
            //使外面可以访问到表格数据
            let arr = Array.isArray(res.data.data)
              ? res.data.data
              : res.data.data.list;
            if (this.tableType === "tree") {
              arr = this.$fn.handleTree(arr);
            }
            if (arr) {
              arr.forEach(item => {
                item.createTime = this.$fn.switchTime(
                  item.createTime,
                  "YYYY-MM-DD hh:mm:ss"
                );
                item.updateTime = this.$fn.switchTime(
                  item.updateTime,
                  "YYYY-MM-DD hh:mm:ss"
                );
              });
              this.$emit("update:data", arr);
            } else {
              this.$emit("update:data", []);
            }
            if (this.pagination) {
              this.listInfo.total = res.data.data.total;
            }
            // resolve(res)
          } else {
            this.$message({
              showClose: true,
              message: res.data.msg,
              type: "error",
              duration: 3000
            });
            // reject()
          }
        })
        .catch(err => {
          console.log(err);
          this.listInfo.loading = false;
          // reject()
        });
      // })
    },
    //得到表格高度
    getTableHeight() {
      //当表格存在的时候才执行操作
      if (document.getElementsByClassName("el-table").length === 0) {
        return;
      }
      let _baseHeight = this.pagination ? 42 : 0;
      if (this.$refs.tableBox && this.$refs.tableBox.offsetHeight) {
        let resultHeight = this.$refs.tableBox.offsetHeight;
        let _height = resultHeight - _baseHeight;
        return _height;
      }
    },
    //判断是否可以被选中
    checkboxInit(row, index) {
      if (row.registered) {
        return 0; //不可勾选
      } else {
        return 1; //可勾选
      }
    }
  }
};
</script>

<style lang="scss" scoped>
/deep/ .el-table {
  @include fd();
  // .el-table__body tr.hover-row > td {
  //   background-color: transparent;
  // }
  .el-table__body tr.hover-row > td {
    background-color: var(--selecthover) !important;
  }
  .el-table__fixed-right::before,
  .el-table__fixed::before {
    background-color: transparent;
  }
  .el-table__fixed-right-patch {
    background-color: aqua;
  }
  .el-table__fixed-right-patch {
    border-bottom-color: aqua;
  }
  .el-table__body-wrapper {
    flex: 1;
  }
}
/deep/ .el-pagination {
  margin-top: 10px;
}
/deep/ .el-pagination.is-background {
  .el-pager li:not(.disabled).active {
    color: #fff;
    background-color: #409eff !important;
  }
}
</style>