308 lines
9.4 KiB
Vue
308 lines
9.4 KiB
Vue
<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>
|