PagingTable.vue 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  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. where: {
  32. type: Object,
  33. default: () => ({})
  34. },
  35. order: {
  36. type: Object,
  37. default: () => ({ createdAt: 'DESC' })
  38. }
  39. })
  40. const search = computed(() => {
  41. const where = { ...(props.where || {}) }
  42. Object.keys(where).forEach((key) => {
  43. if (where[key] === null) {
  44. delete where[key]
  45. }
  46. })
  47. return {
  48. where: props.where,
  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.post(props.url, {
  70. page: {
  71. page: page.value,
  72. limit: pageConfig.value.pageSize
  73. },
  74. search: search.value
  75. })
  76. loading.value = false
  77. tableData.value = res.items
  78. total.value = res.meta.totalItems
  79. } catch (e) {
  80. loading.value = false
  81. ElMessage.error(e.message)
  82. }
  83. }
  84. onMounted(() => {
  85. getData()
  86. })
  87. watch(search, () => {
  88. console.log('search changed')
  89. if (page.value !== 1) {
  90. page.value = 1
  91. } else {
  92. getData()
  93. }
  94. })
  95. watch([page, pageConfig], () => {
  96. console.log('page changed')
  97. getData()
  98. })
  99. defineExpose({
  100. refresh() {
  101. getData()
  102. }
  103. })
  104. </script>
  105. <style lang="less" scoped>
  106. .filter {
  107. :deep(> *) {
  108. margin-bottom: 15px;
  109. margin-right: 15px;
  110. }
  111. }
  112. </style>