index.vue 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. <script setup lang="ts">
  2. import type { AppMemberCouponVO } from '@/api/globals'
  3. import router from '@/router'
  4. definePage({
  5. name: 'voucher',
  6. layout: 'tabbar',
  7. islogin: true,
  8. style: {
  9. navigationBarTitleText: '抵扣券',
  10. navigationStyle: 'custom',
  11. },
  12. })
  13. const StaticUrl = import.meta.env.VITE_STATIC_BASE_URL
  14. // Tab 列表
  15. const tabList = ref([
  16. { label: '可用', value: 2 },
  17. { label: '已使用', value: 1 },
  18. { label: '已过期', value: 5 },
  19. ])
  20. const currentTab = ref(2)
  21. // 状态映射
  22. const statusMap = new Map([
  23. [2, '可用'],
  24. [1, '已使用'],
  25. [5, '已过期'],
  26. ])
  27. // 分页请求
  28. const { data, isLastPage, page, reload } = usePagination(
  29. (pageNum, pageSize) => Apis.app.get_smqjh_system_app_api_membercoupon_page({
  30. params: { pageNum, pageSize, useStatus: currentTab.value },
  31. }),
  32. {
  33. initialPage: 1,
  34. initialPageSize: 10,
  35. immediate: false,
  36. data: res => res.data?.list,
  37. append: true,
  38. },
  39. )
  40. // 切换 Tab
  41. function handleTabChange(value: number) {
  42. currentTab.value = value
  43. page.value = 1
  44. reload()
  45. }
  46. function handleUse(_item: AppMemberCouponVO) {
  47. router.pushTab({ name: 'home' })
  48. useTabbar().setTabbarItemActive('home')
  49. }
  50. // 取消订单(占位)
  51. async function handleCancelOrder(_item: AppMemberCouponVO) {
  52. // useGlobalToast().show('功能开发中')
  53. await useUserStore().handleCommonCancelOrder(_item.lockOrderId as string)
  54. reload()
  55. }
  56. // 付款(占位)
  57. function handlePay(_item: AppMemberCouponVO) {
  58. // useGlobalToast().show('功能开发中')
  59. useUserStore().handleCommonGoXiaoJuPay(_item.lockOrderId as string)
  60. }
  61. // 计算倒计时剩余毫秒数
  62. function getCountdownTime(orderCreateTime?: string): number {
  63. if (!orderCreateTime)
  64. return 0
  65. const createTime = new Date(orderCreateTime).getTime()
  66. const expireTime = createTime + 15 * 60 * 1000 // 假设15分钟支付有效期
  67. const remaining = expireTime - Date.now()
  68. return remaining > 0 ? remaining : 0
  69. }
  70. onShow(() => {
  71. page.value = 1
  72. reload()
  73. })
  74. onReachBottom(() => {
  75. if (!isLastPage.value) {
  76. page.value++
  77. }
  78. })
  79. </script>
  80. <template>
  81. <view class="min-h-100vh bg-#f5f5f5">
  82. <!-- Tab 切换 -->
  83. <view class="sticky top-0 z-10 flex items-center justify-between bg-white px24rpx">
  84. <view
  85. v-for="item in tabList"
  86. :key="item.value"
  87. class="py24rpx text-28rpx"
  88. :class="[currentTab === item.value ? 'text-[var(--them-color)] font-semibold border-b-4rpx border-[var(--them-color)]' : 'text-#666']"
  89. @click="handleTabChange(item.value)"
  90. >
  91. {{ item.label }}
  92. </view>
  93. </view>
  94. <!-- 券列表 -->
  95. <view class="px24rpx pt20rpx">
  96. <view
  97. v-for="item in data"
  98. :key="item.id"
  99. class="mb20rpx rounded-16rpx bg-white px24rpx py28rpx"
  100. >
  101. <view @click="router.push({ name: 'voucherDetail', params: { id: item.id as string } })">
  102. <!-- 券信息头部 -->
  103. <view class="flex items-center justify-between">
  104. <view class="flex items-center">
  105. <image
  106. :src="`${StaticUrl}/smqjh-reful-juan.png`"
  107. class="mr12rpx h32rpx w32rpx"
  108. />
  109. <view class="text-30rpx font-semibold">
  110. 抵扣{{ item.discountMoney }}元(满{{ item.amountMoney }}元可用)
  111. </view>
  112. </view>
  113. <!-- 待支付倒计时 -->
  114. <view v-if="item.lockStatus === 1 && currentTab === 2" class="flex items-center text-24rpx text-#1890ff">
  115. 待支付(<wd-count-down :time="getCountdownTime(item.orderCreateTime)" format="还剩mm:ss" />)
  116. </view>
  117. </view>
  118. <!-- 券详情 -->
  119. <view class="mt16rpx text-26rpx text-#999">
  120. 适用:全部合作油站
  121. </view>
  122. <view class="mt12rpx text-26rpx text-#999">
  123. 有效期至:{{ item.expirationTime }}
  124. </view>
  125. <view class="mt12rpx text-26rpx text-#999">
  126. 可抵扣:<text class="text-#ff4d3a">
  127. ¥{{ item.discountMoney }}
  128. </text>
  129. </view>
  130. <view class="mt12rpx text-26rpx text-#999">
  131. 状态:{{ statusMap.get(item.useStatus as number) || '' }}
  132. </view>
  133. </view>
  134. <!-- 操作按钮区域 -->
  135. <view v-if="currentTab === 2" class="mt20rpx">
  136. <!-- 未被锁定 - 显示去使用 -->
  137. <view v-if="item.lockStatus !== 1" class="flex justify-end">
  138. <wd-button size="small" plain custom-class="use-btn" @click="handleUse(item)">
  139. 去使用
  140. </wd-button>
  141. </view>
  142. <!-- 被锁定 - 显示订单信息和操作 -->
  143. <view v-else>
  144. <view class="flex items-center text-26rpx text-#1890ff">
  145. <wd-icon name="info-circle" size="28rpx" color="#1890ff" class="mr8rpx" />
  146. 当前订单未支付,券被占用
  147. </view>
  148. <view class="mt16rpx flex items-center justify-between">
  149. <view class="text-26rpx text-#999">
  150. 订单号:{{ item.lockOrderId }}
  151. </view>
  152. <view class="flex items-center gap-16rpx">
  153. <wd-button size="small" plain custom-class="cancel-btn" @click="handleCancelOrder(item)">
  154. 取消订单
  155. </wd-button>
  156. <wd-button size="small" plain custom-class="pay-btn" @click="handlePay(item)">
  157. 付款
  158. </wd-button>
  159. </view>
  160. </view>
  161. </view>
  162. </view>
  163. </view>
  164. <!-- 空状态 -->
  165. <view v-if="data && data.length === 0" class="flex flex-col items-center pt100rpx">
  166. <StatusTip tip="暂无抵扣券" />
  167. </view>
  168. </view>
  169. </view>
  170. </template>
  171. <style lang="scss" scoped>
  172. :deep(.use-btn) {
  173. border-color: #333 !important;
  174. color: #333 !important;
  175. border-radius: 32rpx !important;
  176. }
  177. :deep(.cancel-btn) {
  178. border-color: #999 !important;
  179. color: #999 !important;
  180. border-radius: 32rpx !important;
  181. }
  182. :deep(.pay-btn) {
  183. border-color: #333 !important;
  184. color: #333 !important;
  185. border-radius: 32rpx !important;
  186. }
  187. :deep(.wd-count-down){
  188. color: #1890ff !important;
  189. }
  190. </style>