page-helper-evo.vue 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. <script setup lang="ts" generic="T extends Object, R extends { list: T[] }, Q extends T">
  2. import { ResPageData } from '../core/libs/models'
  3. import { NetImages } from '../core/libs/net-images'
  4. import { getRect, addUnit } from 'wot-design-uni/components/common/util'
  5. const props = withDefaults(
  6. defineProps<{
  7. request: (query: any) => Promise<IResData<R>>
  8. query?: Partial<Q> & { [key: symbol]: any }
  9. automatic?: boolean
  10. isLoadMore?: boolean
  11. }>(),
  12. { automatic: true, isLoadMore: true, query: () => ({}) },
  13. )
  14. const slot = defineSlots<{
  15. default(props: { data?: R['list']; items?: T[]; source?: R }): any
  16. top: () => any
  17. }>()
  18. const { proxy } = getCurrentInstance() as any
  19. const pageNo = ref(1)
  20. const pageSize = ref(10)
  21. const nomore = ref(false)
  22. const topRef = ref()
  23. const height = ref(0)
  24. const windowInfo = ref<UniNamespace.GetWindowInfoResult>()
  25. const { data, run: setData } = useRequest(
  26. () => props.request({ pageNo: pageNo.value, pageSize: pageSize.value, ...props.query }),
  27. { immediate: false },
  28. )
  29. const items = ref<T[]>([])
  30. const setPlaceholderHeight = () => {
  31. getRect('.bottom-app-bar', false, proxy).then((res) => {
  32. height.value = res.height as number
  33. })
  34. }
  35. onMounted(async () => {
  36. nextTick(() => {
  37. setPlaceholderHeight()
  38. })
  39. windowInfo.value = await uni.getWindowInfo()
  40. if (props.automatic) {
  41. console.log('Page Helper Automatic')
  42. await setData()
  43. items.value = data.value?.list || []
  44. }
  45. })
  46. watch(
  47. () => props.query,
  48. async () => {
  49. console.log('Page Helper Query Change')
  50. pageNo.value = 1
  51. pageSize.value = 10
  52. await setData()
  53. items.value = data.value?.list || []
  54. },
  55. )
  56. onReachBottom(async () => {
  57. console.log('Page Helper Reach Bottom')
  58. if (!props.isLoadMore) return
  59. if (data.value?.list?.length < pageSize.value) {
  60. return (nomore.value = true)
  61. }
  62. pageNo.value++
  63. await setData()
  64. items.value = items.value.concat(data.value?.list || [])
  65. })
  66. defineExpose({
  67. reload: async () => {
  68. console.log('Page Helper Reload')
  69. pageNo.value = 1
  70. pageSize.value = 10
  71. await setData()
  72. items.value = data.value?.list || []
  73. },
  74. refresh: async () => {
  75. console.log('Page Helper Refresh')
  76. await setData()
  77. // 之前页的数据
  78. const prevItems = items.value.slice(0, pageSize.value * (pageNo.value - 1))
  79. // 之后页的数据
  80. const nextItems = items.value.slice(pageSize.value * pageNo.value, items.value.length)
  81. items.value = prevItems.concat(data.value?.list || [], nextItems)
  82. // console.log(items.value)
  83. },
  84. })
  85. </script>
  86. <template>
  87. <div
  88. class="flex-grow flex flex-col"
  89. :style="{ paddingBottom: addUnit(windowInfo?.safeAreaInsets.bottom || 0) }"
  90. >
  91. <div class="relative" :style="{ height: addUnit(height) }">
  92. <div
  93. ref="topRef"
  94. class="bottom-app-bar fixed absolute left-0 right-0 z-1"
  95. :style="{ top: addUnit(windowInfo?.windowTop || 0) }"
  96. >
  97. <!-- {{ topRef.offsetHeight }} -->
  98. <slot name="top"></slot>
  99. </div>
  100. </div>
  101. <div class="flex-grow flex flex-col">
  102. <template v-if="!items?.length">
  103. <div class="flex-grow flex flex-col justify-center">
  104. <wd-status-tip :image="NetImages.NotContent" tip="暂无内容"></wd-status-tip>
  105. </div>
  106. </template>
  107. <div v-if="items.length" class="flex-grow flex flex-col">
  108. <slot :source="{ list: items }"></slot>
  109. </div>
  110. <!-- <template v-if="nomore">
  111. <div class="my-4"><wd-divider>没有更多了</wd-divider></div>
  112. </template> -->
  113. </div>
  114. </div>
  115. </template>