PagingTable.vue 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. <template>
  2. <div class="filter" ref="filterEl">
  3. <slot name="filter"></slot>
  4. </div>
  5. <ElConfigProvider :size="isMobile ? '' : 'small'">
  6. <ElTable :data="tableData" :height="tableHeight" stripe v-loading="loading">
  7. <slot></slot>
  8. </ElTable>
  9. </ElConfigProvider>
  10. <div class="mt-4 flex justify-center">
  11. <ElPagination
  12. ref="paginEl"
  13. :layout="isMobile ? 'total, pager' : 'total, sizes, prev, pager, next, jumper'"
  14. v-model:page-size="pageConfig.pageSize"
  15. v-model:current-page="page"
  16. :total="total"
  17. :small="!isMobile"
  18. />
  19. </div>
  20. </template>
  21. <script setup>
  22. import { ref, onMounted, computed, watch, inject } from 'vue'
  23. import { http } from '@/plugins/http'
  24. import { ElMessage } from 'element-plus'
  25. import { useStorage, useElementBounding, useWindowSize } from '@vueuse/core'
  26. const props = defineProps({
  27. url: {
  28. type: String,
  29. required: true
  30. },
  31. query: {
  32. type: Object,
  33. default: () => ({})
  34. },
  35. order: {
  36. type: String,
  37. default: () => 'createdAt,desc'
  38. }
  39. })
  40. const search = computed(() => {
  41. const query = { ...(props.query || {}) }
  42. Object.keys(query).forEach((key) => {
  43. if (query[key] === null) {
  44. delete query[key]
  45. }
  46. })
  47. return {
  48. ...query,
  49. order: props.order
  50. }
  51. })
  52. const filterEl = ref(null)
  53. const paginEl = ref(null)
  54. const { height: filterHeight } = useElementBounding(filterEl)
  55. const { height: paginHeight } = useElementBounding(paginEl)
  56. const { height: windowHeight } = useWindowSize()
  57. const tableHeight = computed(() => windowHeight.value - 120 - filterHeight.value - paginHeight.value)
  58. const isMobile = inject('isMobile')
  59. const tableData = ref([])
  60. const page = ref(1)
  61. const pageConfig = useStorage('pageConfig', {
  62. pageSize: 20
  63. })
  64. const total = ref(0)
  65. const loading = ref(false)
  66. async function getData() {
  67. try {
  68. loading.value = true
  69. const res = await http.get(props.url, {
  70. page: page.value,
  71. pageSize: pageConfig.value.pageSize,
  72. ...search.value
  73. })
  74. loading.value = false
  75. tableData.value = res.data
  76. total.value = res.meta.total
  77. } catch (e) {
  78. loading.value = false
  79. ElMessage.error(e.message)
  80. }
  81. }
  82. onMounted(() => {
  83. getData()
  84. })
  85. watch(search, () => {
  86. console.log('search changed')
  87. if (page.value !== 1) {
  88. page.value = 1
  89. } else {
  90. getData()
  91. }
  92. })
  93. watch([page, pageConfig], () => {
  94. console.log('page changed')
  95. getData()
  96. })
  97. defineExpose({
  98. refresh() {
  99. getData()
  100. }
  101. })
  102. </script>
  103. <style lang="less" scoped>
  104. .filter {
  105. :deep(> *) {
  106. margin-bottom: 15px;
  107. margin-right: 15px;
  108. }
  109. }
  110. </style>