mcwl-pc/app/components/Payment.vue

308 lines
9.4 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<script setup lang="ts">
import { RotateCcw, X } from "lucide-vue-next";
import { useMessage } from "naive-ui";
import { defineProps, onBeforeMount, onBeforeUnmount, ref } from "vue";
const props = defineProps({
info: {
type: Array,
default: () => [],
},
isMember: {
type: Object,
default: () => {},
},
});
const emit = defineEmits(["closePayment", "paymentSuccess"]);
const message = useMessage();
let pollingTimer: ReturnType<typeof setInterval> | undefined;
const currentNeedPayment = ref<number>(0);
// const isShowPayment = ref(false)
const userStore = useUserStore();
interface UserInfoType {
nickName: string;
avatar: string;
brief: string;
userId: number | string;
}
const userInfo = {
nickName: userStore.userInfo?.nickName ?? "",
avatar: userStore.userInfo?.avatar ?? "",
brief: userStore.userInfo?.brief ?? "",
userId: userStore.userInfo?.userId ?? "",
} as UserInfoType;
function onCloseModel() {
emit("closePayment");
}
function onPaymentSuccess() {
emit("paymentSuccess");
}
const qrUrl = ref("");
interface Member {
id: number;
title: string;
price: number;
originalPrice: number;
desc: string;
}
// 活动列表
const currentActivity = ref(null);
const activityList = ref<Member[]>([]);
async function getPromotionList() {
try {
const res = await request.post(`/promotion/myPromotionList`, {
pageNum: 1,
pageSize: 50,
});
if (res.code === 200) {
activityList.value = res.rows;
}
} catch (err) {
console.log(err);
}
}
getPromotionList();
// 支付
// 初始化获取支付二维码
// const paymentParams = ref({})
const paymentStatus = ref(1);
const paymentParams = ref({
amount: props.info[0].unitPrice,
productId: props.info[0].id,
promotionId: 0,
type: "member",
});
async function getQrCode() {
try {
const res = await request.post(`/ali/pay/doPay`, paymentParams.value);
if (res.code === 200) {
paymentStatus.value = 1;
qrUrl.value = res.data.url;
pollingTimer && clearTimeout(pollingTimer);
pollingTimer = setInterval(async () => {
try {
const res2 = await request.get(
`/order/queryTradeStatus?outTradeNo=${res.data.orderNo}`
);
if (res2.data === 2) {
paymentStatus.value = 2;
clearTimeout(pollingTimer);
message.success("支付成功!");
onPaymentSuccess();
emit("closePayment");
} else if (res2.data === 4) {
paymentStatus.value = 4;
clearTimeout(pollingTimer);
}
} catch (err) {
console.log("object", err);
}
}, 2000);
}
} catch (err) {
console.log(err);
}
}
// 切换活动
async function handleActivityChange(value: number) {
paymentParams.value.promotionId = value;
const res1 = await request.get(
`/member/calculatePayment?promotionId=${value}&memberLevelId=${paymentParams.value.productId}`
);
if (res1.code === 200) {
paymentParams.value.amount = res1.data;
getQrCode();
}
}
// 切换pay Card
async function changeCurrentNeedPayment(index: number) {
currentNeedPayment.value = index;
paymentParams.value.productId = props.info[index].id;
const res1 = await request.get(
`/member/calculatePayment?promotionId=${paymentParams.value.promotionId}&memberLevelId=${paymentParams.value.productId}`
);
if (res1.code === 200) {
paymentParams.value.amount = res1.data;
getQrCode();
}
}
// 二维码是否过去
const isVisible = ref(true);
onBeforeMount(() => {
getQrCode();
});
defineExpose({
isVisible,
});
onBeforeUnmount(() => {
clearInterval(pollingTimer);
});
</script>
<template>
<n-modal
v-model:show="isVisible"
:preset="null"
:mask-closable="false"
transform-origin="center"
class="custom-modal"
>
<div class="bg-white rounded-xl w-200">
<div
class="p-4 flex justify-between rounded-t-xl bg-gradient-to-r from-[#fcf2da] to-[#f9db9f]"
>
<div class="flex items-center">
<div>
<img :src="userInfo.avatar" class="w-14 h-14 rounded-full mr-4" />
</div>
<div class="flex flex-col">
<div class="text-[#814600] text-xl">
{{ userInfo.nickName }}
</div>
<div class="text-[#6a6a6a] text-xs mt-1">
{{
props.isMember.result === "1"
? `会员到期时间: ${props.isMember.endDate}`
: "您还不是魔创未来的会员"
}}
</div>
</div>
</div>
<div @click="onCloseModel">
<component :is="X" class="h-[18px] w-[18px] text-[#61666d] cursor-pointer" />
</div>
</div>
<div class="grid grid-cols-4 gap-1 mt-4 px-6">
<div
v-for="(item, index) in info"
:key="item"
:style="[
currentNeedPayment === index
? {
background: 'linear-gradient(90deg, #fffaf1, #ffeccf)',
border: '1px solid #f7b252',
}
: {},
]"
class="select-none h-44 border-1 border-solid border-[#e9e9e9] rounded-lg bg-[#f9f9f9] flex justify-between items-center flex-col p-4 box-border cursor-pointer"
@click="changeCurrentNeedPayment(index)"
>
<!-- bg-gradient-to-b from-[#fdf0dd] to-[#fef8ef] -->
<!-- 1px solid #f7b252; -->
<div class="text-[#814600] card-item">
{{ item.memberName }}
</div>
<div class="card-item">
<span class="text-[#814600] text-[20px] mr-2">¥</span>
<span class="text-[#814600] text-[36px] mr-2">{{ item.unitPrice }}</span>
<span class="text-gray-400 text-[20px] line-through">{{
item.originalPrice
}}</span>
</div>
<div class="card-item text-[#814600] w-7/10 text-center text-[12px]">
{{ item.subscriptionPeriod }}
</div>
</div>
</div>
<div class="flex items-center my-4">
<div class="w-[50px] text-right mr-2">活动:</div>
<n-select
v-model:value="currentActivity"
placeholder="请选择活动"
class="w-[200px]"
label-field="activityName"
value-field="id"
:options="activityList"
@change="handleActivityChange"
/>
</div>
<!-- <div v-for="(item, index) in activityList" :key="index">
{{ item.activityName }}
</div> -->
<div class="mt-4 px-6">
<div class="flex border-collapse">
<div class="member-item bg-[#fef9f8]">基础版VIP</div>
<div class="member-item">每月15000点算力</div>
<div class="member-item">20G存储空间</div>
<div class="member-item">每月800次生图</div>
<div class="member-item">2个生图任务并行</div>
<div class="member-item">--</div>
</div>
<div class="flex border-collapse">
<div class="member-item bg-[#fef9f8]">专业版</div>
<div class="member-item">每月35000点算力</div>
<div class="member-item">50G存储空间</div>
<div class="member-item">每月5000次生图</div>
<div class="member-item">3个生图任务并行</div>
<div class="member-item">可训练XL模型</div>
</div>
</div>
<div class="px-6 mt-1 text-[#9d8c75] text-[12px]">
会员每月算力和加速特权按下月下发, 有效期31天, 到期重置
</div>
<div class="flex justify-center items-center my-4">
<div class="w-30 h-30 flex justify-center items-center relative">
<n-qr-code :value="qrUrl" :size="90" style="padding: 0" />
<div
v-if="paymentStatus === 4"
class="absolute top-0 left-0 w-full h-full flex cursor-pointer flex-col justify-center items-center bg-opacity-50 bg-black text-white"
@click="getQrCode"
>
请点击刷新<RotateCcw />
</div>
</div>
<div class="flex justify-center ml-2 flex-col pb-[14px]">
<div class="flex items-baseline">
<div class="text-[#222] font-medium mr-1">支付</div>
<div class="text-[#814600] mr-1">
<span class="text-[16px] mr-1">¥</span>
<span class="text-[40px]">{{ paymentParams.amount }}</span>
</div>
<!-- <div class="px-2 bg-gradient-to-r from-[#ffa700] to-[#ff006b] text-[#814600] text-white rounded-[4px] ml-1 text-[12px">
已减¥11
</div> -->
</div>
<div class="flex items-center mb-1">
<img src="@/assets/img/alipay.png" class="mr-1" /> 请扫码完成支付
</div>
<div class="text-[12px]">
<span class="text-[#999]"> 开通即代表同意 </span>
<span class="text-[#814600]"> 《魔创未来会员协议》 </span>
</div>
</div>
</div>
<div class="bg-[#fefaee] text-center text-[#AF7F1A] text-[12px] py-1 rounded-b-lg">
-*/12
</div>
</div>
</n-modal>
</template>
<style lang="scss" scoped>
.member-item {
display: flex;
justify-content: center;
align-items: center;
width: 16.66%;
height: 40px;
border: 1px solid #f0f0f0;
font-size: 12px;
font-weight: 400;
margin-right: -1px;
margin-bottom: -1px;
}
</style>