<template>
<div class="scTable" ref="scTableMain" :style="{ height: theight }" v-loading="loading">
<div :class="!hideDo ? 'scTable-table' : 'scTable-table-noPag'">
<el-table
v-bind="$attrs"
:data="tableData"
:row-key="rowKey"
:key="toggleIndex"
ref="scTable"
height="100%"
@sort-change="sortChange"
@filter-change="filterChange"
>
<slot></slot>
<template v-for="(item, index) in userColumn" :key="index">
<el-table-column
v-if="!item.hide"
:column-key="item.prop"
:label="item.label"
:prop="item.prop"
:width="item.width"
:sortable="item.sortable"
:fixed="item.fixed"
:filters="item.filters"
:filter-method="remoteFilter || !item.filters ? null : filterHandler"
>
<template #default="scope">
<slot :name="item.prop" v-bind="scope">
{{ scope.row[item.prop] }}
</slot>
</template>
</el-table-column>
</template>
<el-table-column min-width="1"></el-table-column>
<template #empty>
<el-empty :description="emptyText" :image-size="80"></el-empty>
</template>
</el-table>
</div>
<div class="scTable-page" v-if="!hidePagination && !hideDo">
<div class="scTable-pagination">
<el-pagination
v-if="!hidePagination"
background
:small="true"
:layout="paginationLayout"
:total="total"
:page-size="pageSize"
:pager-count="pagerCount"
v-model:currentPage="currentPage"
@current-change="paginationChange"
></el-pagination>
</div>
<div class="scTable-do" v-if="!hiderefresh">
<el-button
@click="refresh"
icon="el-icon-refresh"
circle
style="margin-left: 15px"
></el-button>
</div>
</div>
</div>
</template>
<script>
import { reactive, watch, onMounted, ref, toRefs, getCurrentInstance, computed } from 'vue'
import config from '@/config/table'
export default {
name: 'scTable',
props: {
tableName: { type: String, default: '' },
apiObj: { type: Object, default: () => {} },
params: { type: Object, default: () => ({}) },
data: { type: Object, default: () => {} },
height: { type: [String, Number], default: '100%' },
rowKey: { type: String, default: '' },
column: { type: Object, default: () => {} },
hideDo: { type: Boolean, default: false }, // 是否显示分页
pagerCount: { type: Number, default: 7 }, // 是否显示分页
hiderefresh: { type: Boolean, default: false }, // 是否显示刷新
remoteSort: { type: Boolean, default: false },
remoteFilter: { type: Boolean, default: false },
hidePagination: { type: Boolean, default: false },
paginationLayout: { type: String, default: 'total, prev, pager, next, jumper' }
},
setup(props) {
const { proxy } = getCurrentInstance()
const scTable = ref(null)
const scTableMain = ref(null)
const state = reactive({
emptyText: '暂无数据',
toggleIndex: 0,
tableData: [],
pageSize: config.pageSize,
total: 0,
currentPage: 1,
prop: null,
order: null,
loading: false,
tableHeight: '100%',
tableParams: props.params,
userColumn: []
})
// 计算高度
const theight = computed(() => {
return Number(props.height) ? `${Number(props.height)}px` : props.height
})
// 监听响应式对象
watch(
() => [props.data, props.apiObj],
([newdataValue, newapiObjValue], [olddataValue, oldapiObjValue]) => {
// 判断是不是newdataValue发生的变化
if (olddataValue !== newdataValue) {
if (props.data != undefined) {
state.tableData = props.data
state.total = state.tableData.length
}
}
// 判断是不是oldapiObjValue发生的变化
if (oldapiObjValue !== newapiObjValue) {
state.tableParams = props.params
refresh()
}
}
)
onMounted(() => {
state.userColumn = props.column
// 判断是否静态数据
if (props.apiObj) {
getData()
} else if (props.data) {
state.tableData = props.data
state.total = state.tableData.length
}
})
// 获取数据
const getData = async () => {
state.loading = true
const reqData = {
[config.request.page]: state.currentPage,
[config.request.pageSize]: state.pageSize
}
if (props.hidePagination) {
delete reqData[config.request.page]
delete reqData[config.request.pageSize]
}
Object.assign(reqData, state.tableParams)
try {
var res = await props.apiObj.get(reqData)
} catch (error) {
console.log(error)
state.loading = false
state.emptyText = error.statusText
return false
}
if (res.code != 200) {
state.loading = false
state.emptyText = res.msg
} else {
state.emptyText = '暂无数据'
if (res.data) {
state.tableData = res.data.list
state.total = res.data.total
} else {
state.tableData = []
state.total = 0
}
state.loading = false
}
scTable.value.$el.querySelector('.el-table__body-wrapper').scrollTop = 0
}
// 分页点击
const paginationChange = () => {
getData()
}
// 刷新数据
const refresh = () => {
scTable.value.clearSelection()
getData()
}
// 更新数据 合并上一次params
const upData = (params, page = 1) => {
state.currentPage = page
scTable.value.clearSelection()
Object.assign(state.tableParams, params || {})
getData()
}
// 清空数据data
const clearData = () => {
state.tableData = []
}
// 重载数据 替换params
const reload = (params, page = 1) => {
state.currentPage = page
state.tableParams = params || {}
scTable.value.clearSelection()
scTable.value.clearSort()
scTable.value.clearFilter()
getData()
}
// 排序事件
const sortChange = (obj) => {
if (!props.remoteSort) {
return false
}
if (obj.column && obj.prop) {
state.prop = obj.prop
state.order = obj.order
} else {
state.prop = null
state.order = null
}
getData()
}
// 本地过滤
const filterHandler = (value, row, column) => {
const property = column.property
return row[property] === value
}
// 过滤事件
const filterChange = (filters) => {
if (!props.remoteFilter) {
return false
}
Object.keys(filters).forEach((key) => {
filters[key] = filters[key].join(',')
})
upData(filters)
}
// 原生方法转发
const clearSelection = () => {
scTable.value.clearSelection()
}
const toggleRowSelection = (row, selected) => {
scTable.value.toggleRowSelection(row, selected)
}
const toggleAllSelection = () => {
scTable.value.toggleAllSelection()
}
const toggleRowExpansion = (row, expanded) => {
scTable.value.toggleRowExpansion(row, expanded)
}
const setCurrentRow = (row) => {
scTable.value.setCurrentRow(row)
}
const clearSort = () => {
scTable.value.clearSort()
}
const clearFilter = (columnKey) => {
scTable.value.clearFilter(columnKey)
}
const doLayout = () => {
scTable.value.doLayout()
}
const sort = (prop, order) => {
scTable.value.sort(prop, order)
}
return {
...toRefs(state),
scTable,
scTableMain,
getData,
paginationChange,
refresh,
upData,
reload,
sortChange,
filterHandler,
filterChange,
clearSelection,
toggleRowSelection,
toggleAllSelection,
toggleRowExpansion,
setCurrentRow,
clearSort,
clearFilter,
doLayout,
sort,
clearData,
theight
}
}
}
</script>
<style scoped>
.scTable {
}
.scTable-table {
height: calc(100% - 50px);
}
.scTable-table-noPag {
height: 100%;
}
.scTable-page {
height: 50px;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 15px;
}
.scTable-do {
white-space: nowrap;
}
</style>
|