封装的基础查询table组件,不支持多级表头

<template>
  <div class="content">
    <div class="myForm">
      <el-form
        :model="searchForm"
        ref="refForm"
        :label-width="searchConfig.labeWidth"
        :inline="searchConfig.inline">
        <template v-if="searchForm || searchConfig.itemList">
          <el-form-item v-for="(item,index) of searchConfig.itemList" :key="index" :label="item.label" :prop="item.prop" :class="item.type" :style="{marginLeft:item.marginLeft}">
            <span v-if="item.type =='text'">{{searchForm[item.prop]}}</span>
            <el-input v-if="item.type =='input'" v-model="searchForm[item.prop]" clearable :size="item.size?item.size :'medium'" :disabled="item.disabled" :placeholder="item.placeholder" :style="{width: item.width}"></el-input>
            <el-select clear="select_btn" v-if="item.type =='select'" v-model="searchForm[item.prop]" clearable :size="item.size?item.size :'medium'" :placeholder="item.placeholder" :style="{width: item.width}">
                <el-option v-for="opt of item.option" :key="item.optionControl ? opt[item.optionControl.value] : opt.value" :label="item.optionControl ? opt[item.optionControl.label] : item.label" :value="item.optionControl ? opt[item.optionControl.value] : item.value"></el-option>
            </el-select>
            <!-- 下拉模糊查询多选 -->
            <el-select v-if="item.type =='selectFilter'"  v-model="searchForm[item.prop]"
             :filterable="searchConfig.paginationOption.remote"
             multiple
             :loading="searchConfig.paginationOption.loading"
             :remote="searchConfig.paginationOption.remote"
             :size="item.size?item.size :'medium'"
             clearable
             :style="{width: item.width}"
             :placeholder="item.placeholder">
              <el-option  v-for="opt of item.option" :key="item.optionControl ? opt[item.optionControl.label] : opt.value" :label="item.optionControl ? opt[item.optionControl.label] : item.label" :value="item.optionControl ? opt[item.optionControl.value] : item.value">
              </el-option>
              <pagination
                  v-if="searchConfig.paginationOption.total > 0"
                  small
                  :total="searchConfig.paginationOption.total"
                  :page.sync="searchConfig.paginationOption.pageNum"
                  :limit.sync="searchConfig.paginationOption.pageSize"
                  @pagination = "selectpageNationChange"
                />
            </el-select>
            <el-date-picker v-if="item.type =='datapicker'"
             type="date" 
            :size="item.size?item.size :'medium'" 
            :placeholder="item.placeholder"
             v-model="searchForm[item.prop]" 
             clearable 
             :style="{width: item.width}"
             value-format="yyyy-MM-dd"
             format="yyyy-MM-dd"
             :picker-options="item.hasOwnProperty('dayOptions') && item.dayOptions ? item.dayOptions : {//日限制
                disabledDate: (time) => {
                  return   time.getTime() > Date.now()
                },
              }"
             ></el-date-picker>
            <el-time-picker v-if="item.type =='timepicker'"  
              :size="item.size?item.size :'medium'" 
              :placeholder="item.placeholder" 
              v-model="searchForm[item.prop]" 
              clearable 
              :style="{width: item.width}"></el-time-picker>
           <!-- 时间范围选择 -->
           <el-date-picker
              v-if="item.type === 'datetimerange'"
              key="datetimerange"
              type="datetimerange"
              :size="item.size?item.size :'medium'"
              v-model="searchForm[item.prop]"
              format="yyyy-MM-dd HH:mm:ss"
              value-format="yyyy-MM-dd HH:mm:ss"
              range-separator="-"
              start-placeholder="开始日期"
              end-placeholder="结束日期"
              clearable
              :style="{width: item.width}" 
              :picker-options="item.hasOwnProperty('datetimeOptions') && item.datetimeOptions ? item.datetimeOptions : {//开始-结束时间限制 -带时分秒
                  onPick: ({ maxDate, minDate }) => {
                    searchForm[item.prop]= [];
                    searchForm[item.prop].push( minDate.getTime());
                      if (maxDate) {
                          searchForm[item.prop] = []
                      }
                  },
                  disabledDate: time => {//这里没有限制你的开始时间不能小于某个时间,可以在自己页面写
                  return time.getTime() > new Date().getTime();//time.getTime() + 24 * 3600 * 1000 > new Date().getTime()  
                  },
                  shortcuts: [
                  {
                  text: '最近一个月',
                  onClick(picker) {
                      const end = new Date();
                      const start = new Date();
                      start.setTime(start.getTime() - 3600 * 1000 * 24 * 29);//这里先限制30天内吧,不然继保那边接口报错
                      picker.$emit('pick', [start, end]);
                  }
                  }]
              }"
             ></el-date-picker>
          </el-form-item>
        </template>
        <!-- 自定义按钮 -->
        <template v-if="searchConfig.btnArr">
          <el-form-item>
            <el-button
              v-for="(item, index) of searchConfig.btnArr"
              :key="item + index"
              :icon="item.icon ? item.icon : ''"
              @click="handleClick(item)"
              size="mini"
              :type="item.type"
              :disabled="item.disabled"
              >{{ item.name }}</el-button >
          </el-form-item>
        </template>
        <div :class="searchConfig.btnClass ? searchConfig.btnClass : ''">
          <div v-if="searchConfig.leftBtnArr">
            <el-button
              v-for="(item, index) of searchConfig.leftBtnArr"
              :key="item + index"
              :icon="item.icon ? item.icon : ''"
              @click="handleClick(item)"
              size="mini"
              :type="item.type"
              :disabled="item.disabled"
              >{{ item.name }}</el-button >
          </div>
          <div
            v-if="searchConfig.rightBtnArr"
            :class="
              searchConfig.btnClass ? searchConfig.btnClass : 'margin-top' " >
            <el-button
              v-for="(item, index) of searchConfig.rightBtnArr"
              :key="item + index"
              :icon="item.icon ? item.icon : ''"
              @click="handleClick(item)"
              size="mini"
              :type="item.type"
              :disabled="item.disabled"
              >{{ item.name }}</el-button>
          </div>
        </div>
      </el-form>
    </div>
    <div :class="{'myTable':isMyTable}">
      <el-table
        :show-header="tableConfig.showHeader"
        :show-summary="tableConfig.showSummary"
        :summary-method="getSummaries"
        :header-cell-style="tableConfig.headerCellStyle ? tableConfig.headerCellStyle : {background: '#0c2c5d'}"
        stripe
        v-loading="tableConfig.tableLoading"
        :data="tableConfig.tableData"
        style="width: 100%"
        :height="tableConfig.istableHeight ? tableConfig.istableHeight : tableConfig.tHeight" 
        @row-click="$rowClick"
        @selection-change="$handleSelectionChange" 
        @row-dblclick="$doubleClick"
        @current-change="$handleCurrentChange"
        :span-method="objectSpanMethod"
        :highlight-current-row = "tableConfig.highlight"
        show-overflow-tooltip  
        ref="multipleTable" >
        <el-table-column  width="65"  v-if="tableConfig.rowSelection ==='radio' ">
          <template slot-scope="scope">
            <el-radio v-model="templateSelection" :label="scope.row" @click.native.prevent="singleElection">{{ "" }}</el-radio>
          </template>
        </el-table-column>
          <el-table-column type="selection" width="55" v-if="tableConfig.rowSelection ==='checkbox'"> </el-table-column>
        <el-table-column label="序号" width="50">
          <template slot-scope="scope">
            {{ scope.$index + 1 }}
          </template>
        </el-table-column>
          <el-table-column v-for="(item,index) in tableConfig.columns" :key=" index"
          :width="item.width?item.width:'auto'"
          :min-width="item.minWidth"
          :prop="item.prop"
          :formatter="item.formatter"
          show-overflow-tooltip
          tooltip-effect="light"
          :align="item.align?item.align:'center'"
          :label="item.label">
          <template slot-scope="{ row }">
              <span v-if="!item.render">{{ row[item.prop] == null || row[item.prop] == '' ? '-' : row[item.prop] }}</span>
              <render-dom v-else :render-func="item.render" :row="row"></render-dom>
            </template>
          </el-table-column>
        <el-table-column label="操作" :width="tableConfig.actionWidth ? tableConfig.actionWidth : '200'" v-if="tableConfig.actionArr">
          <template slot-scope="{ row }">
              <el-button  v-for="(item,index) of tableConfig.actionArr" 
              :key="index" size="mini" 
              :type="item.type" 
              :disabled="disabledFunc(item,row)" 
              @click="item.hasOwnProperty('clickAction')&& typeof item.clickAction(item,row) === 'function' ? item.clickAction(item,row) : clickAction(item,row)">
              <span v-if="!item.render"> {{ item.name}}</span>
              <render-dom v-else :render-func="item.render" :row="row"></render-dom>
            </el-button>
            </template>
        </el-table-column>
      </el-table>
      <pagination
        v-if="tableConfig.total > 0"
        :total="tableConfig.total"
        :page.sync="tableConfig.pageNum"
        :limit.sync="tableConfig.pageSize"
        @pagination="paginationFunc"
        :small="tableConfig.paginationType ? tableConfig.paginationType : false"
      />
    </div>
  </div>
</template>
<script>
import "@/assets/reset.css";
import "@/assets/global.less";
import renderDom from "./renderDom";
export default {
  name: "TableList",
  components: { renderDom },
  props: {
    searchConfig: {
      type: Object,
      default: function () {
        return {
          labeWidth: "auto",
          paginationOption:{//分页配置项
            type:Object,
            default:function () {
              return {
                total: 0,
                pageNum: 1,
                pageSize: 6,
                paginationType: false, //是否使用小型分页,默认false
                loading:{//远程数据加载状态显示
                  type:Boolean,
                  default:false
                },
                remote:{//是否支持远程搜索,默认支持
                  type:Boolean,
                  default:true
                },
              }
            },
          },
        };
      },
    },
    searchForm: Object,
    tableConfig: {
      type: Object,
      default: function () {
        return {
          tableLoading: {
            type: Boolean,
            default: false,
          },
          tHeight: null,
          istableHeight: null,
          rowSelection: "",
          total: 0,
          pageNum: 1,
          pageSize: 10,
          paginationType: false, //是否使用小型分页,默认false
          tableData: [],
          columns: [],
          actionArr: [],
          actionWidth: '',
          highlight:false,
          showHeader:true,
          headerCellStyle:{
            type: Object,
            default:()=>{
              return {}
            },
          },
          showSummary: { //表尾是否合计行 2022-10-12
            type: Boolean,
            default: false,
          },
          
        };
      },
    },
    tableHeader: {
      type: Array,
      default: function () {
        return [];
      },
    },
    paginationFunc: {
      type: Function,
      default: function () {},
    },
    selectpageNationChange: {
      type: Function,
        default: function () {},
    },
    toggleSelections: {
       type: [Array],
      default: function () {
        return [];
      },
    },
     isMyTable: {
      type: Boolean,
      default: true,
    },
    // toggleSelections: {
    //    type: [Array,Object,String],
      //  required: true,
      //  validator(val) {
      //   if (Array.isArray(val) || val == '') return {};
      //   return [];
      // },
    // },
    isobjectSpanMethod: {  // 是否合并 2022-10-09
      type: Boolean,
      default: false
    },
    spanColumnArr: { // 合并哪几列, [0]为默认第一列[0,1,2,3]为第1,2,3,4合并用第一条的数据
      type: Array,
      default: () => []
    },
    spanArr: { // 合并单元格
      type: Array,
      default: () => {
        return []
      }
    },
  },
  data() {
    return {
      multipleSelection: [],
      dicts: {},
      //选择
      templateSelection: "",
      templateRadio: "",
      // 轮转规则表格数据
      rotationRuleList: [],
      currentRow: [],
    };
  },
  watch: {
    searchForm: {
      handler: function (val, oldVal) {
        return { ...val };
      },
      deep: true,
    },
    tableConfig: {
      handler: function (newVal, oldVal) {

        return { ...newVal };
      },
      deep: true,
    },
    toggleSelections: {
      handler: function (val, oldVal) {
        return  this.toggleSelection(...val);
      },
      deep: true,
    },
  },
  computed: { },
  mounted() {
    this.handleWindow();
    window.addEventListener("resize", this.handleWindow, true);
  },
  beforeDestroy() {
    window.removeEventListener("resize", this.handleWindow, true);
  },
  methods: {
    handleWindow() {
      this.$nextTick(() => {
        let bodyHeight =
          window.innerHeight ||
          document.documentElement.clientHeight ||
          document.body.clientHeight;
        this.tableConfig.tHeight =
          bodyHeight - document.querySelector(".myForm").clientHeight - 150;
      });
    },
    // 点击按钮执行方法
    handleClick(type) {
      if (type.click == "reset") {//重置
        this.resetForm("refForm");
        this.paginationFunc();
      } else if(type.click == "add") { // 新增
        this.$emit("addClickFun");
      } else if (type.click == "search") {//查询
        this.$emit("serachClickFun", this.searchForm);
      } else if (type.click == "import") {//导入
        this.$emit('importClickFunc')
      } else if (type.click == "download") {//导出
        this.$emit('downloadClickFun')
      } else if (type.click == "allselect") { //全部选中
        this.toggleSelection(this.tableConfig.tableData);
        this.$emit("handleSelectionChange", this.multipleSelection);
      } else if (type.click instanceof Function) {
        this.$emit("clickFunc", type);
      }
    },
    // 清空表单事件
    resetForm(formName) {
      this.$refs[formName].resetFields();
    },
    //全部选中
    $handleSelectionChange(val) {
      this.multipleSelection = val;
      this.$emit("handleSelectionChange", this.multipleSelection);
    },
    //双击
    $doubleClick(val) {
      this.$refs.multipleTable.toggleRowSelection(val);
      this.$emit("doubleclick", val);
    },
    //取消选择
    toggleSelection(rows) {
      if( rows) {
        if(Array.isArray(rows) && this.tableConfig.rowSelection !== "radio") {
          rows.forEach(row => {
            this.multipleSelection = row;
            this.$refs.multipleTable.toggleRowSelection(row);
          });
        }else if( this.tableConfig.rowSelection === "radio"){
          this.templateRadio =  rows.hasOwnProperty('scalaId') ?  rows.scalaId : rows.hasOwnProperty('numberCode') ?  rows.numberCode : rows.scadaId;
          this.templateSelection = rows;
        }
      }else {
        this.$refs.multipleTable.clearSelection();
        this.multipleSelection = [];
      }
    },
    //点击行
    $rowClick(val) {
      if (this.tableConfig.rowSelection === "radio") {
        this.templateRadio = val.scalaId;
        this.templateSelection = val;
      } else {
        this.$refs.multipleTable.toggleRowSelection(val);
      }
      this.$emit("rowClick", val);
    },
    //点击一行加高光
    $handleCurrentChange(val) {
      this.currentRow.push(val)
      this.$refs.multipleTable.setCurrentRow( val);
      this.$emit("handleCurrentChange", val);
    },
    //单选
    singleElection(row) {
      // this.templateSelection = this.rotationRuleList.indexOf(row);
      this.templateSelection = row;
      this.templateRadio = row.scalaId;
    },
    //table操作列
    clickAction(item, row) {
      this.$emit("handleOperate", item, row);
    },
    disabledFunc(item, row) {
      let type = typeof item.disabled;
      return type === "boolean"
        ? item.disabled
        : type === "function"
        ? item.disabled({ item, row })
        : false;
    },
    // 表格合并  2022-10-09
    objectSpanMethod ({ rowIndex, columnIndex }) {
      if (this.spanColumnArr.includes(columnIndex)) {
        // 二维数组存储的数据 取出
        const _row = this.spanArr[rowIndex]
        const _col = _row > 0 ? 1 : 0
        return {
          rowspan: _row,
          colspan: _col
        }
      } else {
        return false
      }
    },
    //  表尾合计行2022-10-12
    getSummaries(param) {
      const { columns, data } = param;
      const sums = [];
      columns.forEach((column, index) => {
        if (index === 0) {
          sums[index] = '总计';
          return;
        }
        const values = data.map(item => Number(item[column.property]));
        if (!values.every(value => isNaN(value))) {
          sums[index] = values.reduce((prev, curr) => {
            const value = Number(curr);
            if (!isNaN(value)) {
              return prev + curr;
            } else {
              return prev;
            }
          }, 0);
          sums[index] += "";
        } else {
          sums[index] = '';
        }
      });
      return sums;
    }   

  },
};
</script>
<style lang="scss" scoped>
.content {
  padding: 0.6rem 1.2rem;
  background-color: #0c3568;
  overflow: hidden;
  .myTable {
    margin-top: 20px;
  }
}
::v-deep .el-button--text {
  background: none !important;
  border: none;
}
::v-deep .el-select .el-input__inner {
  color: #fff !important;
}
/* 滚动轴颜色 */
/* ::-webkit-scrollbar-thumb {
  background:#419be3;  
  border-radius: 4px;
  
} */
/* 滚动轴背景色 */
::-webkit-scrollbar-track {
  /* background: #0c3568;   */
  background: #103c73;
}
</style>


--------------renderDom.vue-------------------
<script>
export default {
  name: 'RenderDom',
  functional: true,
  props: {
    row: Object,
    renderFunc: Function
  },
  render: function (h, ctx) {
    return ctx.props.renderFunc(h, ctx.props.row);
  }
};
</script>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值