123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278 |
- <!-- 支付组件 -->
- <template>
- <div v-if="payType && payQrCodeTxt" class="code pa-5 resume-box">
- <div class="resume-header">
- <div class="resume-title">扫码支付</div>
- </div>
- <div class="d-flex align-end mt-3">
- <div class="code-left">
- <QrCode :text="payQrCodeTxt" :disabled="!remainderTimer" :width="170" @refresh="refreshQRCode" />
- </div>
- <div class="code-right ml-5">
- <div class="price">
- <span class="font-size-13">¥</span>
- {{ FenYuanTransform(props.info?.payPrice || 0) }}
- </div>
- <div class="mt-3 d-flex align-center">
- <span class="color-666 font-weight-bold mr-5">支付方式</span>
- <!-- <v-chip-group v-model="payment" selected-class="text-primary" mandatory>
- <v-chip filter v-for="k in paymentList" :key="k.value" :value="k.value" class="mr-3" label>
- {{ k.label }}
- <svg-icon class="ml-1" :name="k.icon" :size="k.size"></svg-icon>
- </v-chip>
- </v-chip-group> -->
- <v-chip-group v-model="payType" selected-class="text-primary" column mandatory @update:modelValue="payTypeChange">
- <v-chip filter v-for="k in payTypeList" :key="k.code" :value="k.code" class="mr-3" label>
- {{ k.name }}
- <svg-icon v-if="k.icon" class="ml-1" :name="k.icon" :size="k.size"></svg-icon>
- </v-chip>
- </v-chip-group>
- </div>
- <div class="font-size-14 color-666 mt-3 cursor-pointer">
- 服务协议
- <span class="septal-line"></span>
- 充值协议
- </div>
- </div>
- </div>
- <div
- class="mt-5 ml-2"
- style="color: var(--v-error-base);"
- >
- 扫码支付时请勿离开
- <span v-if="remainderZhShow">{{ remainderZhShow }}</span>
- </div>
- </div>
- </template>
- <script setup>
- defineOptions({name: 'personalRecharge-initPay'})
- import QrCode from '@/components/QrCode'
- import { FenYuanTransform } from '@/utils/position'
- import { definePayTypeList, qrCodePay, walletPay } from '@/utils/payType'
- import { getEnableCodeList, payOrderSubmit, getOrderPayStatus } from '@/api/common'
- import { setWalletRecharge } from '@/api/recruit/personal/myWallet.js'
- import { onUnmounted, ref, nextTick, watch } from 'vue'
- const emit = defineEmits(['payTypeChange', 'paySuccess', 'stopInterval'])
- const props = defineProps({
- info: {
- type: Object,
- default: () => ({ id: ''})
- },
- appId: {
- type: Number,
- default: 11 // 10为一般情况下支付,11为充值支付
- },
- })
- // 1.支付方式
- // 2.发起充值(创建钱包充值记录)
- // 2.发起充值(创建钱包充值记录)
- // 3.如果是二维码类型支付(isQrCodePay=true)生成二维码(需要绑定支付订单的订单号)
- // 4.轮询用户是否支付成功
- // 更新账户余额信息
- import { useUserStore } from '@/store/user'; const store = useUserStore()
- const updateAccountInfo = async () => {
- await store.getUserAccountBalance()
- loading.value = false
- }
- import Snackbar from '@/plugins/snackbar'
- import { useRoute } from 'vue-router'; const route = useRoute()
- import { useRouter } from 'vue-router'; const router = useRouter()
- const payStatusTimer = ref(null) // 支付状态轮询
- const payStatus = async () => {
- // if (payStatusTimer.value) clearInterval(payStatusTimer.value); payStatusTimer.value = null
- // setTimeout(() => { // 测试代码
- // }, 2000)
- try {
- const data = await getOrderPayStatus({ id: (props.appId - 0) === 11 ? payOrder.value.payOrderId : payOrder.value.id })
- if ((data?.status - 0) === 10) {
- // 支付成功
- if (payStatusTimer.value) clearInterval(payStatusTimer.value); payStatusTimer.value = null
- setTimeout(() => {
- // 更新点数(充值、发布职位)
- updateAccountInfo()
- // 清除定时器
- clearTimer()
- // 支付成功
- emit('paySuccess')
- // getUnpaidOrderList() // 重新创建新的支付订单
- // 返回指定页面
- if (route.fullPath === props.returnUrl) router.go(0)
- else if (props.returnUrl) router.push(props.returnUrl)
- Snackbar.success('支付成功')
- }, 2000);
- }
- } catch (error) {
- console.log(error)
- }
- }
- const payQrCodeTxt = ref('')
- // 如果是点数支付的话走完payOrderSubmit之后即扣点数,如果是二维码支付的话只是生成二维码,这一步以后是轮询是否支付成功
- const paySubmit = async () => {
- if (!payType.value) return
- if (!payOrder.value?.payOrderId) return
- try {
- if (payOrder.value) {
- // 提交支付订单
- const params = {
- id: payOrder.value.payOrderId, // 支付单编号
- channelCode: payType.value, // 支付渠道
- }
- const res = await payOrderSubmit(params)
- payQrCodeTxt.value = res?.displayContent || '二维码生成失败,请刷新再试。' // 生成二维码内容
- initIntervalFun()
- }
- } catch (error) {
- console.log(error)
- }
- }
- // 2.发起充值
- const loading = ref(true)
- const payOrder = ref({})
- const getUnpaidOrderList = async () => {
- try {
- //* 充值
- if (props.info.payPrice === undefined && props.info.packageId === undefined) return
- const params = {
- payPrice: (props.info.payPrice-0),
- packageId: props.info.id,
- }
- const data = await setWalletRecharge(params)
- payOrder.value = data || {}
- if (isQrCodePay.value) paySubmit()
- } catch (error) {
- console.log(error)
- } finally {
- nextTick(() => {
- loading.value = false
- })
- }
- }
- // 1.支付方式
- const isWalletPay = ref(false)
- const isQrCodePay = ref(false)
- const tip = ref('')
- const payTypeChange = (value) => {
- payType.value = value
- tip.value = payTypeList.value.find(e => e.code === payType.value)?.tip || ''
- isQrCodePay.value = qrCodePay.includes(payType.value)
- isWalletPay.value = walletPay.includes(payType.value)
- paySubmit()
- }
- // 1.支付方式
- const payType = ref('')
- const payTypeList = ref([])
- const codeList = ref([])
- const getCodeList = async () => {
- try {
- const list = await getEnableCodeList({appId: props.appId})
- codeList.value = list || []
- } catch (error) {
- console.log(error)
- } finally {
- if (definePayTypeList?.length && codeList.value?.length) {
- codeList.value.forEach(code => {
- const item = definePayTypeList.find(p => p.code === code)
- if (item) {
- if (!payType.value) {
- tip.value = item.tip || ''
- // payTypeChange(code) // 默认值赋值
- // 默认值赋值(暂时只支持扫码)
- const bool = qrCodePay.includes(code)
- if (bool) payTypeChange(code)
- }
- payTypeList.value.push(item)
- }
- })
- }
- getUnpaidOrderList()
- }
- }
- watch(
- () => props.info.id,
- (newVal, oldVal) => {
- if (!newVal) return
- if (!oldVal && newVal) getCodeList() // 初始化时要从获取支付方式列表开始
- if (oldVal && newVal) getUnpaidOrderList() // 切换充值金额,从创建新充值订单开始
- },
- { immediate: true },
- { deep: true }
- )
- const refreshQRCode =() => { // 刷新二维码
- getUnpaidOrderList()
- }
- const countdownTime = 60000*5 // 倒计时五分钟
- let remainder = 0 // number
- const remainderZhShow = ref('') // 倒计时展示
- const remainderTimer = ref(null)
- // 初始化倒计时
- const initIntervalFun = () => {
- remainder = countdownTime // 初始倒计时时间
- if (remainderTimer.value) clearInterval(remainderTimer.value); remainderTimer.value = null // 每一次点击都清除上一个轮询
- // 倒计时计算
- remainderCalc()
- remainderTimer.value = setInterval(() => { remainderCalc() }, 1000)
- if (payStatusTimer.value) clearInterval(payStatusTimer.value); payStatusTimer.value = null
- payStatusTimer.value = setInterval(() => { payStatus() }, 2000) // 轮巡查询用户是否支付
- }
- const remainderCalc = () => {
- remainder -= 1000
- remainderZhShow.value = formatDuration(remainder)
- if (remainder <= 0) clearTimer()
- }
- const formatDuration = (remainder) => {
- // 将毫秒转换为秒
- var seconds = Math.floor(remainder / 1000)
- // 计算分钟和剩余的秒数
- var minutes = Math.floor(seconds / 60)
- var remainingSeconds = seconds % 60
- // 格式化分钟和秒数,确保秒数为两位数(如果小于10,则前面补0)
- minutes = minutes.toString().padStart(2, '0')
- remainingSeconds = remainingSeconds.toString().padStart(2, '0')
- // 返回格式化的字符串
- return `${minutes}分${remainingSeconds}秒`
- }
- onUnmounted(() => {
- clearTimer()
- })
- const clearTimer = () => {
- if (payStatusTimer.value) clearInterval(payStatusTimer.value); payStatusTimer.value = null
- if (remainderTimer.value) clearInterval(remainderTimer.value); remainderTimer.value = null
- remainderZhShow.value = ''
- emit('stopInterval')
- }
- </script>
- <style lang="scss" scoped>
- .code {
- border-radius: 6px;
- background-color: #f7f8fa;
- &-left {
- border: 1px solid #00897B;
- border-radius: 6px;
- padding: 5px;
- }
- &-right {
- .price {
- font-size: 30px;
- font-weight: 700;
- color: var(--v-error-base);
- }
- }
- }
- </style>
|