123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310 |
- <template>
- <v-slide-group v-model="model" center-active show-arrows>
- <v-slide-group-item v-for="(val, index) in list" :key="index" v-slot="{ isSelected }">
- <v-card :class="{'active': isSelected}" class="ma-4 list-item elevation-2 text-center" height="175" @click="handleClick(index, val)">
- <template v-if="val.id === 'custom'">
- <div class="d-flex flex-column algin-center justify-center" style="height: 100%" :style="{'color': isSelected ? '#fff' : '#333'}">
- <div>需要发布更多职位</div>
- <div>请联系门墩儿购买企业套餐</div>
- <div>点击查看联系方式</div>
- </div>
- </template>
- <template v-else>
- <h4 class="mt-5" :style="{'color': isSelected ? '#fff' : '#333'}">{{ val.name }}</h4>
- <div :style="{'color': isSelected ? '#fff' : '#00897B'}">
- <span>¥</span>
- <span style="font-size: 35px;">{{ val.price / 100 }}</span>
- <span> 元</span>
- </div>
- <div class="text-decoration-line-through" :style="{'color': isSelected ? '#fff' : '#666'}">原价:{{ val.originalPrice / 100 }}元</div>
- <div class="font-size-14 mt-3 py-2" :style="{'color': isSelected ? '#fff' : '#999'}">有效期:{{ val.day }}天</div>
- </template>
- </v-card>
- </v-slide-group-item>
- </v-slide-group>
- <div v-if="payType && payQrCodeTxt" id="codeBox" class="code pa-5 resume-box">
- <div class="resume-header">
- <div class="resume-title">扫码支付</div>
- </div>
- <div class="d-flex justify-center">
- <div id="codeItem" class="d-flex flex-column align-center my-2">
- <div class="d-flex align-center">
- <span class="color-666 font-weight-bold">支付方式:</span>
- <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="code-right">
- <div class="price">
- <span class="font-size-13">¥</span>
- {{ FenYuanTransform(select?.price || 0) }}元
- </div>
- </div>
- <div class="code-left">
- <QrCode :text="payQrCodeTxt" :disabled="!remainderTimer" :width="170" @refresh="refreshQRCode" />
- </div>
- <div class="mt-52" style="color: var(--v-error-base);">
- 扫码支付时请勿离开
- <span v-if="remainderZhShow">{{ remainderZhShow }}</span>
- </div>
- </div>
- </div>
- </div>
- <div v-if="showCustom" id="codeBox" class="code pa-5 resume-box">
- <div style="width: 100%;">
- <div class="text-center">请扫码添加下方企业微信联系我们:</div>
- <div class="my-3" style="width: 180px; height: 180px; margin: auto;">
- <v-img src="https://minio.menduner.com/dev/menduner/contact.png" width="180" height="180"></v-img>
- </div>
- <div class="text-center mt-2">潘青海先生(Peter Pan)</div>
- </div>
- </div>
- </template>
- <script setup>
- defineOptions({ name: 'membershipPackageDynamicPackage' })
- import { ref, onUnmounted, nextTick } from 'vue'
- import { getEnterprisePackageList } from '@/api/enterprise'
- import { FenYuanTransform } from '@/utils/position'
- import { getEnableCodeList, payOrderSubmit, getOrderPayStatus, getUnpaidOrder } from '@/api/common'
- import { definePayTypeList, qrCodePay } from '@/utils/payType'
- import { useUserStore } from '@/store/user'; const store = useUserStore()
- import Snackbar from '@/plugins/snackbar'
- import { createTradeOrder } from '@/api/position'
- import { useRoute } from 'vue-router'; const route = useRoute()
- import { useRouter } from 'vue-router'; const router = useRouter()
- import Confirm from '@/plugins/confirm'
- import { useI18n } from '@/hooks/web/useI18n'; const { t } = useI18n()
- const current = ref()
- const select = ref({})
- const model = ref(0)
- // 套餐列表
- const list = ref([])
- const getPackageList = async () => {
- const data = await getEnterprisePackageList()
- list.value = data
- list.value.push({ id:'custom' })
- select.value = data[0]
- }
- const showCustom = ref(false)
- const handleClick = (index, val) => {
- model.value = index
- if (val.id == 'custom') {
- payQrCodeTxt.value = ''
- showCustom.value = true
- clearTimer()
- return
- }
- showCustom.value = false
- payQrCodeTxt.value = ''
- current.value = index
- select.value = val
- getUnpaidOrderList()
- }
- const payQrCodeTxt = ref('')
- // 2.发起充值
- const loading = ref(true)
- const payOrder = ref({})
- let maxCount = 0
- const getUnpaidOrderList = async () => {
- const data = await getUnpaidOrder({ spuId: select.value.id, type: 4 })
- if (!data) {
- await createTradeOrder({ price: (select.value.price-0), spuId: select.value.id, spuName: select.value.name, type: 4 })
- if (maxCount > 3) return // 避免死循环
- maxCount++
- setTimeout(() => {
- getUnpaidOrderList()
- }, 1000)
- }
- payOrder.value = data?.payOrder || null
- paySubmit()
- }
- const payTypeChange = (val) => {
- payType.value = val
- getUnpaidOrderList()
- }
- const timer = ref(null)
- onUnmounted(() => {
- if (timer.value) clearInterval(timer.value); timer.value = null
- })
- // 更新职位可发布数量
- const updateAccountInfo = async (init = false) => {
- await store.getEnterpriseInfo(true)
- if (init) return
- loading.value = false
- }
- const fromName = ref(route.query?.fromName || '')
- const callBackUrl = () => {
- const urls = {
- position: '/recruit/enterprise/position',
- positionPay: '/recruit/enterprise/position?tab=0',
- }
- const texts = {
- position: '职位管理页面',
- positionPay: '职位管理待发布页面'
- }
- const url = fromName.value ? urls[fromName.value] : -1
- const text = fromName.value ? texts[fromName.value] : '购买前页面'
- //
- Confirm(t('common.confirmTitle'), `支付成功!是否返回${text}?`).then(() => {
- router.push(url)
- })
- }
- const payStatus = async () => {
- try {
- const data = await getOrderPayStatus({ id: payOrder.value.id })
- if ((data?.status - 0) === 10) {
- // 支付成功
- if (timer.value) clearInterval(timer.value); timer.value = null
- setTimeout(() => {
- // 更新点数(充值、发布职位)
- updateAccountInfo()
- // 清除定时器
- clearTimer()
- // 支付成功
- if (fromName.value) callBackUrl()
- else Snackbar.success('支付成功')
- }, 2000);
- }
- } catch (error) {
- console.log(error)
- }
- }
- const paySubmit = async () => {
- if (!payType.value) return
- try {
- // 提交支付订单
- const params = {
- channelCode: payType.value, // 支付渠道
- id: payOrder.value.id
- }
- const res = await payOrderSubmit(params)
- payQrCodeTxt.value = res?.displayContent || '' // 生成二维码内容
- initIntervalFun()
- if (timer.value) clearInterval(timer.value); timer.value = null
- timer.value = setInterval(() => { payStatus() }, 1000) // 轮巡查询用户是否支付
- } catch (error) {
- console.log(error)
- }
- }
- // 1.支付方式
- const payType = ref('')
- const payTypeList = ref([])
- const codeList = ref([])
- const getCodeList = async () => {
- try {
- const list = await getEnableCodeList({ appId: 11 })
- 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) {
- // 默认值赋值(暂时只支持扫码)
- const bool = qrCodePay.includes(code)
- // if (bool) payType.value = code
- if (bool) payTypeChange(code)
- }
- payTypeList.value.push(item)
- }
- })
- }
- }
- }
- nextTick(async () => {
- await getPackageList()
- await getCodeList()
- })
- const refreshQRCode =() => { // 刷新二维码
- getUnpaidOrderList()
- }
- const remainderTimer = ref(null)
- const countdownTime = 60000 * 3 // 倒计时三分钟
- let remainder = 0 // number
- // 初始化倒计时
- const initIntervalFun = () => {
- remainder = countdownTime // 初始倒计时时间
- if (remainderTimer.value) clearInterval(remainderTimer.value); remainderTimer.value = null // 每一次点击都清除上一个轮询
- // 倒计时计算
- remainderCalc()
- remainderTimer.value = setInterval(() => { remainderCalc() }, 1000)
- if (timer.value) clearInterval(timer.value); timer.value = null
- timer.value = setInterval(() => { payStatus() }, 2000) // 轮巡查询用户是否支付
- }
- 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}秒`
- }
- const remainderZhShow = ref('')
- const clearTimer = () => {
- if (timer.value) clearInterval(timer.value); timer.value = null
- if (remainderTimer.value) clearInterval(remainderTimer.value); remainderTimer.value = null
- remainderZhShow.value = ''
- }
- const remainderCalc = () => {
- remainder -= 1000
- remainderZhShow.value = formatDuration(remainder)
- if (remainder <= 0) clearTimer()
- }
- </script>
- <style scoped lang="scss">
- .list-item {
- width: 250px;
- background-color: #f7f8fa;
- }
- .active {
- background-color: #00897B;
- }
- .code {
- background-color: #f7f8fa;
- border-radius: 6px;
- margin: 0 auto;
- &-left {
- border: 1px solid #00897B;
- border-radius: 6px;
- padding: 5px;
- }
- &-right {
- .price {
- font-size: 30px;
- font-weight: 700;
- color: var(--v-error-base);
- }
- }
- }
- </style>
|