index.vue 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. <!-- 支付方式 -->
  2. <template>
  3. <v-card elevation="0" :loading="loading" :disabled="loading">
  4. <!-- 加载样式 -->
  5. <template v-slot:loader="{ isActive }">
  6. <v-progress-linear
  7. :active="isActive"
  8. color="var(--v-primary-base)"
  9. height="1"
  10. indeterminate
  11. ></v-progress-linear>
  12. </template>
  13. <!-- 赏金所需 -->
  14. <div class="pt-3 pb-5" style="color: var(--v-error-base); font-weight: bold; text-align: center;">
  15. <span class="font-size-13">¥</span>
  16. <span class="font-size-30">{{ cost }}</span>
  17. </div>
  18. <radioGroupUI
  19. :modelValue="payType"
  20. :item="payTypeItem"
  21. @change="val => payTypeChange(val)"
  22. ></radioGroupUI>
  23. <div class="pa-5">
  24. <!-- 支付 -->
  25. <div v-if="isWalletPay">
  26. <div>
  27. <span >{{ $t('enterprise.account.accountBalances') }}:</span>
  28. <span style="color: var(--v-primary-base);">{{ balance }}</span>
  29. </div>
  30. <div class="my-3" v-if="balanceNotEnough">
  31. <!-- <v-icon color="warning">mdi-information</v-icon> -->
  32. <span class="color-warning">{{ props.params?.txt || '当前余额不足,请选择其他支付方式' }}</span>
  33. </div>
  34. </div>
  35. <div v-if="isQrCodePay" style="text-align: center;">
  36. <QrCode :text="payQrCodeTet" :width="170" style="margin: 0 auto;" />
  37. <div v-if="isQrCodePay && payQrCodeTet" style="color: var(--v-error-base);">扫码支付时请勿离开</div>
  38. </div>
  39. <div class="mt-10" style="text-align: center;">
  40. <!-- v-if="(isQrCodePay && payQrCodeTet) || isWalletPay" -->
  41. <v-btn
  42. v-if="isWalletPay"
  43. class="buttons" color="primary"
  44. :loading="payLoading"
  45. @click="paySubmit"
  46. >
  47. <!-- {{ isWalletPay ? '确认' : '支付完成' }} -->
  48. 确认
  49. </v-btn>
  50. </div>
  51. </div>
  52. </v-card>
  53. </template>
  54. <script setup>
  55. defineOptions({ name: 'pay-index'})
  56. import { computed, onUnmounted, ref } from 'vue'
  57. import radioGroupUI from '@/components/FormUI/radioGroup'
  58. import QrCode from '@/components/QrCode'
  59. import { definePayTypeList, qrCodePay, walletPay } from './until/payType'
  60. import { getEnableCodeList, getUnpaidOrder, payOrderSubmit, getOrderPayStatus } from '@/api/common'
  61. import { createTradeOrder } from '@/api/position'
  62. import { useSharedState } from '@/store/sharedState'
  63. const emit = defineEmits(['payTypeChange', ])
  64. const props = defineProps({
  65. params: {
  66. type: Object,
  67. default: () => {}
  68. },
  69. cost: {
  70. type: [String, Number],
  71. default: 0
  72. },
  73. spuId: { // 原始数据id
  74. type: String,
  75. default: ''
  76. },
  77. spuName: {
  78. type: String,
  79. default: ''
  80. },
  81. type: {
  82. type: Number,
  83. default: 2 // 订单类型 0平台订单| 1发布职位订单| 2发布众聘职位订单,示例值(1)
  84. },
  85. })
  86. const loading = ref(true)
  87. // 支付方式
  88. const payType = ref('')
  89. const payTypeList = ref([])
  90. const sharedState = useSharedState()
  91. const codeList = ref(sharedState.payCodeList || [])
  92. const getCodeList = async () => {
  93. try {
  94. if (!codeList.value?.length) {
  95. const list = await getEnableCodeList({appId: 10})
  96. codeList.value = list || []
  97. sharedState.setPayCodeList(codeList.value)
  98. } else {
  99. codeList.value = sharedState.payCodeList
  100. }
  101. } catch (error) {
  102. console.log(error)
  103. } finally {
  104. if (definePayTypeList?.length && codeList.value?.length) {
  105. codeList.value.forEach(code => {
  106. const item = definePayTypeList.find(p => p.code === code)
  107. if (item) {
  108. if (!payType.value) {
  109. // payType.value = code
  110. payTypeChange(code) // 默认值赋值
  111. }
  112. payTypeList.value.push(item)
  113. }
  114. })
  115. }
  116. }
  117. }
  118. getCodeList()
  119. const payOrder = ref({})
  120. let maxCount = 0
  121. // 获取待支付的订单
  122. const getUnpaidOrderList = async () => {
  123. try {
  124. const data = await getUnpaidOrder({ spuId: props.spuId, type: props.type })
  125. // order:业务订单; payOrder:支付订单
  126. console.log('获取待支付的订单', data)
  127. if (!data) {
  128. // 订单超时,重新提交订单
  129. await createTradeOrder({
  130. spuId: props.spuId,
  131. spuName: props.spuName,
  132. price: props.cost,
  133. type: props.type, // 发布众聘职位订单
  134. })
  135. if (maxCount > 3) return // 避免死循环
  136. maxCount++
  137. setTimeout(() => {
  138. getUnpaidOrderList()
  139. }, 1000)
  140. }
  141. //
  142. if (data?.payOrder) {
  143. payOrder.value = data.payOrder
  144. loading.value = false
  145. }
  146. } catch (error) {
  147. console.log(error)
  148. }
  149. }
  150. getUnpaidOrderList() // getUnpaidOrder
  151. const payLoading = ref(false)
  152. const payQrCodeTet = ref('')
  153. const payTypeItem = {
  154. label: '',
  155. width: 1,
  156. hideDetails: true,
  157. itemText: 'name',
  158. itemValue: 'code',
  159. items: payTypeList.value
  160. }
  161. const balance = JSON.parse(localStorage.getItem('enterpriseUserAccount'))?.balance || 0
  162. const balanceNotEnough = computed(() => {
  163. return (Number(props.cost) > Number(balance))
  164. })
  165. const isWalletPay = ref(true)
  166. const isQrCodePay = ref(false)
  167. const payTypeChange = (val) => {
  168. payType.value = val
  169. isQrCodePay.value = qrCodePay.includes(payType.value)
  170. isWalletPay.value = walletPay.includes(payType.value)
  171. if (isQrCodePay.value) initPayQrCode() // 生成二维码内容
  172. emit('payTypeChange', val, balanceNotEnough)
  173. }
  174. const paySubmit = () => {
  175. emit('paySubmit', payType.value)
  176. }
  177. // 生成二维码内容
  178. const timer = ref(null)
  179. onUnmounted(() => {
  180. if (timer.value) clearInterval(timer.value); timer.value = null
  181. })
  182. const initPayQrCode = async () => {
  183. if (timer.value) clearInterval(timer.value); timer.value = null
  184. try {
  185. if (payOrder.value) {
  186. // 提交支付订单
  187. const params = {
  188. id: payOrder.value.id, // 支付单编号
  189. channelCode: payType.value, // 支付渠道
  190. displayMode: payOrder.value.notifyUrl, // 展示模式 notifyUrl
  191. returnUrl: '',
  192. }
  193. const res = await payOrderSubmit(params)
  194. payQrCodeTet.value = res?.displayContent || '' // 支付二维码
  195. timer.value = setInterval(() => { payStatus() }, 1000) // 轮巡查询用户是否支付
  196. }
  197. } catch (error) {
  198. console.log(error)
  199. }
  200. }
  201. import Snackbar from '@/plugins/snackbar'
  202. import { useRouter } from 'vue-router'; const router = useRouter()
  203. const payStatus = async () => {
  204. try {
  205. const data = await getOrderPayStatus({ id: payOrder.value.id })
  206. if ((data?.status - 0) === 1) {
  207. // 支付成功
  208. if (timer.value) clearInterval(timer.value); timer.value = null
  209. const query = { hire: true }
  210. router.push({ path: '/recruit/enterprise/position', query }) // 返回到众聘页面
  211. setTimeout(() => {
  212. Snackbar.success('付款成功')
  213. }, 1000);
  214. }
  215. } catch (error) {
  216. console.log(error)
  217. }
  218. }
  219. </script>
  220. <style lang="scss" scoped>
  221. .font-size-30 { font-size: 30px; }
  222. </style>