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(0,0,0,0.8)">
    <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: #043031 !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>