admission-admin/src/components/ProTable/index.vue

106 lines
2.9 KiB
Vue

<template>
<el-table
class="pro-table"
ref="tableRef"
v-loading="loading"
:data="tableData"
:row-key="rowKey"
:row-class-name="({ row }) => row[rowKey]"
:max-height="maxHeight"
@selection-change="selectionChange"
>
<slot />
<template v-for="item in tableColumns" :key="item">
<el-table-column v-if="item.type && columnTypes.includes(item.type)" v-bind="item"></el-table-column>
<TableColumn v-if="!item.type && item.prop" :column="item">
<template v-for="slot in Object.keys($slots)" #[slot]="scope">
<slot :name="slot" v-bind="scope" />
</template>
</TableColumn>
</template>
</el-table>
</template>
<script setup name="ProTable">
import { provide, reactive, ref, unref } from 'vue'
import TableColumn from './components/TableColumn.vue'
import useSelection from '@/hooks/useSelection'
const props = defineProps({
columns: {
type: Array,
default: () => []
},
tableData: {
type: Array,
default: () => []
},
loading: {
type: Boolean,
default: false
},
maxHeight: {
type: [Number, String],
default: ''
},
rowKey: {
type: String,
default: 'id'
}
})
const { isSelected, selectedList, selectedListIds, selectionChange } = useSelection(props.rowKey)
const columnTypes = ['selection', 'radio', 'index', 'expand', 'sort']
const tableRef = ref()
const enumMap = ref(new Map())
const tableColumns = reactive(props.columns)
// 扁平化 columns
const flatColumnsFunc = columns => {
columns.forEach(async column => {
// 设置enumMap
await setEnumMap(column)
})
}
// 定义 enumMap 存储 enum 值
const setEnumMap = async ({ prop, enum: enumValue }) => {
if (!enumValue) return
// 如果当前 enumMap 存在相同的值 return
if (enumMap.value.has(prop) && (typeof enumValue === 'function' || enumMap.value.get(prop) === enumValue)) return
// 当前 enum 为静态数据,则直接存储到 enumMap
if (typeof enumValue !== 'function') return enumMap.value.set(prop, unref(enumValue))
// 为了防止接口执行慢,而存储慢,导致重复请求,所以预先存储为[],接口返回后再二次存储
enumMap.value.set(prop, [])
// 当前 enum 为后台数据需要请求数据,则调用该请求接口,并存储到 enumMap
const { rows } = await enumValue()
enumMap.value.set(prop, rows)
}
flatColumnsFunc(tableColumns)
provide('enumMap', enumMap)
defineExpose({
tableRef,
isSelected,
selectedList,
selectedListIds
})
</script>
<style lang="scss" scoped>
.pro-table {
:deep(.el-table__header) {
width: 100% !important;
}
:deep(.el-table__body) {
width: 100% !important;
}
}
</style>