initPay.vue 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. <!-- 支付组件 -->
  2. <template>
  3. <div v-if="payType && payQrCodeTxt" class="code pa-5 resume-box">
  4. <div class="resume-header">
  5. <div class="resume-title">扫码支付</div>
  6. </div>
  7. <div class="d-flex align-end mt-3">
  8. <div class="code-left">
  9. <QrCode :text="payQrCodeTxt" :width="170" />
  10. </div>
  11. <div class="code-right ml-5">
  12. <div class="price">
  13. <span class="font-size-13">¥</span>
  14. {{ payCalculation(props.info?.payPrice || 0, 'realPay') }}
  15. </div>
  16. <div class="mt-3 d-flex align-center">
  17. <span class="color-666 font-weight-bold mr-5">支付方式</span>
  18. <!-- <v-chip-group v-model="payment" selected-class="text-primary" mandatory>
  19. <v-chip filter v-for="k in paymentList" :key="k.value" :value="k.value" class="mr-3" label>
  20. {{ k.label }}
  21. <svg-icon class="ml-1" :name="k.icon" :size="k.size"></svg-icon>
  22. </v-chip>
  23. </v-chip-group> -->
  24. <v-chip-group v-model="payType" selected-class="text-primary" column mandatory @update:modelValue="payTypeChange">
  25. <v-chip filter v-for="k in payTypeList" :key="k.code" :value="k.code" class="mr-3" label>
  26. {{ k.name }}
  27. <svg-icon v-if="k.icon" class="ml-1" :name="k.icon" :size="k.size"></svg-icon>
  28. </v-chip>
  29. </v-chip-group>
  30. </div>
  31. <div class="font-size-14 color-666 mt-3 cursor-pointer">
  32. 服务协议
  33. <span class="septal-line"></span>
  34. 充值协议
  35. </div>
  36. </div>
  37. </div>
  38. <div class="mt-5 ml-2" style="color: var(--v-error-base);">扫码支付时请勿离开</div>
  39. </div>
  40. </template>
  41. <script setup>
  42. defineOptions({name: 'personalRecharge-initPay'})
  43. import QrCode from '@/components/QrCode'
  44. import { payCalculation } from '@/utils/position'
  45. import { definePayTypeList, qrCodePay, walletPay } from '@/utils/payType'
  46. import { getEnableCodeList, payOrderSubmit, getOrderPayStatus } from '@/api/common'
  47. import { setWalletRecharge } from '@/api/recruit/personal/myWallet.js'
  48. import { onUnmounted, ref, nextTick, watch } from 'vue'
  49. const emit = defineEmits(['payTypeChange', 'paySuccess'])
  50. const props = defineProps({
  51. info: {
  52. type: Object,
  53. default: () => ({ id: ''})
  54. },
  55. appId: {
  56. type: Number,
  57. default: 11 // 10为一般情况下支付,11为充值支付
  58. },
  59. })
  60. // 1.支付方式
  61. // 2.发起充值(创建钱包充值记录)
  62. // 2.发起充值(创建钱包充值记录)
  63. // 3.如果是二维码类型支付(isQrCodePay=true)生成二维码(需要绑定支付订单的订单号)
  64. // 4.轮询用户是否支付成功
  65. // 更新账户余额信息
  66. import { useUserStore } from '@/store/user'; const store = useUserStore()
  67. const updateAccountInfo = async () => {
  68. await store.getUserAccountBalance()
  69. loading.value = false
  70. }
  71. import Snackbar from '@/plugins/snackbar'
  72. import { useRoute } from 'vue-router'; const route = useRoute()
  73. import { useRouter } from 'vue-router'; const router = useRouter()
  74. const payStatus = async () => {
  75. // if (timer.value) clearInterval(timer.value); timer.value = null
  76. // setTimeout(() => { // 测试代码
  77. // }, 2000)
  78. try {
  79. const data = await getOrderPayStatus({ id: (props.appId - 0) === 11 ? payOrder.value.payOrderId : payOrder.value.id })
  80. if ((data?.status - 0) === 10) {
  81. // 支付成功
  82. if (timer.value) clearInterval(timer.value); timer.value = null
  83. setTimeout(() => {
  84. // 更新点数(充值、发布职位)
  85. updateAccountInfo()
  86. // 支付成功
  87. emit('paySuccess')
  88. // 返回指定页面
  89. if (route.fullPath === props.returnUrl) router.go(0)
  90. else if (props.returnUrl) router.push(props.returnUrl)
  91. Snackbar.success('支付成功')
  92. }, 2000);
  93. }
  94. } catch (error) {
  95. console.log(error)
  96. }
  97. }
  98. const timer = ref(null)
  99. const payQrCodeTxt = ref('')
  100. onUnmounted(() => {
  101. if (timer.value) clearInterval(timer.value); timer.value = null
  102. })
  103. // 如果是点数支付的话走完payOrderSubmit之后即扣点数,如果是二维码支付的话只是生成二维码,这一步以后是轮询是否支付成功
  104. const paySubmit = async () => {
  105. if (!payType.value) return
  106. if (!payOrder.value?.payOrderId) return
  107. try {
  108. if (payOrder.value) {
  109. // 提交支付订单
  110. const params = {
  111. id: payOrder.value.payOrderId, // 支付单编号
  112. channelCode: payType.value, // 支付渠道
  113. }
  114. const res = await payOrderSubmit(params)
  115. payQrCodeTxt.value = res?.displayContent || '二维码生成失败,请刷新再试。' // 生成二维码内容
  116. if (timer.value) clearInterval(timer.value); timer.value = null
  117. timer.value = setInterval(() => { payStatus() }, 1000) // 轮巡查询用户是否支付
  118. }
  119. } catch (error) {
  120. console.log(error)
  121. }
  122. }
  123. // 2.发起充值
  124. const loading = ref(true)
  125. const payOrder = ref({})
  126. const getUnpaidOrderList = async () => {
  127. try {
  128. //* 充值
  129. if (props.info.payPrice === undefined && props.info.packageId === undefined) return
  130. const params = {
  131. payPrice: (props.info.payPrice-0),
  132. packageId: props.info.id,
  133. }
  134. const data = await setWalletRecharge(params)
  135. payOrder.value = data || {}
  136. if (isQrCodePay.value) paySubmit()
  137. } catch (error) {
  138. console.log(error)
  139. } finally {
  140. nextTick(() => {
  141. loading.value = false
  142. })
  143. }
  144. }
  145. // 1.支付方式
  146. const isWalletPay = ref(false)
  147. const isQrCodePay = ref(false)
  148. const tip = ref('')
  149. const payTypeChange = (value) => {
  150. payType.value = value
  151. tip.value = payTypeList.value.find(e => e.code === payType.value)?.tip || ''
  152. isQrCodePay.value = qrCodePay.includes(payType.value)
  153. isWalletPay.value = walletPay.includes(payType.value)
  154. paySubmit()
  155. }
  156. // 1.支付方式
  157. const payType = ref('')
  158. const payTypeList = ref([])
  159. const codeList = ref([])
  160. const getCodeList = async () => {
  161. try {
  162. const list = await getEnableCodeList({appId: props.appId})
  163. codeList.value = list || []
  164. } catch (error) {
  165. console.log(error)
  166. } finally {
  167. if (definePayTypeList?.length && codeList.value?.length) {
  168. codeList.value.forEach(code => {
  169. const item = definePayTypeList.find(p => p.code === code)
  170. if (item) {
  171. if (!payType.value) {
  172. tip.value = item.tip || ''
  173. // payTypeChange(code) // 默认值赋值
  174. // 默认值赋值(暂时只支持扫码)
  175. const bool = qrCodePay.includes(code)
  176. if (bool) payTypeChange(code)
  177. }
  178. payTypeList.value.push(item)
  179. }
  180. })
  181. }
  182. getUnpaidOrderList()
  183. }
  184. }
  185. // getCodeList()
  186. watch(
  187. () => props.info.id,
  188. (newVal, oldVal) => {
  189. if (!newVal) return
  190. if (!oldVal && newVal) getCodeList()
  191. if (oldVal && newVal) getUnpaidOrderList()
  192. },
  193. { immediate: true },
  194. { deep: true }
  195. )
  196. </script>
  197. <style lang="scss" scoped>
  198. .code {
  199. // max-width: 1100px;
  200. // max-width: 600px;
  201. border-radius: 6px;
  202. // margin: 0 auto;
  203. background-color: #f7f8fa;
  204. &-left {
  205. border: 1px solid #00897B;
  206. border-radius: 6px;
  207. padding: 5px;
  208. }
  209. &-right {
  210. .price {
  211. font-size: 30px;
  212. font-weight: 700;
  213. color: var(--v-error-base);
  214. }
  215. }
  216. }
  217. </style>