Files
front-pc/components/kl-quick-menu/components/kl-vip.vue

254 lines
6.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<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>