index.vue 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. <script setup lang="ts">
  2. import type { wxpay } from '@/api/globals'
  3. import router from '@/router'
  4. definePage({ name: 'smqjh-threePay', islogin: false, style: { navigationBarTitleText: '支付', navigationStyle: 'custom' } })
  5. const { token } = storeToRefs(useUserStore())
  6. const { tenantCode } = storeToRefs(useSysStore())
  7. const orderNumber = ref()
  8. const model = ref('mixture')
  9. onLoad((options: any) => {
  10. orderNumber.value = options.orderNumber
  11. tenantCode.value = options.tenantCode
  12. if (options.model) {
  13. model.value = options.model
  14. }
  15. token.value = ''
  16. handleLogin(options.phone)
  17. console.log(options, '============options=======')
  18. })
  19. const priceInfo = ref<wxpay>()
  20. function handleLogin(phoneCode: string) {
  21. uni.showLoading({ mask: true })
  22. uni.login({
  23. provider: 'weixin',
  24. success: async (res) => {
  25. const data = await Apis.sys.auth({
  26. params: {
  27. grant_type: 'wechat',
  28. code: res.code,
  29. phoneCode,
  30. },
  31. })
  32. console.log(data, '============data=======')
  33. token.value = `Bearer ${data.data.access_token}`
  34. useUserStore().getUserInfo()
  35. handlePay()
  36. },
  37. complete: () => {
  38. uni.hideLoading()
  39. },
  40. })
  41. }
  42. async function handlePay() {
  43. console.log(model.value, '========model.value=============')
  44. if (model.value === 'wx') {
  45. const payRes = await Apis.charge.wxJsApiPay({
  46. data: {
  47. orderNumber: orderNumber.value,
  48. },
  49. })
  50. priceInfo.value = payRes.data
  51. await useUserStore().getWxCommonPayment(payRes.data)
  52. }
  53. else {
  54. const res = await useUserStore().handleCommonPayMent(orderNumber.value)
  55. priceInfo.value = res
  56. console.log(priceInfo.value, '=============priceInfo.value============')
  57. }
  58. }
  59. async function handleGoPay() {
  60. if (priceInfo.value?.payType !== 1) {
  61. try {
  62. await useUserStore().getWxCommonPayment(priceInfo.value as wxpay)
  63. router.push({ name: 'common-threePayRes', params: { price: String(priceInfo.value?.price), type: '1' } })
  64. }
  65. catch (error: any) {
  66. console.log(error, '=========================')
  67. router.push({ name: 'common-threePayRes', params: { price: String(priceInfo.value?.price), type: '0', error: error.errMsg } })
  68. // console.log(111)
  69. }
  70. }
  71. }
  72. // 倒计时:15分钟 = 900秒
  73. const COUNTDOWN_SECONDS = 15 * 60
  74. const countdown = ref(COUNTDOWN_SECONDS)
  75. const countdownTimer = ref<ReturnType<typeof setInterval> | null>(null)
  76. // 模块级变量:记录倒计时结束的时间戳,离页后回来可继续
  77. // 页面卸载(onUnload)时重置,保证下次进入是全新的15分钟
  78. let endTimestamp: number | null = null
  79. // 格式化为 MM:SS
  80. const countdownText = computed(() => {
  81. const m = Math.floor(countdown.value / 60).toString().padStart(2, '0')
  82. const s = (countdown.value % 60).toString().padStart(2, '0')
  83. return `${m}:${s}`
  84. })
  85. function updateCountdown() {
  86. if (!endTimestamp)
  87. return
  88. const remaining = Math.max(0, Math.ceil((endTimestamp - Date.now()) / 1000))
  89. countdown.value = remaining
  90. if (remaining <= 0) {
  91. stopCountdown()
  92. // TODO: 倒计时结束后的跳转逻辑
  93. router.push({ name: 'common-threePayRes', params: { price: String(priceInfo.value?.price), type: '0' } })
  94. }
  95. }
  96. function startCountdown() {
  97. // 首次进入:初始化结束时间戳
  98. if (!endTimestamp) {
  99. endTimestamp = Date.now() + COUNTDOWN_SECONDS * 1000
  100. }
  101. // 立即同步一次剩余时间(防止回来时短暂显示旧值)
  102. updateCountdown()
  103. stopCountdown()
  104. countdownTimer.value = setInterval(updateCountdown, 1000)
  105. }
  106. function stopCountdown() {
  107. if (countdownTimer.value) {
  108. clearInterval(countdownTimer.value)
  109. countdownTimer.value = null
  110. }
  111. }
  112. // 页面显示时启动/恢复倒计时(含首次进入和从其他页面返回)
  113. onShow(() => {
  114. startCountdown()
  115. })
  116. // 离开页面时暂停定时器,但保留 endTimestamp
  117. onHide(() => {
  118. stopCountdown()
  119. })
  120. // 页面卸载时清理,下次进入重新开始
  121. onUnload(() => {
  122. stopCountdown()
  123. endTimestamp = null
  124. })
  125. </script>
  126. <template>
  127. <view>
  128. <wd-navbar title="支付" :bordered="false" :z-index="99" safe-area-inset-top placeholder fixed />
  129. <view v-if="priceInfo" class="px20rpx pt20rpx">
  130. <view class="text-center text-48rpx text-#FF4A39">
  131. ¥{{ (priceInfo?.price / 100).toFixed(2) }}
  132. </view>
  133. <view class="mb20rpx mt24rpx text-center text-26rpx text-[#999]">
  134. 支付剩余时间:<text class="text-[#FF4A39] font-semibold">
  135. {{ countdownText }}
  136. </text>
  137. </view>
  138. <wd-button block @click="handleGoPay">
  139. 确认支付
  140. </wd-button>
  141. </view>
  142. </view>
  143. </template>
  144. <style lang="scss" scoped></style>