2025-07-01 16:17:13 +08:00
|
|
|
|
<template>
|
2025-07-21 14:34:20 +08:00
|
|
|
|
<view class="payment-page">
|
|
|
|
|
|
<!-- 倒计时区域 -->
|
|
|
|
|
|
<view class="countdown-section">
|
|
|
|
|
|
<view class="countdown-icon">
|
|
|
|
|
|
<u-icon name="clock" size="22" color="#fff"></u-icon>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="countdown-text">待支付</view>
|
|
|
|
|
|
<view class="countdown-timer">
|
|
|
|
|
|
<text>剩余:</text>
|
|
|
|
|
|
<text class="time-value">{{ countdownTime }}</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<view class="scrollable-content">
|
|
|
|
|
|
<web-view :src="payUrl" style="flex: 1;"></web-view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 底部支付区域 -->
|
|
|
|
|
|
<view class="payment-footer">
|
|
|
|
|
|
<view class="action-buttons">
|
|
|
|
|
|
<view class="cancel-btn" @click="cancelRegistration">取消报名</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
2025-07-01 16:17:13 +08:00
|
|
|
|
</view>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script lang="ts" setup>
|
|
|
|
|
|
import { onLoad } from "@dcloudio/uni-app";
|
2025-07-21 14:34:20 +08:00
|
|
|
|
import { jzGetQkExpiredTime, jzXkCancelApi } from "@/api/base/server";
|
2025-07-01 16:17:13 +08:00
|
|
|
|
import { useUserStore } from "@/store/modules/user";
|
2025-07-21 14:34:20 +08:00
|
|
|
|
import { useDataStore } from "@/store/modules/data";
|
|
|
|
|
|
const { getCurXs, getUser, setWsCallback } = useUserStore();
|
|
|
|
|
|
const { getData } = useDataStore();
|
2025-07-01 16:17:13 +08:00
|
|
|
|
|
|
|
|
|
|
const payUrl = ref("");
|
2025-07-21 14:34:20 +08:00
|
|
|
|
setWsCallback((type: string, res: any) => {
|
2025-07-01 20:54:38 +08:00
|
|
|
|
console.log('收到WebSocket消息:', type, res.data);
|
|
|
|
|
|
// 将data从字符串转为对象
|
|
|
|
|
|
const dataObj = JSON.parse(res.data);
|
|
|
|
|
|
if (dataObj.action === 'pay') {
|
2025-07-01 16:17:13 +08:00
|
|
|
|
uni.showToast({
|
|
|
|
|
|
title: '支付成功',
|
|
|
|
|
|
icon: 'success',
|
2025-07-01 20:54:38 +08:00
|
|
|
|
});
|
2025-07-21 14:34:20 +08:00
|
|
|
|
setWsCallback((type: string, res: any) => {})
|
2025-07-01 16:17:13 +08:00
|
|
|
|
// 跳转到支付成功页面
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
uni.reLaunch({
|
|
|
|
|
|
url: "/pages/base/course-selection/payment-success",
|
|
|
|
|
|
});
|
|
|
|
|
|
}, 1000)
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
2025-07-21 14:34:20 +08:00
|
|
|
|
|
|
|
|
|
|
// 倒计时
|
|
|
|
|
|
const countdownTime = ref("1分20秒");
|
|
|
|
|
|
let timer: any = null;
|
|
|
|
|
|
let seconds = 1 * 60 + 20; // 1分20秒
|
|
|
|
|
|
|
|
|
|
|
|
// 开始倒计时
|
|
|
|
|
|
const startCountdown = () => {
|
|
|
|
|
|
timer = setInterval(() => {
|
|
|
|
|
|
seconds--;
|
|
|
|
|
|
if (seconds <= 0) {
|
|
|
|
|
|
clearInterval(timer);
|
|
|
|
|
|
uni.showModal({
|
|
|
|
|
|
title: "支付超时",
|
|
|
|
|
|
content: "支付已超时,请重新选课",
|
|
|
|
|
|
showCancel: false,
|
|
|
|
|
|
success: () => {
|
|
|
|
|
|
cancelRegistration();
|
|
|
|
|
|
},
|
|
|
|
|
|
});
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
const minutes = Math.floor(seconds / 60);
|
|
|
|
|
|
const remainSeconds = seconds % 60;
|
|
|
|
|
|
countdownTime.value = `${minutes}分${remainSeconds}秒`;
|
|
|
|
|
|
}, 1000);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 返回上一页
|
|
|
|
|
|
const goBack = () => {
|
|
|
|
|
|
uni.reLaunch({
|
|
|
|
|
|
url: getData.backUrl
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 取消报名
|
|
|
|
|
|
const cancelRegistration = () => {
|
|
|
|
|
|
uni.showModal({
|
|
|
|
|
|
title: "取消报名",
|
|
|
|
|
|
content: "确定要取消报名吗?",
|
|
|
|
|
|
success: async (res) => {
|
|
|
|
|
|
if (res.confirm) {
|
|
|
|
|
|
await jzXkCancelApi({
|
|
|
|
|
|
xsId: getData.xsId,
|
|
|
|
|
|
xkId: getData.xkId
|
|
|
|
|
|
});
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
title: "已取消报名",
|
|
|
|
|
|
icon: "success",
|
|
|
|
|
|
});
|
|
|
|
|
|
goBack();
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
onLoad(async (options: any) => {
|
2025-07-01 16:17:13 +08:00
|
|
|
|
if (options.payUrl) {
|
|
|
|
|
|
payUrl.value = decodeURIComponent(options.payUrl);
|
2025-07-21 14:34:20 +08:00
|
|
|
|
const res = await jzGetQkExpiredTime({ xsId: getCurXs.id} );
|
|
|
|
|
|
seconds = res.result;
|
|
|
|
|
|
startCountdown();
|
2025-07-01 16:17:13 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
uni.showToast({ title: '缺少支付地址', icon: 'none' })
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
uni.navigateBack()
|
|
|
|
|
|
}, 1000)
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
2025-07-01 17:22:38 +08:00
|
|
|
|
|
2025-07-01 20:54:38 +08:00
|
|
|
|
onBeforeUnmount(() => {
|
2025-07-21 14:34:20 +08:00
|
|
|
|
if (timer) {
|
|
|
|
|
|
clearInterval(timer);
|
|
|
|
|
|
}
|
2025-07-01 17:22:38 +08:00
|
|
|
|
});
|
2025-07-01 16:17:13 +08:00
|
|
|
|
</script>
|
|
|
|
|
|
|
2025-07-21 14:34:20 +08:00
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
|
|
.payment-page {
|
|
|
|
|
|
min-height: 100%;
|
|
|
|
|
|
background-color: #f5f7fa;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
height: 100%;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 可滚动内容区域样式
|
|
|
|
|
|
.scrollable-content {
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.countdown-section {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
padding: 15px;
|
|
|
|
|
|
background-color: #2879ff;
|
|
|
|
|
|
|
|
|
|
|
|
.countdown-icon {
|
|
|
|
|
|
margin-right: 10px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.countdown-text {
|
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
color: #fff;
|
|
|
|
|
|
margin-right: auto;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.countdown-timer {
|
|
|
|
|
|
font-size: 15px;
|
|
|
|
|
|
color: #fff;
|
|
|
|
|
|
|
|
|
|
|
|
.time-value {
|
|
|
|
|
|
color: #ff4d4f;
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.payment-footer {
|
|
|
|
|
|
position: sticky;
|
|
|
|
|
|
bottom: 0;
|
|
|
|
|
|
left: 0;
|
|
|
|
|
|
right: 0;
|
|
|
|
|
|
background-color: #fff;
|
|
|
|
|
|
padding: 15px;
|
|
|
|
|
|
box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.05);
|
|
|
|
|
|
|
|
|
|
|
|
.total-amount {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
margin-bottom: 15px;
|
|
|
|
|
|
font-size: 15px;
|
|
|
|
|
|
color: #333;
|
|
|
|
|
|
|
|
|
|
|
|
.amount-value {
|
|
|
|
|
|
color: #ff6b00;
|
|
|
|
|
|
font-size: 20px;
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.action-buttons {
|
|
|
|
|
|
.cancel-btn {
|
|
|
|
|
|
height: 44px;
|
|
|
|
|
|
line-height: 44px;
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
border-radius: 22px;
|
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
|
background-color: #fff;
|
|
|
|
|
|
color: #333;
|
|
|
|
|
|
border: 1px solid #ddd;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
</style>
|