254 lines
6.7 KiB
Vue
254 lines
6.7 KiB
Vue
<template>
|
||
<el-dialog v-model="visible" width="800px" class="vip-dialog" align-center @close="handleClose">
|
||
<template #header>
|
||
<div class="vip-modal-title">VIP套餐</div>
|
||
</template>
|
||
<div v-loading="loading" class="vip-cards">
|
||
<div v-for="item in viplist" :key="item.id" class="vip-card">
|
||
<div class="relative! w-[100%] flex flex-col items-center">
|
||
<div class="vip-card-header basic">
|
||
<div class="vip-card-title">{{ item.name }}</div>
|
||
<!-- <div class="vip-card-subtitle">中小微企业</div> -->
|
||
</div>
|
||
<div class="vip-card-price">
|
||
<span class="price">¥{{ accDiv(item.payPrice || 0, 100) }}</span>
|
||
<span class="per">/1年</span>
|
||
</div>
|
||
<ul class="vip-card-features">
|
||
<li>1. {{ item.profile }}</li>
|
||
<li
|
||
>2. 佣金比例<span class="color-red">{{ item.brokerageRate }}</span
|
||
>%</li
|
||
>
|
||
</ul>
|
||
<div v-if="item.qrCodeUrl" class="vip-card-qrcode">
|
||
<el-icon class="absolute! right-[0px] top-[0px] cursor-pointer" @click="item.qrCodeUrl = ''"><Close /></el-icon>
|
||
<qrcode-vue :value="item.qrCodeUrl" :size="150" level="H" />
|
||
<div>请使用微信扫二维码</div>
|
||
</div>
|
||
</div>
|
||
<el-button class="vip-card-btn" :loading="item.btnloading" @click="pay(item)">立即开通</el-button>
|
||
</div>
|
||
</div>
|
||
</el-dialog>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { ref, watch, onMounted } from 'vue'
|
||
import { listVip, submitPayOrder, getPayStatus } from '~/api/pay/index'
|
||
import { accDiv } from '~/utils/utils'
|
||
import { Close } from '@element-plus/icons-vue'
|
||
import type { AppPayWalletPackageRespVO } from '~/api/pay/types'
|
||
// @ts-ignore
|
||
import QrcodeVue from 'qrcode.vue'
|
||
import useUserStore from '~/stores/user'
|
||
const userStore = useUserStore()
|
||
const props = defineProps({
|
||
modelValue: {
|
||
type: Boolean,
|
||
default: false,
|
||
},
|
||
})
|
||
const emit = defineEmits(['update:modelValue'])
|
||
|
||
const visible = ref(props.modelValue)
|
||
watch(
|
||
() => props.modelValue,
|
||
(val) => (visible.value = val)
|
||
)
|
||
watch(visible, (val) => emit('update:modelValue', val))
|
||
|
||
const viplist = ref<AppPayWalletPackageRespVO[]>([])
|
||
const loading = ref(false)
|
||
const init = async () => {
|
||
try {
|
||
loading.value = true
|
||
const res = await listVip()
|
||
viplist.value = res.data
|
||
} finally {
|
||
loading.value = false
|
||
console.log(viplist.value)
|
||
}
|
||
}
|
||
|
||
onMounted(() => {
|
||
init()
|
||
})
|
||
|
||
const orderId = ref(0)
|
||
const pay = async (row: AppPayWalletPackageRespVO) => {
|
||
if (userStore.userInfoRes.vipLevel === 1 && row.level === 1) return ElMessage.error('您已经是VIP了,无需重复开通')
|
||
if (userStore.userInfoRes.vipLevel === 2 && row.level === 1) return ElMessage.error('您已经是SVIP了,过期之后再开通VIP')
|
||
if (userStore.userInfoRes.vipLevel === 2 && row.level === 2) return ElMessage.error('您已经是SVIP了,无需重复开通')
|
||
if (row.qrCodeUrl) return ElMessage.error('支付二维码已生成,请勿重复生成')
|
||
viplist.value.forEach((item) => {
|
||
if (item.id !== row.id) {
|
||
item.qrCodeUrl = ''
|
||
}
|
||
})
|
||
try {
|
||
row.btnloading = true
|
||
const res = await submitPayOrder({
|
||
id: row.id,
|
||
memberId: userStore.userId, // 用户id
|
||
channelCode: 'wx_native',
|
||
})
|
||
if (res.code === 0) {
|
||
row.qrCodeUrl = res.data.displayContent
|
||
orderId.value = res.data.orderId
|
||
// 打开轮询任务
|
||
createQueryInterval(row)
|
||
}
|
||
} finally {
|
||
row.btnloading = false
|
||
}
|
||
}
|
||
|
||
/** 轮询查询任务 */
|
||
const interval = ref()
|
||
const createQueryInterval = (row: AppPayWalletPackageRespVO) => {
|
||
if (interval.value) {
|
||
return
|
||
}
|
||
interval.value = setInterval(async () => {
|
||
const data = await getPayStatus({ id: orderId.value })
|
||
// 已支付
|
||
if (data.data.status === 10) {
|
||
clearQueryInterval(row)
|
||
ElMessage.success('支付成功!')
|
||
}
|
||
// 已取消
|
||
if (data.data.status === 20) {
|
||
clearQueryInterval(row)
|
||
ElMessage.error('支付已关闭!')
|
||
}
|
||
}, 1000 * 2)
|
||
}
|
||
|
||
/** 清空查询任务 */
|
||
const clearQueryInterval = (row: AppPayWalletPackageRespVO) => {
|
||
// 清空各种弹窗
|
||
row.qrCodeUrl = ''
|
||
// 清空任务
|
||
clearInterval(interval.value)
|
||
interval.value = undefined
|
||
}
|
||
|
||
/** 关闭弹窗 */
|
||
const handleClose = () => {
|
||
visible.value = false
|
||
// 清空任务
|
||
clearInterval(interval.value)
|
||
interval.value = undefined
|
||
}
|
||
</script>
|
||
|
||
<style scoped>
|
||
.vip-modal-title {
|
||
text-align: center;
|
||
font-size: 20px;
|
||
font-weight: bold;
|
||
margin-bottom: 24px;
|
||
}
|
||
.vip-cards {
|
||
display: flex;
|
||
gap: 32px;
|
||
justify-content: center;
|
||
margin: 24px 0;
|
||
}
|
||
.vip-card {
|
||
background: #fff;
|
||
border-radius: 12px;
|
||
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.06);
|
||
padding: 24px 32px;
|
||
width: 290px;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
padding-bottom: 70px;
|
||
position: relative;
|
||
}
|
||
.vip-card-header {
|
||
width: 100%;
|
||
text-align: center;
|
||
padding-bottom: 12px;
|
||
border-radius: 8px 8px 0 0;
|
||
margin-bottom: 12px;
|
||
padding: 10px;
|
||
box-sizing: border-box;
|
||
}
|
||
.vip-card-header.basic {
|
||
background: linear-gradient(90deg, #f7b7a3, #e97c6a);
|
||
}
|
||
.vip-card-header.pro {
|
||
background: linear-gradient(90deg, #f7b7a3, #e97c6a);
|
||
}
|
||
.vip-card-title {
|
||
font-size: 20px;
|
||
font-weight: bold;
|
||
color: #fff;
|
||
}
|
||
.vip-card-subtitle {
|
||
font-size: 14px;
|
||
color: #fff;
|
||
}
|
||
.vip-card-price {
|
||
margin: 12px 0;
|
||
font-size: 28px;
|
||
color: #e74c3c;
|
||
font-weight: bold;
|
||
display: flex;
|
||
align-items: baseline;
|
||
gap: 8px;
|
||
}
|
||
.vip-card-price .origin {
|
||
font-size: 16px;
|
||
color: #bbb;
|
||
text-decoration: line-through;
|
||
margin-left: 4px;
|
||
}
|
||
.vip-card-price .per {
|
||
font-size: 16px;
|
||
color: #888;
|
||
margin-left: 4px;
|
||
}
|
||
.vip-card-features {
|
||
list-style: none;
|
||
padding: 0;
|
||
margin: 0 0 16px 0;
|
||
color: #444;
|
||
font-size: 15px;
|
||
}
|
||
.vip-card-features li {
|
||
margin-bottom: 6px;
|
||
}
|
||
.vip-card-features .highlight {
|
||
color: #e74c3c;
|
||
font-weight: bold;
|
||
}
|
||
.vip-card-btn {
|
||
width: 80%;
|
||
margin-top: 8px;
|
||
border-radius: 24px;
|
||
position: absolute;
|
||
bottom: 20px;
|
||
}
|
||
:deep(.vip-card-qrcode) {
|
||
position: absolute !important;
|
||
inset: 0 !important;
|
||
z-index: 1;
|
||
text-align: center;
|
||
background-color: #fff;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
:deep(.el-dialog__header) {
|
||
.el-dialog__close {
|
||
top: -10px !important;
|
||
}
|
||
}
|
||
</style>
|