select.vue 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. <template>
  2. <cwg-page-wrapper>
  3. <view class="page">
  4. <view class="select-card-desc">{{ t('pages.card.select') }}</view>
  5. <view class="card-types-container">
  6. <swiper class="card-types-wrapper" :circular="false" :duration="300" :current="currentCardIndex"
  7. @change="handleSwiperChange">
  8. <swiper-item v-for="(type, index) in cardTypes" :key="index" class="card-box">
  9. <image src="/static/images/select-card-1.png" mode="aspectFit" />
  10. <view class="card-info">
  11. <view class="card-title">{{ type.cardName }}</view>
  12. <view class="card-content">{{ type.cardDesc }}</view>
  13. <view class="card-list">
  14. <view class="card-item">
  15. <text class="label">{{ t('card.New.n6') }}</text>
  16. <text>{{ type.currency || 'USD' }}</text>
  17. </view>
  18. <view class="card-item">
  19. <text class="label">{{ t('card.New.n7') }}</text>
  20. <text>{{ type.rechargeMinQuota }} USD</text>
  21. </view>
  22. <view class="card-item">
  23. <text class="label">{{ t('card.New2.n8') }}</text>
  24. <text>{{ type.rechargeMaxQuota }} USD</text>
  25. </view>
  26. <view class="card-item">
  27. <text class="label">{{ t('card.New.n9') }}</text>
  28. <text>{{ type.rechargeFeeRate }} %</text>
  29. </view>
  30. <view class="card-item one">
  31. <text class="label">{{ t('card.New.n4') }}</text>
  32. <text>
  33. <text v-if="type.originalCardFee > type.cardFee" class="strike strike1">{{
  34. type.originalCardFee }}</text>
  35. <text class="strike1">{{ type.cardFee }} USD</text>
  36. </text>
  37. </view>
  38. <view class="card-item" v-if="isPromotionActive">
  39. <text class="k"></text>
  40. <text class="v strike1" v-t="'card.New3.p13'"></text>
  41. </view>
  42. </view>
  43. </view>
  44. </swiper-item>
  45. </swiper>
  46. <view class="swiper-indicators" v-if="cardTypes.length > 1">
  47. <view v-for="(card, index) in cardTypes" :key="card.id || index" class="indicator-dot"
  48. :class="{ active: index === currentCardIndex }" @click="currentCardIndex = index"></view>
  49. </view>
  50. </view>
  51. <view class="fixed-btn">
  52. <view class="cwg-button">
  53. <u-button type="primary" block @click="handleSubmit">{{ t('card.Btn.Next') }}</u-button>
  54. </view>
  55. </view>
  56. </view>
  57. </cwg-page-wrapper>
  58. </template>
  59. <script setup lang="ts">
  60. import { ref, onMounted, computed } from 'vue'
  61. import type { CardType } from '@/api/ucard'
  62. import { useI18n } from 'vue-i18n'
  63. import useRouter from '@/hooks/useRouter'
  64. import useGlobalStore from '@/stores/use-global-store'
  65. import { ucardApi } from '@/api/ucard'
  66. const isPromotionActive = computed(() => {
  67. const now = new Date();
  68. return now <= new Date('2026-01-31T23:59:59');
  69. })
  70. const globalStore = useGlobalStore()
  71. const router = useRouter()
  72. const { t } = useI18n()
  73. const cardTypes = ref<CardType[]>([])
  74. const currentCardIndex = ref(0)
  75. function handleSwiperChange(e: any) {
  76. const current = e.detail?.current ?? 0
  77. currentCardIndex.value = current
  78. }
  79. async function getCardTypes() {
  80. globalStore.setFullScreenLoading(true)
  81. try {
  82. const [response1, response2] = await Promise.all([
  83. ucardApi.cardTypesList(),
  84. ucardApi.applyList({
  85. page: { current: 1, row: 100 },
  86. }),
  87. ])
  88. const [data1, data2] = await Promise.all([response1.data, response2.data])
  89. const recordTypeIds = new Set(
  90. data2.map((item) => {
  91. if (item.status != 'fail' && item.status != 'cancel') {
  92. return item.cardTypeId
  93. }
  94. }),
  95. )
  96. const result1 = data1
  97. const result2 = result1.filter((item) => !recordTypeIds.has(item.cardTypeId))
  98. // const result3 = result2.filter((item) => item.supportHolderRegin.includes(this.businessForm.country))
  99. cardTypes.value = [...result2]
  100. console.log(cardTypes.value, 1212);
  101. globalStore.setFullScreenLoading(false)
  102. } catch (error) {
  103. console.log(error)
  104. globalStore.setFullScreenLoading(false)
  105. cardTypes.value = []
  106. }
  107. }
  108. function handleSubmit() {
  109. const selectedCard = cardTypes.value[currentCardIndex.value]
  110. if (!selectedCard) {
  111. uni.showToast({
  112. title: t('cards.selectCard') || '请先选择卡片',
  113. icon: 'none'
  114. })
  115. return
  116. }
  117. router.push({
  118. path: '/pages/card/apply',
  119. query: {
  120. cardTypeId: selectedCard.cardTypeId,
  121. type: selectedCard.type,
  122. },
  123. })
  124. }
  125. onMounted(() => {
  126. getCardTypes()
  127. })
  128. </script>
  129. <style scoped lang="scss">
  130. @import "@/uni.scss";
  131. .page {
  132. padding-bottom: px2rpx(100);
  133. }
  134. .select-card-desc {
  135. color: #474747;
  136. width: 100%;
  137. text-align: left;
  138. font-size: var(--font-size-16);
  139. line-height: px2rpx(24);
  140. margin-bottom: px2rpx(20);
  141. }
  142. .card-types-container {
  143. width: 100%;
  144. position: relative;
  145. overflow: hidden;
  146. margin-bottom: px2rpx(40);
  147. }
  148. .card-types-wrapper {
  149. width: 100%;
  150. height: px2rpx(600);
  151. }
  152. :deep(.swiper-item) {
  153. height: 100%;
  154. display: flex;
  155. align-items: flex-start;
  156. justify-content: center;
  157. }
  158. .card-box {
  159. width: 100%;
  160. height: 100%;
  161. border-radius: px2rpx(20);
  162. // padding: px2rpx(16);
  163. display: flex;
  164. flex-direction: column;
  165. align-items: center;
  166. box-sizing: border-box;
  167. overflow-y: auto;
  168. image {
  169. width: 100%;
  170. height: auto;
  171. max-height: px2rpx(200);
  172. flex-shrink: 0;
  173. }
  174. }
  175. .card-info {
  176. width: 100%;
  177. margin-top: px2rpx(16);
  178. flex: 1;
  179. display: flex;
  180. flex-direction: column;
  181. }
  182. .card-title {
  183. margin: px2rpx(24) 0 px2rpx(12) 0;
  184. font-weight: 600;
  185. font-size: px2rpx(22);
  186. line-height: px2rpx(28);
  187. text-align: left;
  188. color: #1a1a1a;
  189. }
  190. .card-content {
  191. font-size: var(--font-size-16);
  192. color: #474747;
  193. margin: 0 0 px2rpx(26) 0;
  194. text-align: left;
  195. line-height: px2rpx(24);
  196. }
  197. .card-list {
  198. width: 100%;
  199. padding: px2rpx(12) 0;
  200. margin: 0;
  201. box-shadow: 0 4px 20px rgba(140, 145, 143, 0.194);
  202. border-radius: px2rpx(10);
  203. background: #fff;
  204. }
  205. .card-item {
  206. display: flex;
  207. justify-content: space-between;
  208. align-items: center;
  209. font-size: px2rpx(14);
  210. color: #1a1a1a;
  211. padding: px2rpx(12) px2rpx(24);
  212. transition: all 0.3s ease;
  213. position: relative;
  214. font-family: 'Roboto';
  215. font-style: normal;
  216. font-weight: 600;
  217. line-height: px2rpx(20);
  218. text {
  219. display: inline-block;
  220. }
  221. }
  222. .label {
  223. width: px2rpx(200);
  224. font-weight: 600;
  225. font-size: px2rpx(14);
  226. line-height: px2rpx(20);
  227. color: #8e8a8a;
  228. }
  229. .card-item:last-child {
  230. margin-bottom: 0;
  231. }
  232. .swiper-indicators {
  233. display: flex;
  234. justify-content: center;
  235. align-items: center;
  236. margin-top: px2rpx(16);
  237. gap: px2rpx(8);
  238. }
  239. .indicator-dot {
  240. width: px2rpx(9);
  241. height: px2rpx(9);
  242. border-radius: 50%;
  243. background: var(--gray);
  244. transition: all 0.3s ease;
  245. &.active {
  246. background-color: var(--main-yellow);
  247. transform: scale(1.2);
  248. }
  249. }
  250. .card-list {
  251. .one {
  252. margin: px2rpx(12) px2rpx(24);
  253. padding: px2rpx(12) 0;
  254. border-top: 1px dashed #beb6b6;
  255. color: #329644;
  256. font-family: Roboto;
  257. font-size: px2rpx(28);
  258. font-style: normal;
  259. font-weight: 700;
  260. line-height: px2rpx(36);
  261. align-items: flex-end;
  262. .label {
  263. color: #343434;
  264. font-family: Roboto;
  265. font-size: px2rpx(16);
  266. font-style: normal;
  267. font-weight: 600;
  268. line-height: px2rpx(24);
  269. width: px2rpx(100);
  270. }
  271. .strike {
  272. display: inline-block;
  273. padding-right: px2rpx(12);
  274. text-decoration-line: line-through;
  275. text-decoration-color: #333;
  276. text-decoration-thickness: px2rpx(1);
  277. text-decoration-skip-ink: none;
  278. font-size: px2rpx(20);
  279. }
  280. }
  281. }
  282. .fixed-btn {
  283. position: fixed;
  284. bottom: 0;
  285. left: 0;
  286. right: 0;
  287. padding: px2rpx(16);
  288. background: #fff;
  289. box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.1);
  290. z-index: 100;
  291. }
  292. .strike1 {
  293. color: var(--main-yellow);
  294. }
  295. </style>