vue3 table table packaging

index.vue

<template>
  <div class="cst-list">
    <el-table :data="props.tableData" style="width: 100%" stripe ref="tableRef" :row-key="rowKey" :height="props.height "
      :size="props.tableSize" :border="props.border" @selection-change="handleSelectionChange" @select="handleSelect"
      @select-all="handleSelect" :highlight-current-row="props.highlightCurrentRow" @current-change="choiseTableItem">
      <template v-for="(item, index) in props.tHead" :key="index">
        <el-table-column v-if="item.slot" :prop="item.prop" :label="item.label" :width="item.width"
          :min-width="item.minWidth" :fixed="item.fixed" :type="item.type" :show-overflow-tooltip="item.tooltip"
          :align="item.align" :sortable="item.sortable" :formatter="item.formatter"
          :reserve-selection="item.reserveSelection">
          <template #default="scope">
            <slot :name="item.prop" :row="scope.row" :column="scope.column" :index="scope.$index"></slot>
          </template>
        </el-table-column>
        <el-table-column v-else :prop="item.prop" :label="item.label" :width="item.width" :min-width="item.minWidth\ "
          :fixed="item.fixed" :type="item.type" :show-overflow-tooltip="item.tooltip" :align="item.align"
          :sortable="item.sortable" :formatter="item.formatter" :reserve-selection="item.reserveSelection"
          :selectable="selectable"></el-table-column>
      </template>
    </el-table>
    <div class="page-box" :style="align">
      <el-pagination v-if="showPage" @size-change="handleSizeChange" @current-change="handleCurrentChange"
        :current-page="props.currentPage" :page-sizes="props.pageSizes" :page-size="props.pageSize" :layout="props.layout"
        :total="props.total"></el-pagination>
    </div>
  </div>
</template>
<script setup lang="ts">
import { computed, ref, inject } from 'vue'
import { Props, TypeOfYourItem } from "./type";

const emit = defineEmits([
  'select',
  'selection-change',
  'size-change',
  'update:pageSize',
  'update:currentPage',
  'current-change',
  'choiseTableItem'
])

const props: Props = defineProps({
  // zebra print
  stripe: {
    type: Boolean,
    default: true
  },
  //vertical border
  border: {
    type: Boolean,
    default: false
  },
  //Table size large / default /small
  tableSize: {
    type: String,
    default: 'default'
  },
  // table height
  height: {
    type: Number,
    default: null
  },
  // tooltip theme
  tooltipEffect: {
    type: String,
    default: 'dark'
  },
  // Render header data
  tHead: {
    type: Array,
    default: () => []
  },
  tableData: {
    type: Array,
    required: true
  },
  rowKey: {
    type: Function
  },
  currentPage: {
    type: Number,
    default: 1
  },
  pageSizes: {
    type: Array,
    default: () => [10, 20, 30, 50]
  },
  pageSize: {
    type: Number,
    default: 10
  },
  layout: {
    type: String,
    default: 'total, sizes, prev, pager, next, jumper'
  },
  total: {
    type: Number,
    default: 0
  },
  // Whether to display pagination
  isPage: {
    type: Boolean,
    default: true
  },
  //Paging position left | center | right
  pageAlign: {
    type: String,
    default: 'center'
  },
  highlightCurrentRow: {
    type: Boolean,
    default: false
  },
  // inject throws method name
  provideName: {
    type: String,
    default: 'selectable'
  },
})

const align = computed(() => {
  return { 'justify-content': props.pageAlign }
})

const showPage = computed(() => {
  return props.isPage & amp; & amp; props.tableData & amp; & amp; props.tableData.length > 0
})

const tableRef = ref()

//Table selection event
const handleSelectionChange = (val: any) => {
  emit('selection-change', val)
}
//Table selected
const handleSelect = (val: any, obj: any) => {
  emit('select', val, obj)
}
//The number of items per page changes
const handleSizeChange = (val: any) => {
  emit('size-change', val)
  emit('update:pageSize', val)
}

//Current page changes
const handleCurrentChange = (val: any) => {
  emit('update:currentPage', val)
  emit('current-change', val)
}

const handtop = () => {
  tableRef.value.toggleAllSelection() // Trigger the all-select event on the table table
}

const selectable = inject(`${props.provideName}`, () => () => true);

defineExpose({
  tableRef,
  handtop,
  selectable
})
const choiceTableItem = (val: any) => {
  emit('choiseTableItem', val)
}

</script>

<style lang="less" scoped>
.cst-list {
  .page-box {
    display: flex;
    margin-top: 24px;
  }
}
</style>

type.ts

export type Props = {
  stripe?: boolean;
  border?: boolean;
  tableSize?: string;
  height?: number;
  tooltipEffect?: string;
  tHead?: any;
  total: number;
  isPage: boolean,
  pageAlign: string,
  tableData: any,
  highlightCurrentRow: boolean,
  currentPage: number,
  pageSizes: any,
  pageSize: number,
  layout: string,
  provideName?: string,
}

export type TypeOfYourItem = {
  slot: Boolean,
  prop: String,
  label: String,
  width: Number | String,
  minWidth: Number | String,
  fixed: String | Boolean,
  type: String,
  tooltip: Boolean,
  align: String,
  sortable: Boolean | String,
  formatter: any,
  reserveSelection: Boolean,
}

used in components

<template>
  <el-card>
    <el-input placeholder="Please enter" style="width: 200px;"></el-input> & amp;nbsp;
    <el-input placeholder="Please enter" style="width: 200px;"></el-input> & amp;nbsp;
    <el-input placeholder="Please enter" style="width: 200px;"></el-input> & amp;nbsp;
    <el-input placeholder="Please enter" style="width: 200px;"></el-input> & amp;nbsp;
    <el-button type="primary">Search</el-button>
    <el-button type="primary">Reset</el-button>
  </el-card>
  <br />
  <el-card>
    <systemList
      :tHead="tHead"
      :tableData="tableData"
      v-model:current-page="dataState.pageinfo.currPage"
      v-model:page-size="dataState.pageinfo.pageSize"
      v-model:isPage="isPage"
      :total="dataState.pageinfo.total"
      @size-change="sizeChange"
      @current-change="currentChange"
    >
    <template #merchantStatus="{row}">
        {<!-- -->{ row }}
    </template>
    <template #operate="{row}">
        <el-button type="text">View details</el-button>
    </template>
    </systemList>
  </el-card>
</template>
<script setup lang="ts">
import systemList from '@/components/tablePagination/index.vue'
import { reactive, ref, toRefs } from 'vue'
import { TabForm, TypeOfYourItem } from "./type";

//Do not display pagination
const isPage = ref(true)

const dataState = reactive<TabForm>({
    pageinfo: {
        total: 0,
        currPage: 1,
        pageSize: 10
    },
    applyForm: {
        merchantStatus: '',
        rejectReason: ''
    },
    tableData: [
      {
        auditId: '123',
        merchantId: '123',
        merchantName: '123',
        applyTime: '123',
        merchantStatus: '123',
        auditTime: '123',
        operate: '123',
      },
      {
        auditId: '123',
        merchantId: '123',
        merchantName: '123',
        applyTime: '123',
        merchantStatus: '123',
        auditTime: '123',
        operate: '123',
      },
      {
        auditId: '123',
        merchantId: '123',
        merchantName: '123',
        applyTime: '123',
        merchantStatus: '123',
        auditTime: '123',
        operate: '123',
      },
      {
        auditId: '123',
        merchantId: '123',
        merchantName: '123',
        applyTime: '123',
        merchantStatus: '123',
        auditTime: '123',
        operate: '123',
      },
      {
        auditId: '123',
        merchantId: '123',
        merchantName: '123',
        applyTime: '123',
        merchantStatus: '123',
        auditTime: '123',
        operate: '123',
      },
    ],
})

const { tableData } = toRefs(dataState)
const tHead: TypeOfYourItem[] = [
    { align: 'center', tooltip: true, prop: 'auditId', label: 'Application number', minWidth: 100, slot: false },
    { align: 'center', tooltip: true, prop: 'merchantId', label: 'merchant number', minWidth: 100, slot: false },
    { align: 'center', tooltip: true, prop: 'merchantName', label: 'MerchantName', minWidth: 140, slot: false },
    { align: 'center', tooltip: true, prop: 'applyTime', label: 'application time', minWidth: 200, slot: false },
    { align: 'center', tooltip: true, prop: 'merchantStatus', label: 'Application status', minWidth: 140, slot: true },
    { align: 'center', tooltip: true, prop: 'auditTime', label: 'audit time', minWidth: 140, slot: false },
    { align: 'center', tooltip: true, prop: 'operate', label: 'operate', minWidth: 140, slot: true }
]

//The current page number changes
const currentChange = (val: number) => {
    dataState.pageinfo.currPage = val
    // Call list method
}
const sizeChange = (val: number) => {
    dataState.pageinfo.currPage = 1
    dataState.pageinfo.pageSize = val
}
</script>
<style lang="less" scoped>
</style>

type.ts

export type TabForm = {
  pageinfo: {
    total: number;
    currPage: number;
    pageSize: number;
  };
  applyForm: {
    merchantStatus: string;
    rejectReason: string;
  };
  tableData: {
    auditId: string;
    merchantId: string,
    merchantName: string,
    applyTime: string,
    merchantStatus: string,
    auditTime: string,
    operate: string,
  }[];
}

export type TypeOfYourItem = {
  slot: boolean,
  prop: string,
  label: string,
  align: number | string,
  minWidth: number | string,
  tooltip: boolean
}