list.vue 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. <template>
  2. <view>
  3. <!-- @scrolltolower="scrolltolower" -->
  4. <up-list style="height: auto" id="item_height" class="wrap_list">
  5. <up-list-item v-for="(item, index) in lists" :key="index">
  6. <slot name="item" :item="item" :index="index"></slot>
  7. </up-list-item>
  8. </up-list>
  9. <view class="null_warp" v-if="isLoaded && !lists.length && !isLoading">
  10. <slot name="null">
  11. <view class="null_text">{{ t(nullText || "无数据") }}</view>
  12. </slot>
  13. </view>
  14. <template v-if="(!!status && lists.length) || isLoading">
  15. <view class="load_more">
  16. <u-loadmore
  17. :status="status"
  18. :loading-text="t(loadingText)"
  19. :loadmore-text="t(loadmoreText)"
  20. :nomore-text="t(nomoreText)"
  21. />
  22. </view>
  23. </template>
  24. </view>
  25. </template>
  26. <script setup>
  27. import { query, $post, systemInfo } from "@/utils";
  28. import { ref, nextTick, computed } from "vue";
  29. import { t } from "@/locale";
  30. import { useCacheStore } from "@/store";
  31. const useCache = useCacheStore();
  32. const props = defineProps({
  33. topHeight: {
  34. type: Number,
  35. default: 0,
  36. },
  37. url: {
  38. type: String,
  39. default: "",
  40. },
  41. pageSize: {
  42. type: Number,
  43. default: 10,
  44. },
  45. defaultParams: {
  46. type: Object,
  47. default: () => {},
  48. },
  49. nullText: String,
  50. loadingText: {
  51. type: String,
  52. default: "正在加载中",
  53. },
  54. loadmoreText: {
  55. type: String,
  56. default: "加载更多",
  57. },
  58. nomoreText: {
  59. type: String,
  60. default: "没有更多了",
  61. },
  62. getIndex: {
  63. type: Number,
  64. default: 0,
  65. },
  66. activeIndex: {
  67. type: Number,
  68. default: 0,
  69. },
  70. isCache: Boolean,
  71. isLoading: Boolean,
  72. });
  73. const emit = defineEmits(["datas"]);
  74. const lists = ref([]);
  75. const page = ref(1);
  76. const totals = ref(0);
  77. const status = ref("nomore");
  78. const noData = ref(false);
  79. const height = ref(0);
  80. const isLoaded = ref(false);
  81. const scrolltolower = () => {
  82. if (!noData.value) {
  83. let num = page.value;
  84. num += 1;
  85. page.value = num;
  86. nextTick(() => {
  87. getData(true);
  88. });
  89. }
  90. };
  91. const deleteSpace = (str) => {
  92. return str.replace(/\s+/g, "");
  93. };
  94. const getData = async (flag = false) => {
  95. let newFlag = flag;
  96. const _list = useCache.getShopList(
  97. props.defaultParams?.channel,
  98. props.defaultParams?.keyWord
  99. );
  100. if (_list && props.isCache && !flag) {
  101. let search_text =
  102. props.defaultParams.keyWord && deleteSpace(props.defaultParams.keyWord);
  103. const searchKey = `search_${search_text}`;
  104. const { page: pageNum, children } = _list;
  105. page.value = pageNum;
  106. if (children[searchKey]) {
  107. lists.value = children[searchKey];
  108. emit("datas", children[searchKey]);
  109. nextTick(() => {
  110. getHeight();
  111. });
  112. } else {
  113. newFlag = true;
  114. }
  115. isLoaded.value = true;
  116. if (newFlag) {
  117. } else {
  118. return;
  119. }
  120. }
  121. try {
  122. status.value = "loading";
  123. const {
  124. data: {
  125. data: { item: data, total_results: count },
  126. },
  127. } = await $post(
  128. props.url,
  129. {
  130. pageSize: props.pageSize,
  131. page: page.value,
  132. ...props.defaultParams,
  133. },
  134. { isLoading: props.isLoading }
  135. );
  136. status.value = "nomore";
  137. if (data.length >= count) {
  138. noData.value = true;
  139. } else {
  140. noData.value = false;
  141. }
  142. totals.value = count - 0;
  143. if (page.value > 1) {
  144. const arrList = lists.value;
  145. lists.value = [...arrList, ...data];
  146. !props.defaultParams.img &&
  147. useCache.setShopList(
  148. props.defaultParams.channel,
  149. page.value,
  150. data,
  151. props.defaultParams.keyWord
  152. );
  153. emit("datas", lists.value);
  154. nextTick(() => {
  155. getHeight();
  156. });
  157. return;
  158. }
  159. lists.value = data;
  160. isLoaded.value = true;
  161. !props.defaultParams.img &&
  162. useCache.setShopList(
  163. props.defaultParams.channel,
  164. page.value,
  165. data,
  166. props.defaultParams.keyWord
  167. );
  168. emit("datas", lists.value);
  169. nextTick(() => {
  170. getHeight();
  171. });
  172. } catch (error) {
  173. console.error(error, "getData");
  174. isLoaded.value = true;
  175. }
  176. };
  177. const getHeight = async (name = "#item_height") => {
  178. const { height: heights } = await query(name, this);
  179. nextTick(() => {
  180. height.value = heights || 0;
  181. const { windowHeight, statusBarHeight } = systemInfo();
  182. let contHeight = windowHeight - 44 - props.topHeight;
  183. if (height < contHeight) {
  184. scrolltolower();
  185. }
  186. });
  187. return height;
  188. };
  189. const handleRefresh = (flag = false) => {
  190. page.value = 1;
  191. status.value = "nomore";
  192. noData.value = false;
  193. isLoaded.value = false;
  194. if (!flag) {
  195. lists.value = [];
  196. }
  197. nextTick(() => {
  198. getData(flag);
  199. });
  200. };
  201. const setList = (_list) => {
  202. nextTick(() => {
  203. lists.value = _list;
  204. emit("datas", lists.value);
  205. nextTick(() => {
  206. getHeight();
  207. });
  208. });
  209. };
  210. defineExpose({
  211. handleRefresh,
  212. setList,
  213. getData,
  214. scrolltolower,
  215. });
  216. </script>
  217. <style lang="less" scoped>
  218. @import url("@/style.less");
  219. :deep(.u-list) {
  220. height: 100% !important;
  221. }
  222. /deep/ .uni-scroll-view {
  223. overflow: unset !important;
  224. }
  225. .null_warp {
  226. .null_text {
  227. min-height: 100rpx;
  228. .flex_center();
  229. font-size: 28rpx;
  230. color: #333;
  231. }
  232. }
  233. .load_more {
  234. padding: 16rpx 0;
  235. }
  236. </style>