index.vue 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. <template>
  2. <cwg-page-wrapper>
  3. <view v-if="isShow">
  4. <view v-if="typesList.length > 0 && cardList.length > 0" class="add-apply" @click="addApply">{{ t("cards.p10") }}
  5. </view>
  6. <FirstApply v-if="cardList.length == 0" />
  7. <VirtualCard v-else />
  8. </view>
  9. </cwg-page-wrapper>
  10. </template>
  11. <script setup lang="ts">
  12. import { ref, onMounted, watch, computed } from "vue";
  13. import type { CardInfo } from "@/api/ucard";
  14. import { useI18n } from "vue-i18n";
  15. import useRouter from "@/hooks/useRouter";
  16. import { ucardApi } from "@/api/ucard";
  17. import FirstApply from "./components/FirstApply.vue";
  18. import VirtualCard from "./components/VirtualCard.vue";
  19. import useUserStore from "@/stores/use-user-store";
  20. import useCardStore from "@/stores/use-card-store";
  21. import useGlobalStore from "@/stores/use-global-store";
  22. const userStore = useUserStore();
  23. const cardStore = useCardStore();
  24. const router = useRouter();
  25. const { t } = useI18n();
  26. const globalStore = useGlobalStore();
  27. const cardList = ref<CardInfo[]>([]);
  28. const typesList = ref<CardInfo[]>([]);
  29. const isShow = ref(false);
  30. async function applyList() {
  31. // 后台刷新最新卡列表,不阻塞已有缓存渲染
  32. globalStore.setFullScreenLoading(true);
  33. try {
  34. const [response1, response2, response3] = await Promise.all([
  35. ucardApi.cardList({ page: { current: 1, row: 10 }, a: 1 }),
  36. ucardApi.applyList({
  37. page: { current: 1, row: 100 },
  38. }),
  39. ucardApi.cardTypesList(),
  40. ]);
  41. const [data1, data2, data3] = await Promise.all([
  42. response1.data,
  43. response2.data,
  44. response3.data,
  45. ]);
  46. const merged = await mergeLists(data1, data2);
  47. cardList.value = merged;
  48. cardStore.saveUserCard(merged);
  49. cardTypesList(data3, data2);
  50. cardStore.saveApplyCard(data2);
  51. isShow.value = true;
  52. } catch (error) {
  53. // 请求失败时保留本地缓存的 cardList,避免页面空白
  54. console.error('加载卡片列表失败', error);
  55. } finally {
  56. globalStore.setFullScreenLoading(false);
  57. isShow.value = true;
  58. }
  59. }
  60. async function cardTypesList(data1, data2) {
  61. try {
  62. const recordTypeIds = new Set(
  63. data2.map((item) => {
  64. if (item.status != "fail" && item.status != "cancel") {
  65. return item.cardTypeId;
  66. }
  67. })
  68. );
  69. const result1 = data1;
  70. const result2 = result1.filter(
  71. (item) => !recordTypeIds.has(item.cardTypeId)
  72. );
  73. const result3 = result2.filter((item) =>
  74. item.supportHolderRegin.includes(this.businessForm.country)
  75. );
  76. typesList.value = result3;
  77. } catch (error) {
  78. typesList.value = [];
  79. }
  80. }
  81. async function mergeLists(list1, list2) {
  82. const mainList = list1.map((item) => {
  83. const { status, ...rest } = item;
  84. return {
  85. ...rest,
  86. activateStatus: status || null,
  87. status,
  88. };
  89. });
  90. const list3 = list2.filter((i) => i.status != "fail");
  91. const mainList2 = list3.map((item) => {
  92. const { status, ...rest } = item;
  93. return {
  94. ...rest,
  95. applyStatus: status || null,
  96. status,
  97. };
  98. });
  99. const mainCardTypeIds = new Set(mainList.map((i) => i.cardTypeId));
  100. const filteredList2 = mainList2.filter(
  101. (i) => !mainCardTypeIds.has(i.cardTypeId)
  102. );
  103. const latestMap = {};
  104. for (const item of filteredList2) {
  105. const cur = latestMap[item.cardTypeId];
  106. if (
  107. !cur ||
  108. new Date(item.addTime).getTime() > new Date(cur.addTime).getTime()
  109. ) {
  110. latestMap[item.cardTypeId] = { ...item, aId: item.id };
  111. }
  112. }
  113. const latestList2 = Object.values(latestMap);
  114. const latestList3 = latestList2.filter((i) => i.status != "cancel");
  115. return [...latestList3, ...mainList];
  116. }
  117. function addApply() {
  118. router.push("/select/card");
  119. }
  120. onMounted(() => {
  121. // 1. 先用本地缓存的卡列表快速渲染,提升首屏速度
  122. const cachedCards = (cardStore.userCard as any) || [];
  123. if (Array.isArray(cachedCards) && cachedCards.length > 0) {
  124. cardList.value = cachedCards as CardInfo[];
  125. isShow.value = true;
  126. }
  127. // 2. 异步拉取最新数据并更新缓存
  128. applyList();
  129. });
  130. </script>
  131. <style scoped lang="scss">
  132. @import "@/uni.scss";
  133. .add-apply {
  134. position: fixed;
  135. top: px2rpx(14);
  136. right: px2rpx(10);
  137. cursor: pointer;
  138. z-index: 100;
  139. display: flex;
  140. flex-direction: row;
  141. justify-content: center;
  142. align-items: center;
  143. gap: px2rpx(4);
  144. min-width: px2rpx(100);
  145. padding: 0 px2rpx(10);
  146. height: px2rpx(30);
  147. background: #ea002a;
  148. border-radius: px2rpx(100);
  149. font-size: px2rpx(14);
  150. color: #ffffff;
  151. }
  152. </style>