forked from iod/cpnode-front
172 lines
4.0 KiB
Vue
172 lines
4.0 KiB
Vue
<template>
|
|
<div v-loading="loading" class="pro-table">
|
|
<div class="header">
|
|
<div class="action-container">
|
|
<el-button
|
|
v-if="props.createText"
|
|
type="primary"
|
|
size="mini"
|
|
:icon="Plus"
|
|
@click="onCreate"
|
|
>
|
|
{{ props.createText }}
|
|
</el-button>
|
|
</div>
|
|
</div>
|
|
<el-table :data="displayTableData" v-bind="$attrs">
|
|
<slot></slot>
|
|
</el-table>
|
|
<el-config-provider :locale="zhCn">
|
|
<el-pagination
|
|
v-if="paginationInfo.showPagination"
|
|
class="pagination"
|
|
:current-page="paginationInfo.currentPage"
|
|
layout="total, jumper, prev, pager, next, sizes"
|
|
:page-size="paginationInfo.pageSize"
|
|
:total="paginationInfo.total"
|
|
@size-change="handleSizeChange"
|
|
@current-change="handleCurrentChange"
|
|
>
|
|
</el-pagination>
|
|
</el-config-provider>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { defineProps, withDefaults, provide, ref } from 'vue'
|
|
|
|
import zhCn from 'element-plus/lib/locale/lang/zh-cn'
|
|
import { Plus } from '@element-plus/icons-vue'
|
|
|
|
import {
|
|
ITableDataItem,
|
|
IPaginationInfo,
|
|
IOnCreated,
|
|
} from '~/interfaces/proTable'
|
|
import {
|
|
DELETE_ROW,
|
|
UPDATE_ROW,
|
|
PAGINATION_INFO,
|
|
CREATE_ROW,
|
|
} from '~/constants/proTable'
|
|
import { HandleProTableData } from '~/tools/proTable'
|
|
|
|
interface Props {
|
|
request: () => Promise<{ data: ITableDataItem[] }>
|
|
// 分页
|
|
showPagination?: boolean
|
|
currentPage?: number
|
|
pageSize?: number
|
|
pageSizes?: number[]
|
|
// header
|
|
createText?: string
|
|
}
|
|
const props = withDefaults(defineProps<Props>(), {
|
|
currentPage: 1,
|
|
pageSize: 10,
|
|
pageSizes: () => [10, 20, 30, 40, 50, 100],
|
|
showPagination: true,
|
|
})
|
|
|
|
const emit = defineEmits(['onCreated'])
|
|
|
|
// 分页
|
|
const paginationInfo = ref<IPaginationInfo>({
|
|
currentPage: props.currentPage,
|
|
pageSize: props.pageSize,
|
|
pageSizes: props.pageSizes,
|
|
showPagination: props.showPagination,
|
|
total: 0,
|
|
})
|
|
const handleSizeChange = (val: number) => {
|
|
paginationInfo.value.pageSize = val
|
|
updateTheView()
|
|
}
|
|
const handleCurrentChange = (val: number) => {
|
|
paginationInfo.value.currentPage = val
|
|
updateTheView()
|
|
}
|
|
// 数据获取
|
|
const tableData = ref<ITableDataItem[]>([])
|
|
const displayTableData = ref<ITableDataItem[]>(tableData.value)
|
|
const loading = ref(false)
|
|
async function getData() {
|
|
try {
|
|
loading.value = true
|
|
const { data } = await props.request()
|
|
tableData.value = data
|
|
paginationInfo.value.total = tableData.value?.length
|
|
updateTheView()
|
|
loading.value = false
|
|
} catch (e) {
|
|
loading.value = false
|
|
console.log((e as Error).message)
|
|
}
|
|
}
|
|
onMounted(async () => {
|
|
await getData()
|
|
})
|
|
|
|
const updateTheView = () => {
|
|
if (!paginationInfo.value?.showPagination) {
|
|
displayTableData.value = tableData.value
|
|
}
|
|
const { currentPage, pageSize } = paginationInfo.value
|
|
const pageStart: number = (currentPage - 1) * pageSize
|
|
displayTableData.value = tableData.value.slice(
|
|
pageStart,
|
|
pageStart + pageSize,
|
|
)
|
|
paginationInfo.value.total = tableData.value.length
|
|
}
|
|
|
|
const handleTable = computed(() => {
|
|
return new HandleProTableData(updateTheView, tableData)
|
|
})
|
|
|
|
const onCreate = () => {
|
|
emit('onCreated', handleTable.value.createRow)
|
|
}
|
|
|
|
// 暴漏给给父组件用的方法
|
|
defineExpose({
|
|
paginationInfo,
|
|
...handleTable.value,
|
|
})
|
|
|
|
// 发送给后代组件使用
|
|
provide(PAGINATION_INFO, paginationInfo)
|
|
provide(UPDATE_ROW, handleTable.value.updatedRow)
|
|
provide(DELETE_ROW, handleTable.value.deleteRow)
|
|
provide(CREATE_ROW, handleTable.value.createRow)
|
|
</script>
|
|
|
|
<style scoped lang="scss">
|
|
.pro-table {
|
|
width: 100%;
|
|
|
|
.header {
|
|
margin-bottom: 8px;
|
|
}
|
|
|
|
.pagination {
|
|
display: flex;
|
|
justify-content: flex-end;
|
|
margin-top: 15px;
|
|
$marginLeft: 15px;
|
|
|
|
::v-deep(.btn-prev) {
|
|
margin-left: $marginLeft !important;
|
|
}
|
|
|
|
::v-deep(.el-input) {
|
|
margin-left: $marginLeft !important;
|
|
}
|
|
|
|
::v-deep(.el-pager li) {
|
|
margin: 0 2px;
|
|
}
|
|
}
|
|
}
|
|
</style>
|